Android NDK——使用Android Studio引用so庫(kù),jar包、module以及導(dǎo)入Eclipse項(xiàng)目并使用JNI的正確姿勢(shì)

引言

由于項(xiàng)目中需要用到JNI,以前雖然在Eclipse上使用過(guò)JNI和SO 文件,移植到Android Studio上的時(shí)候是花費(fèi)好些力氣的,也處理過(guò)不少常見(jiàn)的錯(cuò)誤,而且網(wǎng)上很多文章都是只寫(xiě)了大致的步驟,忽略了很多細(xì)節(jié),為了讓新手們少走彎路,同時(shí)也是加強(qiáng)自己的理解,把自己一步一步的操作記錄下來(lái)。

一、Android studio引入jar

不同于eclipse的配置build path,Android Studio可以通過(guò)圖形界面Project Structure來(lái)配置dependencies還可以通過(guò)gradle.build腳本來(lái)配置

1、先把對(duì)應(yīng)jar包c(diǎn)opy到libs或者jniLibs下再"Add As Library"(個(gè)人推薦)

  • 將jar文件復(fù)制、粘貼到app的libs或者jniLibs目錄中
  • 右鍵點(diǎn)擊jar文件,并點(diǎn)擊彈出菜單中的“Add As Library”,將jar文件作為類庫(kù)添加到項(xiàng)目中
  • 選擇指定的類庫(kù)。(高能提醒:如果不執(zhí)行后兩步,jar文件將不起作用,當(dāng)然不能使用import語(yǔ)句引用。)

2、先copy再通過(guò)gradle.build腳本配置

  • 將jar文件復(fù)制、粘貼到app的libs或者jniLibs目錄中

  • 在app下的build.gradle腳本里配置dependencies 節(jié)點(diǎn)(與android節(jié)點(diǎn)同級(jí))

dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')//**主要是這兩句
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    compile files('libs/konke-android-lib.jar')//**編譯konke-android-lib.jar
}

3、通過(guò)Android Studio的圖形界面

Open module setting——>Project Structure——>選中對(duì)應(yīng)的module——>Dependencies——>"+"——>選擇對(duì)應(yīng)的jar包執(zhí)行完畢之后會(huì)被添加到libs文件夾下(即Project模式下的libs)

這里寫(xiě)圖片描述

二、Android Studio依賴module

如圖module app 依賴于zklibs

這里寫(xiě)圖片描述

1、通過(guò)Android Studio的圖形界面

Open module setting——>Project Structure——>選中對(duì)應(yīng)的module——>Dependencies——>"+"——>選擇對(duì)應(yīng)的jar包

2、通過(guò)gradle.build腳本配置

//app的gradle
dependencies {
    compile fileTree(include: ['*.jar'], dir: 'libs')
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:24.0.0'
    
    compile 'com.google.code.gson:gson:2.7'
  
    compile project(path: ':zklibs')//主要是這一句
    
}

三、Android Studio使用SO文件

前面一篇Android NDK——配置NDK及使用Android studio開(kāi)發(fā)Hello JNI并簡(jiǎn)單打包SO介紹了so文件,它是unix的動(dòng)態(tài)連接庫(kù),是二進(jìn)制文件,其本質(zhì)就是本地語(yǔ)言(c/c++)程序文件,作用相當(dāng)于windows下的.dll文件。而在Android中調(diào)用動(dòng)態(tài)庫(kù)文件(.so)都是通過(guò)jni的方式*。

這里寫(xiě)圖片描述

1、引入so文件到項(xiàng)目中

我們都知道Android Studio的項(xiàng)目結(jié)構(gòu)與在Eclipse里的區(qū)別巨大,切換為Project模式和Android模式,顯示的結(jié)構(gòu)都有所不同,這也導(dǎo)致很多初學(xué)者有點(diǎn)迷了,當(dāng)然也包括我,走過(guò)不少?gòu)澛罚珿oogle、StackOverFlow走了很多遍,折騰了一番,最后終于成功了,只需兩步驟。

  • 把Android Studio 里的項(xiàng)目且為Project類型的結(jié)構(gòu),在xxx/src/main的目錄下下新建名為 ”jniLibs“ 文件夾(注意大小寫(xiě),與java文件夾同級(jí))

  • 再將so文件復(fù)制、粘貼到“jniLibs”目錄內(nèi)。(其實(shí)jniLibs文件里不僅僅可以放置so文件、也可以放置jar包類型的庫(kù))不需要再額外去配置Gradle了

//當(dāng)然還有另一種引入so,就是放到libs下,我不喜歡用這種方式。。。
/**如果使用jniLibs文件夾導(dǎo)入so文件,不需要在gradle中配置了;如果將so文件添加在module的libs文件夾下,則需要在module的gradle配置中添加一下配置*/
sourceSets {
    main {
        jniLibs.srcDirs = ['libs']
    }
}

2、定義自己的本地jni接口類

2.1、獲取so里定義的本地方法簽名

借助是是Linux的一個(gè)命令:nm -D xxxx.so還可以設(shè)置-D以外的其他參數(shù),不過(guò)-D已經(jīng)足夠

nm -D  libelia.so

下圖顯示的就是聯(lián)發(fā)科SmartLink方案的so庫(kù)定義的方法簽名還有其他信息,就不貼了


這里寫(xiě)圖片描述

2.2、實(shí)現(xiàn)自己的本地jni接口類

把所要使用的so文件復(fù)制粘貼到”jniLibs“文件夾之后,一般來(lái)說(shuō)其他第三方的開(kāi)放平臺(tái)的so文件都是已經(jīng)把對(duì)應(yīng)的本地Java接口類一起封裝到so或者其他庫(kù)文件里了,我們不需要自己去定義自己的本地接口類,假如說(shuō)第三方只是提供了so文件,那么就需要我們?nèi)ザxjni接口類(這個(gè)類并不能是隨意的,必須是和so文件里定義的方法名的一一對(duì)應(yīng),即包名和類名必須一致,否則會(huì)發(fā)生編譯通過(guò)加載的時(shí)候就出錯(cuò))


這里寫(xiě)圖片描述

假如so里是這樣定義本地方法,那么對(duì)應(yīng)的我們這個(gè)本地接口類,必須滿足四個(gè)條件:

  1. 包名是crazymo.train.jnitraining

  2. 類名是MainActivity

  3. 定義的方法名為 helloJni

  4. 返回值類型為String

那么定義這個(gè)本地接口方法類的一般步驟是:

  1. 在項(xiàng)目里首先創(chuàng)建一個(gè)對(duì)應(yīng)的包
  2. 再這個(gè)包里創(chuàng)建對(duì)應(yīng)的公開(kāi)類
  3. 最后在這個(gè)類里定義對(duì)應(yīng)的本地接口方法(常規(guī)修飾符 native static 返回值類型 helloJni**當(dāng)然static并不是必須的)

3、加載so文件

加載so文件很簡(jiǎn)單,如果你這個(gè)APP必須依賴于這個(gè)so才能運(yùn)行的話,建議可以在自己的Application去實(shí)現(xiàn)

 System.loadLibrary("helloJni");//加載so文件,不要帶上前綴lib和后綴.so
package crazymo.train.jni;

/**
 * @auther: Crazy.Mo
 * Date: 2016/10/13
 * Time:15:22
 * Des:
 */
public class HelloJNI {
    static {
        System.loadLibrary("helloJni");//引入你的so庫(kù)文件,不要把前面的lib添加進(jìn)來(lái)
    }
    public native String helloJni();
}

4、利用本地jni接口類調(diào)用對(duì)應(yīng)的接口方法

這個(gè)更簡(jiǎn)單了,就和我們普通java類的調(diào)用語(yǔ)法一樣,如果是靜態(tài)的就用類去調(diào)用,如果非靜態(tài)則用對(duì)應(yīng)的實(shí)例去調(diào)用,至于怎么調(diào)用到本地代碼的,那部分工作由系統(tǒng)會(huì)根據(jù)你本地接口的包名、方法名去找到對(duì)應(yīng)的C/C++代碼,所以本地接口類往往是我們使用so時(shí)發(fā)生錯(cuò)誤的罪魁禍?zhǔn)字?/p>

package crazymo.train.jni;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ((TextView)findViewById(R.id.txt_usejni)).setText( new HelloJNI().helloJni());//使用jni方法
    }
}

5、簡(jiǎn)單使用so庫(kù)項(xiàng)目的結(jié)構(gòu)圖

這里寫(xiě)圖片描述

四、NDK調(diào)試

默認(rèn)情況下是不支持NDK調(diào)試的,但我們只要做些簡(jiǎn)單配置即可實(shí)現(xiàn)支持。

1、打開(kāi)JNI調(diào)試 openModuleSettings——>選中module——>Build Types——>Jni Debuggable為true——Apply

這里寫(xiě)圖片描述

2、配置Android Native - Debugger run——>Edit configurations——>選中對(duì)應(yīng)的module——>Debugger——>Debugger Type 選native——Apply

這里寫(xiě)圖片描述

3、下載安裝LLDB,Done。

五、Eclipse項(xiàng)目導(dǎo)入到Android Studio

1、普通Eclipse導(dǎo)入Android Studio

普通的導(dǎo)入流程很簡(jiǎn)單,有兩個(gè)入口:直接在打開(kāi)Android studio的窗口中選擇"import project(Eclipse ADT ,gradle,etc)"然后按步驟導(dǎo)入即可(進(jìn)到這個(gè)入口也很簡(jiǎn)單,把Android studio其他的Project 窗口都關(guān)閉了,只留下一個(gè)Project然后“Close Project”即可)

這里寫(xiě)圖片描述

或者在已經(jīng)打開(kāi)的Project窗口中,切換到Project視圖——>在Project跟目錄上右鍵——>Module——>import Eclipse ADT project

2、JNI Eclipse 項(xiàng)目導(dǎo)入到Android Studio

導(dǎo)入JNI Eclipse項(xiàng)目時(shí),前面的步驟都一樣,導(dǎo)入完成之后,還得通過(guò)選中Module——>右鍵“Link C++ Project with Gradle”配置C++ Link——>可以選ndk-build——>找到Android.mk——>點(diǎn)擊Ok (或者CMake——>選中CMakeList.txtk——>點(diǎn)擊Ok),否則會(huì)本地代碼會(huì)報(bào)錯(cuò)。


這里寫(xiě)圖片描述

3、Eclipse項(xiàng)目導(dǎo)入到Android Studio的常見(jiàn)錯(cuò)誤

3.1、編碼錯(cuò)誤

比如說(shuō)Eclise項(xiàng)目下的編碼為UTF-8,而Android Studio下的默認(rèn)為UTF-8 無(wú)BOM 格式,此時(shí)只需要把Eclipse下的編碼改為UTF-8 無(wú)BOM即可解決以下錯(cuò)誤

這里寫(xiě)圖片描述

3.2、未配置Link C++ Project with Gradle

這里寫(xiě)圖片描述

六、使用so時(shí)常見(jiàn)錯(cuò)誤

1、java.lang.UnsatisfiedLinkError: Couldn't load library xxxx from loader dalvik.system.PathClassLoader

導(dǎo)致這個(gè)異常的根本原因就是系統(tǒng)在本地方法與我們本地方法接口類無(wú)法對(duì)應(yīng)上,官方一點(diǎn)就是JVM找不到native method的native

  • 還未加載對(duì)應(yīng)的so導(dǎo)致的Crash!xxxcouldn’t find “xxx.so”,因?yàn)閍pk打包安裝時(shí),系統(tǒng)會(huì)把a(bǔ)pk中l(wèi)ibs目錄下armeabi的so拷貝到應(yīng)用的私有目錄下

Crash!java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file “/data/app/xxx],nativeLibraryDirectories=[/vendor/lib, /systemb]]] couldn’t find “xxx.so”
  • 加載的so與所運(yùn)行的設(shè)備的abi架構(gòu)不一致,只要在在對(duì)應(yīng)的文件夾里添加上相應(yīng)的so文件即可

  • java.lang.UnsatisfiedLinkError:No implementation found for XXX
    這種錯(cuò)誤一般來(lái)就是我們本地方法接口類沒(méi)有和c/c++里的方法對(duì)應(yīng)上

2、java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader

原因是引用了多方的so,很常見(jiàn)的情況是libaxx.so在各個(gè)架構(gòu)對(duì)應(yīng)的文件夾中都存在,而另一個(gè)libcxx.so只存在于32位對(duì)應(yīng)的armaebi文件下,其他架構(gòu)的都沒(méi)有,那么此時(shí)程序運(yùn)行在非armaebi架構(gòu)的設(shè)備時(shí)則會(huì)直接報(bào)錯(cuò)強(qiáng)退。錯(cuò)誤的日志如下:

10-28 15:42:28.122 5307-5307/com.xiaoi.app.zkSmartHome E/AndroidRuntime: FATAL EXCEPTION: main
                                                                         Process: com.xiaoi.app.zkSmartHome, PID: 5307
                                                                         java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-zxing_c557fb7a8d7e6e337af354ce06614692a32b946a-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-support-annotations-24.0.0_abdd7eb84ec5507286f957f2abccaca254128b0c-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-rxjava-1.1.8_75fd2ee9fdad54b1b788e8d01c74e78698f28eae-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-retrofit-2.0.0-beta4_3efd0604843b4a6440028ce43f72e5845c1c3325-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-picasso-2.5.2_badcc59626c8bf60fbd570ba883ac0f8d5c9be7a-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-okio-1.6.0_c6c36c9266a53bff725e5087f6a3090b1d0ab593-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-okhttp-3.0.1_a35a122a63f63f6d2b3ba59d028c055fab521b52-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-io.reactivex-rxandroid-1.2.1_6e88671f81f408ad9e58406d59bc0cda6a6af625-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-internal_impl-24.0.0_1ca3cb52067dc09725d551b03ece99cd965979ac-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-in.srain.cube-ultra-ptr-1.0.11_b0a09794d2bb3bfed3ce82634bdccabed79fc5d0-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-gson-2.4_1cef8cfc76ca82a728656c88394ab94c85c46ee1-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-glide-3.6.1_f81c2f329f31a6fbb9641a61098e423c033cd42e-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-converter-gson-2.0.0-beta4_75a1a6273cb28d11375dfff6cd0aa45f11079258-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.orhanobut-logger-1.3_89736aa22bffa06d17995d9ad26acdfaf3572df7-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.android.support-support-vector-drawable-24.0.0_8d5d9e2412dc464146da0fdb00638a8cb0b0130d-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.android.support-support-v4-24.0.0_225ce4463e0d8c3e77ccfd8c1e749bd698e46fcc-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.android.support-recyclerview-v7-24.0.0_39a4b7cd3d134a80b92025fdd19f175953aa0dcc-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.android.support-cardview-v7-24.0.0_22b22b962be76ccc27cc64fad5c53d30515f6535-classes.dex", dex file "/data/data/com.xiaoi.app.zkSmartHome/files/instant-run/dex/slice-com.android.support-appcompat-v7-24.0.0_4ce805b4f9e08926ae1

解決方法
最佳的方案肯定是添加上對(duì)應(yīng)的so到對(duì)應(yīng)的文件夾下,不過(guò)由于某些原因,不能找到對(duì)應(yīng)的so庫(kù),也可以采用投機(jī)取巧的方式,把a(bǔ)rmaebi下的copy到其他文件下或者刪除其他的文件夾,總之,要保證你有我也有,不能你有我無(wú)。

3、還未發(fā)現(xiàn)...后面發(fā)現(xiàn)了再補(bǔ)充

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

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