Carson帶你學(xué)Android:BroadcastReceiver史上最全面解析

前言

  • BroadcastReceiver(廣播接收器),屬于 Android 四大組件之一
  • Android 開(kāi)發(fā)中,BroadcastReceiver 的應(yīng)用場(chǎng)景非常多
  • 今天,我將詳細(xì)講解關(guān)于BroadcastReceiver的一切相關(guān)知識(shí)

目錄

示意圖

1. 定義

即 廣播,是一個(gè)全局的監(jiān)聽(tīng)器,屬于Android四大組件之一

Android 廣播分為兩個(gè)角色:廣播發(fā)送者、廣播接收者


2. 作用

監(jiān)聽(tīng) / 接收 應(yīng)用 App 發(fā)出的廣播消息,并 做出響應(yīng)


3. 應(yīng)用場(chǎng)景

  • Android不同組件間的通信(含 :應(yīng)用內(nèi) / 不同應(yīng)用之間)
  • 多線程通信
  • Android 系統(tǒng)在特定情況下的通信

如:電話呼入時(shí)、網(wǎng)絡(luò)可用時(shí)


4. 實(shí)現(xiàn)原理

4.1 采用的模型

  • Android中的廣播使用了設(shè)計(jì)模式中的觀察者模式:基于消息的發(fā)布 / 訂閱事件模型

因此,Android將廣播的發(fā)送者 和 接收者 解耦,使得系統(tǒng)方便集成,更易擴(kuò)展

4.2 模型講解

  • 模型中有3個(gè)角色:

    1. 消息訂閱者(廣播接收者)
    2. 消息發(fā)布者(廣播發(fā)布者)
    3. 消息中心(AMS,即Activity Manager Service
  • 示意圖 & 原理如下

示意圖

5. 使用流程

  • 使用流程如下:
示意圖
  • 下面,我將一步步介紹如何使用BroadcastReceiver

即上圖中的 開(kāi)發(fā)者手動(dòng)完成部分

5.1 自定義廣播接收者BroadcastReceiver

  • 繼承BroadcastReceivre基類(lèi)
  • 必須復(fù)寫(xiě)抽象方法onReceive()方法
  1. 廣播接收器接收到相應(yīng)廣播后,會(huì)自動(dòng)回調(diào) onReceive() 方法
  2. 一般情況下,onReceive方法會(huì)涉及 與 其他組件之間的交互,如發(fā)送Notification、啟動(dòng)Service
  3. 默認(rèn)情況下,廣播接收器運(yùn)行在 UI 線程,因此,onReceive()方法不能執(zhí)行耗時(shí)操作,否則將導(dǎo)致ANR
  • 代碼范例
    mBroadcastReceiver.java
// 繼承BroadcastReceivre基類(lèi)
public class mBroadcastReceiver extends BroadcastReceiver {

  // 復(fù)寫(xiě)onReceive()方法
  // 接收到廣播后,則自動(dòng)調(diào)用該方法
  @Override
  public void onReceive(Context context, Intent intent) {
   //寫(xiě)入接收廣播后的操作
    }
}

5.2 廣播接收器注冊(cè)

注冊(cè)的方式分為兩種:靜態(tài)注冊(cè)、動(dòng)態(tài)注冊(cè)

5.2.1 靜態(tài)注冊(cè)

  • 注冊(cè)方式:在AndroidManifest.xml里通過(guò)<receive>標(biāo)簽聲明
  • 屬性說(shuō)明:
<receiver 
    android:enabled=["true" | "false"]
//此broadcastReceiver能否接收其他App的發(fā)出的廣播
//默認(rèn)值是由receiver中有無(wú)intent-filter決定的:如果有intent-filter,默認(rèn)值為true,否則為false
    android:exported=["true" | "false"]
    android:icon="drawable resource"
    android:label="string resource"
//繼承BroadcastReceiver子類(lèi)的類(lèi)名
    android:name=".mBroadcastReceiver"
//具有相應(yīng)權(quán)限的廣播發(fā)送者發(fā)送的廣播才能被此BroadcastReceiver所接收;
    android:permission="string"
//BroadcastReceiver運(yùn)行所處的進(jìn)程
//默認(rèn)為app的進(jìn)程,可以指定獨(dú)立的進(jìn)程
//注:Android四大基本組件都可以通過(guò)此屬性指定自己的獨(dú)立進(jìn)程
    android:process="string" >

//用于指定此廣播接收器將接收的廣播類(lèi)型
//本示例中給出的是用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
 <intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>
  • 注冊(cè)示例
<receiver 
    //此廣播接收者類(lèi)是mBroadcastReceiver
    android:name=".mBroadcastReceiver" >
    //用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
    <intent-filter>
        <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
    </intent-filter>
</receiver>

當(dāng)此 App首次啟動(dòng)時(shí),系統(tǒng)會(huì)自動(dòng)實(shí)例化mBroadcastReceiver類(lèi),并注冊(cè)到系統(tǒng)中。

5.2.2 動(dòng)態(tài)注冊(cè)

  • 注冊(cè)方式:在代碼中調(diào)用Context.registerReceiver()方法

  • 具體代碼如下:

// 選擇在Activity生命周期方法中的onResume()中注冊(cè)
@Override
  protected void onResume(){
      super.onResume();

    // 1. 實(shí)例化BroadcastReceiver子類(lèi) &  IntentFilter
     mBroadcastReceiver mBroadcastReceiver = new mBroadcastReceiver();
     IntentFilter intentFilter = new IntentFilter();

    // 2. 設(shè)置接收廣播的類(lèi)型
    intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

    // 3. 動(dòng)態(tài)注冊(cè):調(diào)用Context的registerReceiver()方法
     registerReceiver(mBroadcastReceiver, intentFilter);
 }


// 注冊(cè)廣播后,要在相應(yīng)位置記得銷(xiāo)毀廣播
// 即在onPause() 中unregisterReceiver(mBroadcastReceiver)
// 當(dāng)此Activity實(shí)例化時(shí),會(huì)動(dòng)態(tài)將MyBroadcastReceiver注冊(cè)到系統(tǒng)中
// 當(dāng)此Activity銷(xiāo)毀時(shí),動(dòng)態(tài)注冊(cè)的MyBroadcastReceiver將不再接收到相應(yīng)的廣播。
 @Override
 protected void onPause() {
     super.onPause();
      //銷(xiāo)毀在onResume()方法中的廣播
     unregisterReceiver(mBroadcastReceiver);
     }
}

特別注意

  • 動(dòng)態(tài)廣播最好在ActivityonResume()注冊(cè)、onPause()注銷(xiāo)。
  • 原因:
    1. 對(duì)于動(dòng)態(tài)廣播,有注冊(cè)就必然得有注銷(xiāo),否則會(huì)導(dǎo)致內(nèi)存泄露

重復(fù)注冊(cè)、重復(fù)注銷(xiāo)也不允許

  1. Activity生命周期如下:
Activity生命周期

Activity生命周期的方法是成對(duì)出現(xiàn)的:

  • onCreate() & onDestory()
  • onStart() & onStop()
  • onResume() & onPause()

在onResume()注冊(cè)、onPause()注銷(xiāo)是因?yàn)閛nPause()在App死亡前一定會(huì)被執(zhí)行,從而保證廣播在App死亡前一定會(huì)被注銷(xiāo),從而防止內(nèi)存泄露。

  1. 不在onCreate() & onDestory() 或 onStart() & onStop()注冊(cè)、注銷(xiāo)是因?yàn)椋?br> 當(dāng)系統(tǒng)因?yàn)閮?nèi)存不足(優(yōu)先級(jí)更高的應(yīng)用需要內(nèi)存,請(qǐng)看上圖紅框)要回收Activity占用的資源時(shí),Activity在執(zhí)行完onPause()方法后就會(huì)被銷(xiāo)毀,有些生命周期方法onStop(),onDestory()就不會(huì)執(zhí)行。當(dāng)再回到此Activity時(shí),是從onCreate方法開(kāi)始執(zhí)行。
  2. 假設(shè)我們將廣播的注銷(xiāo)放在onStop(),onDestory()方法里的話,有可能在Activity被銷(xiāo)毀后還未執(zhí)行onStop(),onDestory()方法,即廣播仍還未注銷(xiāo),從而導(dǎo)致內(nèi)存泄露。
  3. 但是,onPause()一定會(huì)被執(zhí)行,從而保證了廣播在App死亡前一定會(huì)被注銷(xiāo),從而防止內(nèi)存泄露。

5.2.3 兩種注冊(cè)方式的區(qū)別

示意圖

5.3 廣播發(fā)送者向AMS發(fā)送廣播

5.3.1 廣播的發(fā)送
  • 廣播 是 用”意圖(Intent)“標(biāo)識(shí)
  • 定義廣播的本質(zhì) = 定義廣播所具備的“意圖(Intent)”
  • 廣播發(fā)送 = 廣播發(fā)送者 將此廣播的“意圖(Intent)”通過(guò)sendBroadcast()方法發(fā)送出去
5.3.2 廣播的類(lèi)型

廣播的類(lèi)型主要分為5類(lèi):

  • 普通廣播(Normal Broadcast
  • 系統(tǒng)廣播(System Broadcast
  • 有序廣播(Ordered Broadcast
  • 粘性廣播(Sticky Broadcast
  • App應(yīng)用內(nèi)廣播(Local Broadcast

具體說(shuō)明如下:
1. 普通廣播(Normal Broadcast)
即 開(kāi)發(fā)者自身定義 intent的廣播(最常用)。發(fā)送廣播使用如下:

Intent intent = new Intent();
//對(duì)應(yīng)BroadcastReceiver中intentFilter的action
intent.setAction(BROADCAST_ACTION);
//發(fā)送廣播
sendBroadcast(intent);
  • 若被注冊(cè)了的廣播接收者中注冊(cè)時(shí)intentFilteraction與上述匹配,則會(huì)接收此廣播(即進(jìn)行回調(diào)onReceive())。如下mBroadcastReceiver則會(huì)接收上述廣播
<receiver 
    //此廣播接收者類(lèi)是mBroadcastReceiver
    android:name=".mBroadcastReceiver" >
    //用于接收網(wǎng)絡(luò)狀態(tài)改變時(shí)發(fā)出的廣播
    <intent-filter>
        <action android:name="BROADCAST_ACTION" />
    </intent-filter>
</receiver>
  • 若發(fā)送廣播有相應(yīng)權(quán)限,那么廣播接收者也需要相應(yīng)權(quán)限

2. 系統(tǒng)廣播(System Broadcast)

  • Android中內(nèi)置了多個(gè)系統(tǒng)廣播:只要涉及到手機(jī)的基本操作(如開(kāi)機(jī)、網(wǎng)絡(luò)狀態(tài)變化、拍照等等),都會(huì)發(fā)出相應(yīng)的廣播
  • 每個(gè)廣播都有特定的Intent - Filter(包括具體的action),Android系統(tǒng)廣播action如下:
系統(tǒng)操作 action
監(jiān)聽(tīng)網(wǎng)絡(luò)變化 android.net.conn.CONNECTIVITY_CHANGE
關(guān)閉或打開(kāi)飛行模式 Intent.ACTION_AIRPLANE_MODE_CHANGED
充電時(shí)或電量發(fā)生變化 Intent.ACTION_BATTERY_CHANGED
電池電量低 Intent.ACTION_BATTERY_LOW
電池電量充足(即從電量低變化到飽滿時(shí)會(huì)發(fā)出廣播 Intent.ACTION_BATTERY_OKAY
系統(tǒng)啟動(dòng)完成后(僅廣播一次) Intent.ACTION_BOOT_COMPLETED
按下照相時(shí)的拍照按鍵(硬件按鍵)時(shí) Intent.ACTION_CAMERA_BUTTON
屏幕鎖屏 Intent.ACTION_CLOSE_SYSTEM_DIALOGS
設(shè)備當(dāng)前設(shè)置被改變時(shí)(界面語(yǔ)言、設(shè)備方向等) Intent.ACTION_CONFIGURATION_CHANGED
插入耳機(jī)時(shí) Intent.ACTION_HEADSET_PLUG
未正確移除SD卡但已取出來(lái)時(shí)(正確移除方法:設(shè)置--SD卡和設(shè)備內(nèi)存--卸載SD卡) Intent.ACTION_MEDIA_BAD_REMOVAL
插入外部?jī)?chǔ)存裝置(如SD卡) Intent.ACTION_MEDIA_CHECKING
成功安裝APK Intent.ACTION_PACKAGE_ADDED
成功刪除APK Intent.ACTION_PACKAGE_REMOVED
重啟設(shè)備 Intent.ACTION_REBOOT
屏幕被關(guān)閉 Intent.ACTION_SCREEN_OFF
屏幕被打開(kāi) Intent.ACTION_SCREEN_ON
關(guān)閉系統(tǒng)時(shí) Intent.ACTION_SHUTDOWN
重啟設(shè)備 Intent.ACTION_REBOOT

注:當(dāng)使用系統(tǒng)廣播時(shí),只需要在注冊(cè)廣播接收者時(shí)定義相關(guān)的action即可,并不需要手動(dòng)發(fā)送廣播,當(dāng)系統(tǒng)有相關(guān)操作時(shí)會(huì)自動(dòng)進(jìn)行系統(tǒng)廣播

3. 有序廣播(Ordered Broadcast)

  • 定義
    發(fā)送出去的廣播被廣播接收者按照先后順序接收

有序是針對(duì)廣播接收者而言的

  • 廣播接受者接收廣播的順序規(guī)則(同時(shí)面向靜態(tài)和動(dòng)態(tài)注冊(cè)的廣播接受者)

    1. 按照Priority屬性值從大-小排序;
    2. Priority屬性相同者,動(dòng)態(tài)注冊(cè)的廣播優(yōu)先;
  • 特點(diǎn)

    1. 接收廣播按順序接收
    2. 先接收的廣播接收者可以對(duì)廣播進(jìn)行截?cái)?,即后接收的廣播接收者不再接收到此廣播;
    3. 先接收的廣播接收者可以對(duì)廣播進(jìn)行修改,那么后接收的廣播接收者將接收到被修改后的廣播
  • 具體使用
    有序廣播的使用過(guò)程與普通廣播非常類(lèi)似,差異僅在于廣播的發(fā)送方式:

sendOrderedBroadcast(intent);

4. App應(yīng)用內(nèi)廣播(Local Broadcast)

  • 背景
    Android中的廣播可以跨App直接通信(exported對(duì)于有intent-filter情況下默認(rèn)值為true)

  • 沖突
    可能出現(xiàn)的問(wèn)題:

    • 其他App針對(duì)性發(fā)出與當(dāng)前App intent-filter相匹配的廣播,由此導(dǎo)致當(dāng)前App不斷接收廣播并處理;
    • 其他App注冊(cè)與當(dāng)前App一致的intent-filter用于接收廣播,獲取廣播具體信息;
      即會(huì)出現(xiàn)安全性 & 效率性的問(wèn)題。
  • 解決方案
    使用App應(yīng)用內(nèi)廣播(Local Broadcast)

  1. App應(yīng)用內(nèi)廣播可理解為一種局部廣播,廣播的發(fā)送者和接收者都同屬于一個(gè)App。
  2. 相比于全局廣播(普通廣播),App應(yīng)用內(nèi)廣播優(yōu)勢(shì)體現(xiàn)在:安全性高 & 效率高
  • 具體使用1 - 將全局廣播設(shè)置成局部廣播

    1. 注冊(cè)廣播時(shí)將exported屬性設(shè)置為false,使得非本App內(nèi)部發(fā)出的此廣播不被接收;
    2. 在廣播發(fā)送和接收時(shí),增設(shè)相應(yīng)權(quán)限permission,用于權(quán)限驗(yàn)證;
    3. 發(fā)送廣播時(shí)指定該廣播接收器所在的包名,此廣播將只會(huì)發(fā)送到此包中的App內(nèi)與之相匹配的有效廣播接收器中。

    通過(guò)intent.setPackage(packageName)指定報(bào)名

  • 具體使用2 - 使用封裝好的LocalBroadcastManager類(lèi)
    使用方式上與全局廣播幾乎相同,只是注冊(cè)/取消注冊(cè)廣播接收器和發(fā)送廣播時(shí)將參數(shù)的context變成了LocalBroadcastManager的單一實(shí)例

注:對(duì)于LocalBroadcastManager方式發(fā)送的應(yīng)用內(nèi)廣播,只能通過(guò)LocalBroadcastManager動(dòng)態(tài)注冊(cè),不能靜態(tài)注冊(cè)

//注冊(cè)應(yīng)用內(nèi)廣播接收器
//步驟1:實(shí)例化BroadcastReceiver子類(lèi) & IntentFilter mBroadcastReceiver 
mBroadcastReceiver = new mBroadcastReceiver(); 
IntentFilter intentFilter = new IntentFilter(); 

//步驟2:實(shí)例化LocalBroadcastManager的實(shí)例
localBroadcastManager = LocalBroadcastManager.getInstance(this);

//步驟3:設(shè)置接收廣播的類(lèi)型 
intentFilter.addAction(android.net.conn.CONNECTIVITY_CHANGE);

//步驟4:調(diào)用LocalBroadcastManager單一實(shí)例的registerReceiver()方法進(jìn)行動(dòng)態(tài)注冊(cè) 
localBroadcastManager.registerReceiver(mBroadcastReceiver, intentFilter);

//取消注冊(cè)應(yīng)用內(nèi)廣播接收器
localBroadcastManager.unregisterReceiver(mBroadcastReceiver);

//發(fā)送應(yīng)用內(nèi)廣播
Intent intent = new Intent();
intent.setAction(BROADCAST_ACTION);
localBroadcastManager.sendBroadcast(intent);

5. 粘性廣播(Sticky Broadcast)
由于在Android5.0 & API 21中已經(jīng)失效,所以不建議使用,在這里也不作過(guò)多的總結(jié)。


6. 特別注意

對(duì)于不同注冊(cè)方式的廣播接收器回調(diào)OnReceive(Context context,Intent intent)中的context返回值是不一樣的:

  • 對(duì)于靜態(tài)注冊(cè)(全局+應(yīng)用內(nèi)廣播),回調(diào)onReceive(context, intent)中的context返回值是:ReceiverRestrictedContext;
  • 對(duì)于全局廣播的動(dòng)態(tài)注冊(cè),回調(diào)onReceive(context, intent)中的context返回值是:Activity Context;
  • 對(duì)于應(yīng)用內(nèi)廣播的動(dòng)態(tài)注冊(cè)(LocalBroadcastManager方式),回調(diào)onReceive(context, intent)中的context返回值是:Application Context。
  • 對(duì)于應(yīng)用內(nèi)廣播的動(dòng)態(tài)注冊(cè)(非LocalBroadcastManager方式),回調(diào)onReceive(context, intent)中的context返回值是:Activity Context;

7. 總結(jié)

  • 本文主要介紹了Android中四大組件的BroadcastReceiver的所有知識(shí)
  • Carson帶你學(xué)四大組件文章系列:

Carson帶你學(xué)Android:頁(yè)面活動(dòng)-Activity
Carson帶你學(xué)Android:廣播-BroadcastReceiver
Carson帶你學(xué)Android:服務(wù)-Service
Carson帶你學(xué)Android:內(nèi)存承載器-ContentProvider


歡迎關(guān)注Carson_Ho的簡(jiǎn)書(shū)

不定期分享關(guān)于安卓開(kāi)發(fā)的干貨,追求短、平、快,但卻不缺深度。


請(qǐng)點(diǎn)贊!因?yàn)槟愕墓膭?lì)是我寫(xiě)作的最大動(dòng)力!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,428評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,024評(píng)論 3 413
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事?!?“怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 175,285評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 62,548評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,328評(píng)論 6 404
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 54,878評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,971評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 42,098評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,616評(píng)論 1 331
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,554評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,725評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,243評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,971評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 34,361評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 35,613評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,339評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,695評(píng)論 2 370

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