(轉(zhuǎn)載)Android WebView 開發(fā)詳解(二)

轉(zhuǎn)載請注明出處 http://blog.csdn.net/typename/article/details/39495409 powered by miechal zhao

概覽:

Android WebView 做為承載網(wǎng)頁的載體控件曹仗,他在網(wǎng)頁顯示的過程中會產(chǎn)生一些事件,并回調(diào)給我們的應(yīng)用程序蠕搜,以便我們在網(wǎng)頁加載過程中做應(yīng)用程序想處理的事情怎茫。比如說客戶端需要顯示網(wǎng)頁加載的進度、網(wǎng)頁加載發(fā)生錯誤等等事件妓灌。 WebView提供兩個事件回調(diào)類給應(yīng)用層轨蛤,分別為WebViewClient,WebChromeClient開發(fā)者可以繼承這兩個類,接手相應(yīng)事件處理虫埂。WebViewClient 主要提供網(wǎng)頁加載各個階段的通知祥山,比如網(wǎng)頁開始加載onPageStarted,網(wǎng)頁結(jié)束加載onPageFinished等告丢;WebChromeClient主要提供網(wǎng)頁加載過程中提供的數(shù)據(jù)內(nèi)容枪蘑,比如返回網(wǎng)頁的title,favicon等损谦。
1.WebViewClient的基本使用
創(chuàng)建WebViewClient實例并設(shè)置到WebView對象中,具體代碼參考如下:

class MyAndroidWebViewClient extends WebViewClient {  
     @Override  
    public void onPageStarted(WebView view, String url, Bitmap favicon) {  
       // TODO  
    }  
  
    @Override  
    public void onPageFinished(WebView view, String url) {  
      // TODO  
    }  
}  
webview.setWebViewClient(new MyAndroidWebViewClient ());  

2.WebViewClient API詳解
1)網(wǎng)頁加載時機部分

public boolean shouldOverrideUrlLoading(WebView view, String url)  

當(dāng)加載的網(wǎng)頁需要重定向的時候就會回調(diào)這個函數(shù)告知我們應(yīng)用程序是否需要接管控制網(wǎng)頁加載岳颇,如果應(yīng)用程序接管照捡,并且return true意味著主程序接管網(wǎng)頁加載,如果返回false讓webview自己處理话侧。

參數(shù)說明:
@param view 接收WebViewClient的那個實例栗精,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview瞻鹏。
@param url 即將要被加載的url
@return true 當(dāng)前應(yīng)用程序要自己處理這個url悲立, 返回false則不處理。

Tips
(1) 當(dāng)請求的方式是"POST"方式時這個回調(diào)是不會通知的新博。
(2) 當(dāng)我們訪問的地址需要我們應(yīng)用程序自己處理的時候薪夕,可以在這里截獲,比如我們發(fā)現(xiàn)跳轉(zhuǎn)到的是一個market的鏈接赫悄,那么我們可以直接跳轉(zhuǎn)到應(yīng)用市場原献,或者其他app。

public void onPageStarted(WebView view, String url, Bitmap favicon)  

當(dāng)內(nèi)核開始加載訪問的url時埂淮,會通知應(yīng)用程序姑隅,對每個main frame這個函數(shù)只會被調(diào)用一次,頁面包含iframe 或者framesets 不會另外調(diào)用一次onPageStarted倔撞,當(dāng)網(wǎng)頁內(nèi)內(nèi)嵌的frame 發(fā)生改變時也不會調(diào)用onPageStarted讲仰。

參數(shù)說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())痪蝇,即是這個webview鄙陡。
@param url 即將要被加載的url
@param favicon 如果這個favicon已經(jīng)存儲在本地數(shù)據(jù)庫中,則會返回這個網(wǎng)頁的favicon霹俺,否則返回為null柔吼。

Tips:
(1) iframe 可能不少人不知道什么含義,這里我解釋下丙唧,iframe 我們加載的一張愈魏,下面有很多鏈接,我們隨便點擊一個鏈接是即當(dāng)前host的一個iframe.
(2) 有個問題可能是開發(fā)者困惑的想际,onPageStarted和shouldOverrideUrlLoading 在網(wǎng)頁加載過程中這兩個函數(shù)到底哪個先被調(diào)用培漏。
當(dāng)我們通過loadUrl的方式重新加載一個網(wǎng)址時候,這時候會先調(diào)用onPageStarted再調(diào)用shouldOverrideUrlLoading胡本,當(dāng)我們在打開的這個網(wǎng)址點擊一個link牌柄,這時候會先調(diào)用shouldOverrideUrlLoading 再調(diào)用onPageStarted。不過shouldOverrideUrlLoading不一定每次都被調(diào)用侧甫,只有需要的時候才會被調(diào)用珊佣。

public void onPageFinished(WebView view, String url)  

當(dāng)內(nèi)核加載完當(dāng)前頁面時會通知我們的應(yīng)用程序蹋宦,這個函數(shù)只有在main frame情況下才會被調(diào)用,當(dāng)調(diào)用這個函數(shù)之后咒锻,渲染的圖片不會被更新冷冗,如果需要獲得新圖片的通知可以使用@link WebView.PictureListener#onNewPicture。

參數(shù)說明:
@param view 接收WebViewClient的那個實例惑艇,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())蒿辙,即是這個webview。
@param url 即將要被加載的url

public void onLoadResource(WebView view, String url)  

通知應(yīng)用程序WebView即將加載url 制定的資源

參數(shù)說明:
@param view 接收WebViewClient的那個實例滨巴,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())思灌,即是這個webview。
@param url 即將加載的url 資源

public WebResourceResponse shouldInterceptRequest(WebView view,  
            String url)  

通知應(yīng)用程序內(nèi)核即將加載url制定的資源恭取,應(yīng)用程序可以返回本地的資源提供給內(nèi)核泰偿,若本地處理返回數(shù)據(jù),內(nèi)核不從網(wǎng)絡(luò)上獲取數(shù)據(jù)秽荤。

參數(shù)說明:
@param view 接收WebViewClient的那個實例甜奄,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview窃款。
@param url raw url 制定的資源
@return 返回WebResourceResponse包含數(shù)據(jù)對象,或者返回null

Tips
這個回調(diào)并不一定在UI線程執(zhí)行牍氛,所以我們需要注意在這里操作View或者私有數(shù)據(jù)相關(guān)的動作晨继。
如果我們需要改變網(wǎng)頁的背景,或者需要實現(xiàn)網(wǎng)頁頁面顏色定制化的需求搬俊,可以在這個回調(diào)時機處理紊扬。

public void onReceivedError(WebView view, int errorCode,  
            String description, String failingUrl)  

當(dāng)瀏覽器訪問制定的網(wǎng)址發(fā)生錯誤時會通知我們應(yīng)用程序,比如網(wǎng)絡(luò)錯誤唉擂。

參數(shù)說明:
@param view 接收WebViewClient的那個實例餐屎,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview玩祟。
@param errorCode 錯誤號可以在WebViewClient.ERROR_* 里面找到對應(yīng)的錯誤名稱腹缩。
@param description 描述錯誤的信息
@param failingUrl 當(dāng)前訪問失敗的url,注意并不一定是我們主url

Tips
在onReceiveError我們可以自定義網(wǎng)頁的錯誤頁面空扎。

public void onFormResubmission(WebView view, Message dontResend,  
            Message resend)  

如果瀏覽器需要重新發(fā)送POST請求谭胚,可以通過這個時機來處理饵史。默認是不重新發(fā)送數(shù)據(jù)。
參數(shù)說明:
@param view 接收WebViewClient的那個實例,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())橙困,即是這個webview。
@param dontResent 當(dāng)瀏覽器不需要重新發(fā)送數(shù)據(jù)時毛萌,可以使用這個參數(shù)。
@param resent 當(dāng)瀏覽器需要重新發(fā)送數(shù)據(jù)時脆粥, 可以使用這個參數(shù)。

public void doUpdateVisitedHistory(WebView view, String url,  
            boolean isReload)  

通知應(yīng)用程序可以將當(dāng)前的url存儲在數(shù)據(jù)庫中影涉,意味著當(dāng)前的訪問url已經(jīng)生效并被記錄在內(nèi)核當(dāng)中冠绢。這個函數(shù)在網(wǎng)頁加載過程中只會被調(diào)用一次。注意網(wǎng)頁前進后退并不會回調(diào)這個函數(shù)常潮。
參數(shù)說明:
@param view 接收WebViewClient的那個實例弟胀,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview喊式。
@param url 當(dāng)前正在訪問的url
@ param isReload 如果是true 這個是正在被reload的url

public void onReceivedSslError(WebView view, SslErrorHandler handler,  
            SslError error)  

當(dāng)網(wǎng)頁加載資源過程中發(fā)現(xiàn)SSL錯誤會調(diào)用此方法孵户。我們應(yīng)用程序必須做出響應(yīng),是取消請求handler.cancel(),還是繼續(xù)請求handler.proceed();內(nèi)核的默認行為是handler.cancel();

參數(shù)說明:
@param view 接收WebViewClient的那個實例岔留,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())夏哭,即是這個webview。
@param handler 處理用戶請求的對象献联。
@param error SSL錯誤對象

Tips
內(nèi)核會記住本次選擇竖配,如果下次還有相同的錯誤,內(nèi)核會直接執(zhí)行之前選擇的結(jié)果里逆。

public void onReceivedHttpAuthRequest(WebView view,  
            HttpAuthHandler handler, String host, String realm)  

通知應(yīng)用程序WebView接收到了一個Http auth的請求进胯,應(yīng)用程序可以使用supplied 設(shè)置webview的響應(yīng)請求。默認行為是cancel 本次請求原押。
參數(shù)說明:
@param view 接收WebViewClient的那個實例胁镐,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview诸衔。
@param handler 用來響應(yīng)WebView請求的對象
@param host 請求認證的host
@param realm 認真請求所在的域

public boolean shouldOverrideKeyEvent(WebView view, KeyEvent event)   

提供應(yīng)用程序同步一個處理按鍵事件的機會盯漂,菜單快捷鍵需要被過濾掉。如果返回true笨农,webview不處理該事件就缆,如果返回false, webview會一直處理這個事件谒亦,因此在view 鏈上沒有一個父類可以響應(yīng)到這個事件竭宰。默認行為是return false;
參數(shù)說明:
@param view 接收WebViewClient的那個實例诊霹,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())羞延,即是這個webview。
@param event 鍵盤事件名
@return 如果返回true,應(yīng)用程序處理該時間脾还,返回false 交有webview處理伴箩。

public void onScaleChanged(WebView view, float oldScale, float newScale)  

通知應(yīng)用程序webview 要被scale。應(yīng)用程序可以處理改事件鄙漏,比如調(diào)整適配屏幕嗤谚。

public void onReceivedLoginRequest(WebView view, String realm,  
            String account, String args)  

通知應(yīng)用程序有個自動登錄的帳號過程
參數(shù)說明:
@param view 請求登陸的webview
@param realm 賬戶的域名棺蛛,用來查找賬戶。
@param account 一個可選的賬戶巩步,如果是null 需要和本地的賬戶進行check旁赊, 如果是一個可用的賬戶,則提供登錄椅野。
@param args 驗證制定參數(shù)的登錄用戶

3.WebChromeClient 基本使用

  1. WebChromeClient API詳解
    創(chuàng)建WebChromeClient實例并設(shè)置到WebView對象中终畅,具體代碼參考如下:

    public void onProgressChanged(WebView view, int newProgress)

通知應(yīng)用程序當(dāng)前網(wǎng)頁加載的進度。
參數(shù)說明:
@param view 接收WebViewClient的那個實例竟闪,前面看到webView.setWebViewClient(new MyAndroidWebViewClient())离福,即是這個webview。

public void onReceivedTitle(WebView view, String title)  

當(dāng)document 的title變化時炼蛤,會通知應(yīng)用程序
參數(shù)說明:
@param view 接收WebViewClient的那個實例妖爷,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview理朋。
@param title document新的title
Tips
這個函數(shù)調(diào)用時機不確定絮识,有可能很早,有可能很晚嗽上,取決于網(wǎng)頁把title設(shè)置在什么位置次舌,大多數(shù)網(wǎng)頁一般把title設(shè)置到頁面的前面,因此很多情況會比較早回調(diào)到這個函數(shù)炸裆。

public void onReceivedIcon(WebView view, Bitmap icon)  

當(dāng)前頁面有個新的favicon時候垃它,會回調(diào)這個函數(shù)。
參數(shù)說明:
@param view 接收WebViewClient的那個實例烹看,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview洛史。
@param icon 當(dāng)前頁面的favicon

public void onReceivedTouchIconUrl(WebView view, String url,  
            boolean precomposed)  

通知應(yīng)用程序 apple-touch-icon的 url
參數(shù)說明:
@param view 接收WebViewClient的那個實例惯殊,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview也殖。
@param url apple-touch-icon 的服務(wù)端地址
@param precomposed 如果precomposed 是true 則touch-icon是預(yù)先創(chuàng)建的
Tips
如果應(yīng)用程序需要這個icon的話土思, 可以通過這個url獲取得到 icon。

public void onShowCustomView(View view, CustomViewCallback callback)  

通知應(yīng)用程序webview需要顯示一個custom view忆嗜,主要是用在視頻全屏HTML5Video support己儒。
參數(shù)說明:
@param view 即將要顯示的view
@param callback 當(dāng)view 需要dismiss 則使用這個對象進行回調(diào)通知。

public void onHideCustomView()  

退出視頻通知

public boolean onCreateWindow(WebView view, boolean isDialog,  
            boolean isUserGesture, Message resultMsg)  

請求創(chuàng)建一個新的窗口捆毫,如果我們應(yīng)用程序接管這個請求闪湾,必須返回true,并且創(chuàng)建一個新的webview來承載主窗口绩卤。
如果應(yīng)用程序不處理途样,則需要返回false江醇,默認行為和返回false表現(xiàn)一樣。
參數(shù)說明:
@param view 請求創(chuàng)建新窗口的webview
@param isUserGesture 如果是true何暇,則說明是來自用戶收拾操作行為陶夜,比如用戶點擊鏈接
@param isDialog true 請求創(chuàng)建的新窗口必須是個dialog,而不是全屏的窗口裆站。
@param resultMsg 當(dāng)webview創(chuàng)建時需要發(fā)送一個消息条辟。WebView.WebViewTransport.setWebView(WebView)
Tips 具體例子如下:

  private void createWindow(final Message msg) {  
WebView.WebViewTransport transport = (WebView.WebViewTransport) msg.obj;  
final Tab newTab = mWebViewController.openTab(null, Tab.this, true,  
        true);  
transport.setWebView(newTab.getWebView());  
msg.sendToTarget();  
  }  

public void onRequestFocus(WebView view)  

webview請求得到focus,發(fā)生這個主要是當(dāng)前webview不是前臺狀態(tài)宏胯,是后臺webview羽嫡。

public void onCloseWindow(WebView window)  

通知應(yīng)用程序從關(guān)閉傳遞過來的webview并從view tree中remove。

public boolean onJsAlert(WebView view, String url, String message,  
            JsResult result)  

通知應(yīng)用程序顯示javascript alert對話框胳嘲,如果應(yīng)用程序返回true內(nèi)核認為應(yīng)用程序處理這個消息厂僧,返回false,內(nèi)核自己處理了牛。
參數(shù)說明:
@param view 接收WebViewClient的那個實例颜屠,前面看到webView.setWebViewClient(new MyAndroidWebViewClient()),即是這個webview鹰祸。
@param url 當(dāng)前請求彈出javascript 對話框webview 加載的url地址甫窟。
@param message 彈出的內(nèi)容信息
@result 用來響應(yīng)用戶的處理。

Tips
如果我們應(yīng)用接管處理蛙婴, 則必須給出result的結(jié)果粗井,result.cancel,result.comfirm必須調(diào)用其中之后,否則內(nèi)核會hang住街图。

public boolean onJsConfirm(WebView view, String url, String message,  
            JsResult result)  

通知應(yīng)用程序提供confirm 對話框浇衬。
參數(shù)說明同上onJsAlert

public boolean onJsPrompt(WebView view, String url, String message,  
            String defaultValue, JsPromptResult result)  

通知應(yīng)用程序顯示一個prompt對話框。
Tips
必須調(diào)用result.confirm 方法如果應(yīng)用程序接管這個方法餐济。

public boolean onJsBeforeUnload(WebView view, String url, String message,  
            JsResult result)  

通知應(yīng)用程序顯示一個對話框耘擂,讓用戶選擇是否離開當(dāng)前頁面,這個回調(diào)是javascript中的onbeforeunload事件絮姆,如果客戶端返回true醉冤,內(nèi)核會認為客戶端提供對話框。默認行為是return false篙悯。
參數(shù)說明和之前介紹的onJsAlert()相同蚁阳。

public void onExceededDatabaseQuota(String url, String databaseIdentifier,  
            long quota, long estimatedDatabaseSize, long totalQuota,  
            WebStorage.QuotaUpdater quotaUpdater)  

通知應(yīng)用程序webview內(nèi)核web sql 數(shù)據(jù)庫超出配額,請求是否擴大數(shù)據(jù)庫磁盤配額鸽照。默認行為是不會增加數(shù)據(jù)庫配額螺捐。
參數(shù)說明:

@param url 觸發(fā)這個數(shù)據(jù)庫配額的url地址
@param databaseIdentifier 指示出現(xiàn)數(shù)據(jù)庫超過配額的標(biāo)識。
@param quota 原始數(shù)據(jù)庫配額的大小,是字節(jié)單位bytes
@param estimatedDatabaseSize 到達底線的數(shù)據(jù)大小 bytes
@param totalQuota 總的數(shù)據(jù)庫配額大小 bytes
@param quotaUpdater 更新數(shù)據(jù)庫配額的對象归粉,可以使用 quotaUpdater.updateQuota(newQuota);配置新的數(shù)據(jù)庫配額大小椿疗。

public void onReachedMaxAppCacheSize(long requiredStorage, long quota,  
            WebStorage.QuotaUpdater quotaUpdater)  

通知應(yīng)用程序內(nèi)核已經(jīng)到達最大的appcache。
appcache是HTML5針對offline的一個數(shù)據(jù)處理標(biāo)準(zhǔn)糠悼。

public void onGeolocationPermissionsShowPrompt(String origin,  
            GeolocationPermissions.Callback callback)  

當(dāng)前頁面請求是否允許進行定位届榄。

GeolocationPermissions.Callback的使用

public void invoke(String origin, boolean allow, boolean retain);

參數(shù)說明:
@param origin 權(quán)限設(shè)置的源地址
@param allow 是否允許定位
@retain 當(dāng)前的選擇是否讓內(nèi)核記住。

public void onGeolocationPermissionsHidePrompt()  

public void openFileChooser(ValueCallback<Uri> uploadFile, String acceptType, String capture)  

這個回調(diào)是私有回調(diào)倔喂, 當(dāng)頁面需要請求打開系統(tǒng)的文件選擇器铝条,則會回調(diào)這個方法,比如我們需要上傳圖片席噩,請求拍照班缰,郵件的附件上傳等等操作。
如果不實現(xiàn)這個私有API悼枢,則上面的請求都將不會執(zhí)行埠忘。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市馒索,隨后出現(xiàn)的幾起案子莹妒,更是在濱河造成了極大的恐慌,老刑警劉巖绰上,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件旨怠,死亡現(xiàn)場離奇詭異,居然都是意外死亡蜈块,警方通過查閱死者的電腦和手機鉴腻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來百揭,“玉大人爽哎,你說我怎么就攤上這事∑饕唬” “怎么了倦青?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長盹舞。 經(jīng)常有香客問我,道長隘庄,這世上最難降的妖魔是什么踢步? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮丑掺,結(jié)果婚禮上获印,老公的妹妹穿的比我還像新娘。我一直安慰自己街州,他們只是感情好兼丰,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布玻孟。 她就那樣靜靜地躺著,像睡著了一般鳍征。 火紅的嫁衣襯著肌膚如雪黍翎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天艳丛,我揣著相機與錄音匣掸,去河邊找鬼。 笑死氮双,一個胖子當(dāng)著我的面吹牛碰酝,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播戴差,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼送爸,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了暖释?” 一聲冷哼從身側(cè)響起袭厂,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎饭入,沒想到半個月后嵌器,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡谐丢,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年爽航,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片乾忱。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡讥珍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窄瘟,到底是詐尸還是另有隱情衷佃,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布蹄葱,位于F島的核電站氏义,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏图云。R本人自食惡果不足惜惯悠,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竣况。 院中可真熱鬧克婶,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至筋岛,卻和暖如春娶视,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泉蝌。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工歇万, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人勋陪。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓贪磺,卻偏偏與公主長得像,于是被迫代替她去往敵國和親诅愚。 傳聞我的和親對象是個殘疾皇子寒锚,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容