Intent和Intent過濾器

概述

Intent是用于和其他應(yīng)用組件通信的消息對(duì)象,

通常有三種用途:啟動(dòng)Activity啸罢、啟動(dòng)Service裳朋、發(fā)送Broadcast

Intent類型

  • 顯式Intent
  • 隱式Intent

創(chuàng)建Intent

  • Component name

    • setComponent()
    • setClass()
    • setClassName()
  • Action

    • ACTION_VIEW
    • ACTION_SEND
  • Data

    Uri對(duì)象、指定數(shù)據(jù)的MIME類型

    • setDataAndType()
  • Category

    • CATEGORY_BROWSABLE
    • CATEGORY_LAUNCHER
  • Extras

    Bundle鍵值對(duì)

  • Flags

    指示如何啟動(dòng)Activity温学,以及啟動(dòng)后它所屬的任務(wù)棧

示例: App選擇器
val sendIntent = Intent(Intent.ACTION_SEND)
...

// Always use string resources for UI text.
// This says something like "Share this photo with"
val title: String = resources.getString(R.string.chooser_title)
// Create intent to show the chooser dialog
val chooser: Intent = Intent.createChooser(sendIntent, title)

// Verify the original intent will resolve to at least one activity
if (sendIntent.resolveActivity(packageManager) != null) {
    startActivity(chooser)
}

接收隱式Intent

清單文件中定義<intent-filter>

- <action>
- <data>
- <category>
<activity android:name="MainActivity">
    <!-- This activity is the main entry, should appear in app launcher -->
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<activity android:name="ShareActivity">
    <!-- This activity handles "SEND" actions with text data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="text/plain"/>
    </intent-filter>
    <!-- This activity also handles "SEND" and "SEND_MULTIPLE" with media data -->
    <intent-filter>
        <action android:name="android.intent.action.SEND"/>
        <action android:name="android.intent.action.SEND_MULTIPLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:mimeType="application/vnd.google.panorama360+jpg"/>
        <data android:mimeType="image/*"/>
        <data android:mimeType="video/*"/>
    </intent-filter>
</activity>

PendingIntent

使用場景:

- Notification
- App Widget
- AlarmManager

創(chuàng)建:

- PendingIntent.getActivity()
- PendingIntent.getService()
- PendingIntent.getBroadcast()

<font color="red">解析Intent</font>

  • action

    Intent中指定的action必須與intent-filter中列出的action一項(xiàng)匹配聪建。

    若intent-filter中不包含action钙畔,匹配永遠(yuǎn)不會(huì)成功。

    若Intent中未指定action金麸,而只要intent-filter至少包含一個(gè)action就會(huì)默認(rèn)匹配成功擎析。

  • category

    Intent中的每個(gè)category都必須與intent-filter中列出的category匹配。

    即Intent中指定的category必須是intent-filter中category的子集挥下。

    若Intent不包含category揍魂,則匹配成功。

  • data

    1. 僅當(dāng)過濾器未指定任何 URI 或 MIME 類型時(shí)棚瘟,不含 URI 和 MIME 類型的 Intent 才會(huì)通過測試现斋。
    2. 對(duì)于包含 URI 但不含 MIME 類型(既未顯式聲明,也無法通過 URI 推斷得出)的 Intent偎蘸,僅當(dāng)其 URI 與過濾器的 URI 格式匹配庄蹋、且過濾器同樣未指定 MIME 類型時(shí),才會(huì)通過測試迷雪。
    3. 僅當(dāng)過濾器列出相同的 MIME 類型且未指定 URI 格式時(shí)限书,包含 MIME 類型但不含 URI 的 Intent 才會(huì)通過測試。
    4. 如果過濾器只是列出 MIME 類型章咧,則假定組件支持 content:file: 數(shù)據(jù)倦西。

Intent匹配

PackageManager 提供一整套 query...() 方法來返回所有能夠接受特定 Intent 的組件。

此外赁严,還會(huì)提供一系列類似的 resolve...() 方法來確定響應(yīng) Intent 的最佳組件扰柠。

常見Intent

鬧鐘

  • Action:ACTION_SET_ALARM
  • Extras
    • EXTRA_HOUR
    • EXTRA_MINUTES
    • EXTRA_MESSAGE
    • EXTRA_DAYS
    • EXTRA_RINGTONE
    • EXTRA_VIBRATE
    • EXTRA_SKIP_UI
//SET_ALARM permission 
fun createAlarm(message: String, hour: Int, minutes: Int) {
    val intent = Intent(AlarmClock.ACTION_SET_ALARM).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_HOUR, hour)
        putExtra(AlarmClock.EXTRA_MINUTES, minutes)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

定時(shí)器

  • Action:ACTION_SET_TIMER
  • Extras:
    • EXTRA_LENGTH
    • EXTRA_MESSAGE
    • EXTRA_SKIP_UI
//SET_ALARM permission
fun startTimer(message: String, seconds: Int) {
    val intent = Intent(AlarmClock.ACTION_SET_TIMER).apply {
        putExtra(AlarmClock.EXTRA_MESSAGE, message)
        putExtra(AlarmClock.EXTRA_LENGTH, seconds)
        putExtra(AlarmClock.EXTRA_SKIP_UI, true)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

顯示所有鬧鐘

  • Action:ACTION_SHOW_ALARMS

日歷

  • Action:ACTION_INSERT
  • Data URI:Events.CONTENT_URI
  • MIME Type:“vnd.android.cursor.dir/event”
  • Extra:
    • EXTRA_EVENT_ALL_DAY
    • EXTRA_EVENT_BEGIN_TIME
    • EXTRA_EVENT_END_TIME
    • TITLE
    • DESCRIPTION
    • EVENT_LOCATION
    • EXTRA_EMAIL
fun addEvent(title: String, location: String, begin: Long, end: Long) {
    val intent = Intent(Intent.ACTION_INSERT).apply {
        data = Events.CONTENT_URI
        putExtra(Events.TITLE, title)
        putExtra(Events.EVENT_LOCATION, location)
        putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, begin)
        putExtra(CalendarContract.EXTRA_EVENT_END_TIME, end)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

相機(jī)

拍攝照片或視頻

相對(duì)于相機(jī)應(yīng)用粉铐,此界面只要拍攝功能,無相冊

  • Action:ACTION_IMAGE_CAPTURE or ACTION_VIDEO_CAPTURE
  • Extras:EXTRA_OUTPUT
const val REQUEST_IMAGE_CAPTURE = 1
val locationForPhotos: Uri = ...

fun capturePhoto(targetFilename: String) {
    val intent = Intent(MediaStore.ACTION_IMAGE_CAPTURE).apply {
        putExtra(MediaStore.EXTRA_OUTPUT, Uri.withAppendedPath(locationForPhotos, targetFilename))
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_CAPTURE)
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == REQUEST_IMAGE_CAPTURE && resultCode == Activity.RESULT_OK) {
        val thumbnail: Bitmap = data.getParcelableExtra("data")
        // Do other work with full size photo saved in locationForPhotos
        ...
    }
}

For more information about how to use this intent to capture a photo, including how to create an appropriate Uri for the output location, read Taking Photos Simply or Taking Videos Simply.

啟動(dòng)相機(jī)應(yīng)用
  • INTENT_ACTION_STILL_IMAGE_CAMERA
  • INTENT_ACTION_VIDEO_CAMERA

聯(lián)系人

選擇聯(lián)系人
  • Action:ACTION_PICK
  • MIME Type:Contacts.CONTENT_TYPE
選擇特定聯(lián)系人數(shù)據(jù)
  • Action:ACTION_PICK
  • MIME Type:
    • CommonDataKinds.Phone.CONTNET_TYPE
    • CommonDataKinds.Email.CONTNET_TYPE
const val REQUEST_SELECT_PHONE_NUMBER = 1

fun selectContact() {
    // Start an activity for the user to pick a phone number from contacts
    val intent = Intent(Intent.ACTION_PICK).apply {
        type = CommonDataKinds.Phone.CONTENT_TYPE   
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivityForResult(intent, REQUEST_SELECT_PHONE_NUMBER)
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == REQUEST_SELECT_PHONE_NUMBER && resultCode == Activity.RESULT_OK) {
        // Get the URI and query the content provider for the phone number
        val contactUri: Uri = data.data
        val projection: Array<String> = arrayOf(CommonDataKinds.Phone.NUMBER)
        contentResolver.query(contactUri, projection, null, null, null).use { cursor ->
            // If the cursor returned is valid, get the phone number
            if (cursor.moveToFirst()) {
                val numberIndex = cursor.getColumnIndex(CommonDataKinds.Phone.NUMBER)
                val number = cursor.getString(numberIndex)
                // Do something with the phone number
                ...
            }
        }
    }
}
查看聯(lián)系人
  • Action:ACTION_VIEW
  • Data URI:content:<URI>
fun viewContact(contactUri: Uri) {
    val intent = Intent(Intent.ACTION_VIEW, contactUri)
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}
編輯現(xiàn)有聯(lián)系人
  • Action:ACTION_EDIT
  • Data URI:content:<URI>
  • MIME Type:該類型是從聯(lián)系人 URI 推斷得出
  • Extra:ContactsContract.Intents.Insert
fun editContact(contactUri: Uri, email: String) {
    val intent = Intent(Intent.ACTION_EDIT).apply {
        data = contactUri
        putExtra(ContactsContract.Intents.Insert.EMAIL, email)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}
插入聯(lián)系人
  • Action:ACTION_INSERT
  • MIME Type:Contacts.CONTENT_TYPE
  • Extra:ContactsContract.Intents.Insert
fun insertContact(name: String, email: String) {
    val intent = Intent(Intent.ACTION_INSERT).apply {
        type = ContactsContract.Contacts.CONTENT_TYPE
        putExtra(ContactsContract.Intents.Insert.NAME, name)
        putExtra(ContactsContract.Intents.Insert.EMAIL, email)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

電子郵件

文件存儲(chǔ)

檢索特定類型的文件
  • Action:ACTION_GET_CONTENT
  • MIME Type:文件對(duì)應(yīng)類型
  • Extra:
    • EXTRA_ALLOW_MULTIPLE
    • EXTRA_LOCAL_ONLY
  • Category(可選):CATEGORY_OPENABLE
//獲取照片
const val REQUEST_IMAGE_GET = 1

fun selectImage() {
    val intent = Intent(Intent.ACTION_GET_CONTENT).apply {
        type = "image/*"
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_GET)
    }
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == REQUEST_IMAGE_GET && resultCode == Activity.RESULT_OK) {
        val thumbnail: Bitmap = data.getParcelableExtra("data")
        val fullPhotoUri: Uri = data.data
        // Do work with photo saved at fullPhotoUri
        ...
    }
}
打開特定類型的文件
  • Action:ACTION_OPEN_DOCUMENT or ACTION_CREATE_DOCUMENT

  • MIME Type:文件對(duì)應(yīng)類型

  • Extra:

    • EXTRA_MIME_TYPES
    • EXTRA_ALLOW_MULTIPLE
    • EXTRA_TITLE
    • EXTRA_LOCAL_ONLY
  • Category:CATEGORY_OPENABLE

//獲取照片2
const val REQUEST_IMAGE_OPEN = 1

fun selectImage2() {
    val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
        type = "image/*"
        addCategory(Intent.CATEGORY_OPENABLE)
    }
    // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
    startActivityForResult(intent, REQUEST_IMAGE_OPEN)
}

override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    if (requestCode == REQUEST_IMAGE_OPEN && resultCode == Activity.RESULT_OK) {
        val fullPhotoUri: Uri = data.data
        // Do work with full size photo saved at fullPhotoUri
        ...
    }
}

地圖

  • Action:ACTION_VIEW

  • Data URI:

    • geo:latitude,longitude

      顯示給定經(jīng)緯度地圖

    • geo:latitude,longitude?z=zoom

      按照特定縮放級(jí)別顯示(1-23耻矮,1為全球地圖秦躯,23為最高精度縮放)

    • geo:0,0?q=lat,lng(label)

      顯示給定經(jīng)緯度處帶字符串標(biāo)簽的地圖

    • geo:0,0?q=my+street+address

      顯示“我的街道”位置

fun showMap(geoLocation: Uri) {
    val intent = Intent(Intent.ACTION_VIEW).apply {
        data = geoLocation
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

音樂或視頻

播放媒體文件
  • Action:ACTION_VIEW
  • Data URI:
    • file:<URI>
    • content:<URI>
    • http:<URI>
  • MIME Type:
    • "audio/*"
    • "application/ogg"
    • "application/x-ogg"
    • "application/itunes"
fun playMedia(file: Uri) {
    val intent = Intent(Intent.ACTION_VIEW).apply {
        data = file
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}
基于搜索播放音樂
  • Action:INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH
  • Extra:MediaStore.EXTRA_MEDIA_FOCUS
fun playSearchArtist(artist: String) {
    val intent = Intent(MediaStore.INTENT_ACTION_MEDIA_PLAY_FROM_SEARCH).apply {
        putExtra(MediaStore.EXTRA_MEDIA_FOCUS, MediaStore.Audio.Artists.ENTRY_CONTENT_TYPE)
        putExtra(MediaStore.EXTRA_MEDIA_ARTIST, artist)
        putExtra(SearchManager.QUERY, artist)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

新筆記

  • Action:ACTION_CREATE_NOTE
  • MIME Type:PLAIN_TEXT_TYPE
  • Extra:
    • EXTRA_NAME
    • EXTRA_TEXT
fun createNote(subject: String, text: String) {
    val intent = Intent(NoteIntents.ACTION_CREATE_NOTE).apply {
        putExtra(NoteIntents.EXTRA_NAME, subject)
        putExtra(NoteIntents.EXTRA_TEXT, text)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

電話

  • Action:
    • ACTION_DIAL 打開撥號(hào)界面
    • ACTION_CALL 撥打電話(需要CALL_PHONE權(quán)限)
  • Data URI:
    • tel:<phone-number>
    • voicemail:<phone-number>
fun dialPhoneNumber(phoneNumber: String) {
    val intent = Intent(Intent.ACTION_DIAL).apply {
        data = Uri.parse("tel:$phoneNumber")
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

網(wǎng)頁搜索

  • Action:ACTION_WEB_SEARCH
  • Extra:SearchManager.QUERY 搜索字符串
fun searchWeb(query: String) {
    val intent = Intent(Intent.ACTION_WEB_SEARCH).apply {
        putExtra(SearchManager.QUERY, query)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

設(shè)置

  • Action:
    • ACTION_SETTINGS
    • ACTION_WIRELESS_SETTINGS
    • ACTION_AIRPLANE_MODE_SETTINGS
    • ACTION_WIFI_SETTINGS
    • ACTION_APN_SETTINGS
    • ACTION_BLUETOOTH_SETTINGS
    • ACTION_DATE_SETTINGS
    • ACTION_LOCALE_SETTINGS
    • ACTION_INPUT_METHOD_SETTINGS
    • ACTION_DISPLAY_SETTINGS
    • ACTION_SECURITY_SETTINGS
    • ACTION_LOCATION_SOURCE_SETTINGS
    • ACTION_INTERNAL_STORAGE_SETTINGS
    • ACTION_MEMORY_CARD_SETTINGS
fun openWifiSettings() {
    val intent = Intent(Settings.ACTION_WIFI_SETTINGS)
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

發(fā)短信

  • Action:
    • ACTION_SENDTO
    • ACTION_SEND
    • ACTION_SEND_MULTIPLE
  • Data URI:
    • sms:<phone_number>
    • smsto:<phone_number>
    • mms:<phone_number>
    • mmsto:<phone_number>
  • MIME Type:
    • "text/plain"
    • "image/*"
    • "video/*"
  • Extra
    • "subject"
    • "sms_body"
    • EXTRA_STREAM
fun composeMmsMessage(message: String, attachment: Uri) {
    val intent = Intent(Intent.ACTION_SEND).apply {
        data = Uri.parse("smsto:")  // This ensures only SMS apps respond
        putExtra("sms_body", message)
        putExtra(Intent.EXTRA_STREAM, attachment)
    }
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

網(wǎng)頁瀏覽器

  • Action:ACTION_VIEW
  • Data URI:
    • http:<URL>
    • https:<URL>
  • MIME Type:
    • "text/plain"
    • "text/html"
    • "application/xhtml+xml"
    • "application/vnd.wap.xhtml+xml"
fun openWebPage(url: String) {
    val webpage: Uri = Uri.parse(url)
    val intent = Intent(Intent.ACTION_VIEW, webpage)
    if (intent.resolveActivity(packageManager) != null) {
        startActivity(intent)
    }
}

示例intent-filter

<activity ...>
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />
        <!-- Include the host attribute if you want your app to respond
             only to URLs with your app's domain. -->
        <data android:scheme="http" android:host="www.example.com" />
        <category android:name="android.intent.category.DEFAULT" />
        <!-- The BROWSABLE category is required to get links from web pages. -->
        <category android:name="android.intent.category.BROWSABLE" />
    </intent-filter>
</activity>

使用adb調(diào)試Intent

adb shell am start -a <ACTION> -t <MIME_TYPE> -d <DATA> \
  -e <EXTRA_NAME> <EXTRA_VALUE> -n <ACTIVITY>

如:

adb shell am start -a android.intent.action.DIAL \
  -d tel:555-5555 -n org.example.MyApp/.MyActivity
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市裆装,隨后出現(xiàn)的幾起案子踱承,更是在濱河造成了極大的恐慌,老刑警劉巖哨免,帶你破解...
    沈念sama閱讀 222,627評(píng)論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件茎活,死亡現(xiàn)場離奇詭異,居然都是意外死亡琢唾,警方通過查閱死者的電腦和手機(jī)载荔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,180評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來采桃,“玉大人懒熙,你說我怎么就攤上這事∑瞻欤” “怎么了工扎?”我有些...
    開封第一講書人閱讀 169,346評(píng)論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長衔蹲。 經(jīng)常有香客問我肢娘,道長,這世上最難降的妖魔是什么舆驶? 我笑而不...
    開封第一講書人閱讀 60,097評(píng)論 1 300
  • 正文 為了忘掉前任橱健,我火速辦了婚禮,結(jié)果婚禮上沙廉,老公的妹妹穿的比我還像新娘拘荡。我一直安慰自己,他們只是感情好撬陵,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,100評(píng)論 6 398
  • 文/花漫 我一把揭開白布俱病。 她就那樣靜靜地躺著,像睡著了一般袱结。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上途凫,一...
    開封第一講書人閱讀 52,696評(píng)論 1 312
  • 那天垢夹,我揣著相機(jī)與錄音,去河邊找鬼维费。 笑死果元,一個(gè)胖子當(dāng)著我的面吹牛促王,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播而晒,決...
    沈念sama閱讀 41,165評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼蝇狼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了倡怎?” 一聲冷哼從身側(cè)響起迅耘,我...
    開封第一講書人閱讀 40,108評(píng)論 0 277
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎监署,沒想到半個(gè)月后颤专,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,646評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡钠乏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,709評(píng)論 3 342
  • 正文 我和宋清朗相戀三年栖秕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片晓避。...
    茶點(diǎn)故事閱讀 40,861評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡簇捍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出俏拱,到底是詐尸還是另有隱情暑塑,我是刑警寧澤,帶...
    沈念sama閱讀 36,527評(píng)論 5 351
  • 正文 年R本政府宣布彰触,位于F島的核電站梯投,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏况毅。R本人自食惡果不足惜分蓖,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,196評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望尔许。 院中可真熱鬧么鹤,春花似錦、人聲如沸味廊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,698評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽余佛。三九已至柠新,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間辉巡,已是汗流浹背恨憎。 一陣腳步聲響...
    開封第一講書人閱讀 33,804評(píng)論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人憔恳。 一個(gè)月前我還...
    沈念sama閱讀 49,287評(píng)論 3 379
  • 正文 我出身青樓瓤荔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親钥组。 傳聞我的和親對(duì)象是個(gè)殘疾皇子输硝,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,860評(píng)論 2 361

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