Android 學(xué)習(xí)記錄三:廣播

廣播機(jī)制簡(jiǎn)介

Android中的廣播機(jī)制更加靈活巷燥,因?yàn)?code>Android中的每個(gè)應(yīng)用程序都可以對(duì)自己感興趣的廣播進(jìn)行注冊(cè),這樣該程序就只會(huì)接收到自己所關(guān)心的廣播內(nèi)容裸燎,這些廣播可能是來自系統(tǒng)的描睦,也可能是來自于其他應(yīng)用程序的璃赡。Android提供了一套完整的API薯蝎,允許應(yīng)用程序自由地發(fā)送或者接受廣播遥倦。發(fā)送廣播的方法其實(shí)之前有稍微提到過有一下,就是借助第二章的Intent占锯。接受廣播需要用到一個(gè)新的工具袒哥,廣播接收器缩筛。
Android中的廣播可以分為兩類,標(biāo)準(zhǔn)廣播和有序廣播统诺。

標(biāo)準(zhǔn)廣播

標(biāo)準(zhǔn)廣播是一種完全異步執(zhí)行的廣播歪脏。在廣播發(fā)出之后疑俭,所有的廣播接收器幾乎都會(huì)在同一時(shí)刻接收到這條廣播信息 粮呢,因此它們之間沒有任何先后順序可言。這種廣播效率較高钞艇,但是同時(shí)也意味著它是無法被階段的啄寡。

有序廣播

有序廣播是一種同步執(zhí)行的廣播。在廣播發(fā)出之后哩照,同一時(shí)刻只有一個(gè)廣播接收器能夠收到這條廣播消息挺物。當(dāng)這個(gè)廣播接收器中的邏輯執(zhí)行完畢之后廣播才會(huì)繼續(xù)傳遞。優(yōu)先級(jí)高的廣播接收器就可以先收到廣播消息飘弧,并且前面的廣播接收器還可以截?cái)嗾趥鬟f的廣播识藤。

接收系統(tǒng)廣播

Android內(nèi)置了很多系統(tǒng)級(jí)別的廣播,我們可以在應(yīng)用程序張通過監(jiān)聽這些廣播來得到各種系統(tǒng)的狀態(tài)信息次伶。比如手機(jī)開機(jī)痴昧、電池電量發(fā)生變化、時(shí)間或者時(shí)區(qū)發(fā)生改變等等冠王。如果想要接收到這些廣播就需要使用廣播接收器赶撰。

動(dòng)態(tài)注冊(cè)監(jiān)聽網(wǎng)絡(luò)變化

廣播接收器可以自由地對(duì)自己感興趣的廣播進(jìn)行豬兒,這樣當(dāng)有相應(yīng)的廣播發(fā)出時(shí)柱彻,廣播接收器就能夠收到該廣播豪娜,并且在內(nèi)部處理相應(yīng)的邏輯。
注冊(cè)廣播的方式一般也有兩種哟楷,在代碼中注冊(cè)或者在AndroidManifest.xml中注冊(cè)瘤载,其中前者也被稱為動(dòng)態(tài)注冊(cè),后者就是靜態(tài)注冊(cè)卖擅。
如何創(chuàng)建呢鸣奔?其實(shí)只需要新建一個(gè)類,讓它繼承自BroadcastReceiver磨镶,并且重寫父類的onReceive方法就行了溃蔫。這樣當(dāng)有廣播到來時(shí),onReceive方法就會(huì)得到執(zhí)行琳猫,具體的邏輯就可以在這個(gè)方法中處理伟叛。

public class MainActivity extends AppCompatActivity {
    private IntentFilter intentFilter;
    private NetworkChangeReceiver networkChangeReceiver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        intentFilter = new IntentFilter();
        networkChangeReceiver = new NetworkChangeReceiver();
        intentFilter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
        registerReceiver(networkChangeReceiver, intentFilter);
    }
    
    @Override
    protected void onDestroy(){
        super.onDestroy();
        unregisterReceiver(networkChangeReceiver);
    }
    
    class NetworkChangeReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent){
            Toast.makeText(context, "network changes", Toast.LENGTH_SHORT).show();
        }
    }
}

可以看到,我們?cè)?code>MainActivity中定義了一個(gè)內(nèi)部類NetworkChangeRectiver脐嫂,這個(gè)類繼承自BroadcastReceiver统刮,重寫了父類的onReceive方法紊遵,這樣每當(dāng)網(wǎng)絡(luò)狀態(tài)發(fā)生變化,onReceive方法就會(huì)得到執(zhí)行侥蒙。
觀察一下onCreate方法暗膜,我們創(chuàng)建了一個(gè)IntentFilter實(shí)例,并給他添加了一個(gè)值為android.net.conn.CONNECTIVITY_CHANGEaction鞭衩。當(dāng)系統(tǒng)網(wǎng)絡(luò)狀態(tài)發(fā)生變化是学搜,系統(tǒng)發(fā)出的正是一條值為android.net.conn.CONNECTIVITY_CHANGE的廣播。我們的廣播接收器想要監(jiān)聽什么廣播论衍,就在這里添加相應(yīng)的action即可瑞佩。接下來創(chuàng)建了一個(gè)NetworkChangeReceiver的實(shí)例,然后調(diào)用registerReceiver方法進(jìn)行注冊(cè)坯台,將NetworkChangeReceiver的實(shí)例和IntentFilter的實(shí)例都傳了進(jìn)去炬丸,這樣NetworkChangeRecevier就會(huì)受到所有值為android.net.conn.CONNECTIVITY_CHANGE的廣播。
最后記得蜒蕾,動(dòng)態(tài)注冊(cè)的廣播接收器一定都要取消注冊(cè)才行稠炬,這里我們是在onDestroy方法中通過調(diào)用unregisterReceiver來實(shí)現(xiàn)的。

細(xì)化調(diào)整

只是提醒網(wǎng)絡(luò)發(fā)生了變化還是不夠人性化咪啡,最好能準(zhǔn)確地告訴用戶當(dāng)前有網(wǎng)絡(luò)還是沒有首启。因此需要進(jìn)一步的優(yōu)化。

public void onReceive(Context context, Intent intent){
    ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo();
    if (networkInfo != null && networkInfo.isAvailable())
        Toast.makeText(context, "network is available", Toast.LENGTH_SHORT).show();
    else
        Toast.makeText(context, "network is unavailable", Toast.LENGTH_SHORT).show();
}

這里直接監(jiān)控系統(tǒng)網(wǎng)絡(luò)瑟匆,需要在AndroidManifest.xml里面注冊(cè)一下權(quán)限闽坡。

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>

訪問 開發(fā)者手冊(cè) 可以查看Android系統(tǒng)所有可以聲明的權(quán)限。

靜態(tài)注冊(cè)實(shí)現(xiàn)開機(jī)啟動(dòng)

動(dòng)態(tài)注冊(cè)的廣播接收器可以自由地控制祖冊(cè)預(yù)祝校愁溜,在靈活性方面有很大的優(yōu)勢(shì)疾嗅,但是也存在著一個(gè)缺點(diǎn),就是必須要在程序啟動(dòng)之后才能接收到廣播冕象,因?yàn)樽?cè)的邏輯是寫在onCreate方法中的代承。如果要讓程序在未啟動(dòng)的情況就能接收到廣播,就需要使用靜態(tài)注冊(cè)的方式了渐扮。
這里讓程序及收一條開機(jī)廣播论悴,當(dāng)收到這條廣播,就可以在onReceive方法里執(zhí)行相應(yīng)的邏輯墓律,從而實(shí)現(xiàn)開機(jī)啟動(dòng)的功能膀估。
創(chuàng)建一個(gè)BootCompleteReceiver類。

public class BootCompleteReceiver extends BroadcastReceiver{
    @Override
    public void onReceive(Context context, Intent intent){
        Toast.makeText(context, "Boot Complete", Toast.LENGTH_LONG).show();
    }
}

這里不再使用內(nèi)部類的方式來定義廣播接收器耻讽。我們?cè)賹⑦@個(gè)接收器注冊(cè)到AndroidManifest.xml中察纯,將這個(gè)廣播接收器的類名注冊(cè)進(jìn)去。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.oujitsune.broadcasttest">

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
    <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
    
    <application
        ...
        <receiver android:name=".BootCompleteReceiver">
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED"/>
            </intent-filter>
        </receiver>
    </application>

</manifest>

<application>標(biāo)簽內(nèi)出現(xiàn)了一個(gè)新的標(biāo)簽<receiver>,所有靜態(tài)注冊(cè)的廣播接收器都是在這里注冊(cè)的饼记。用法和<activity>標(biāo)簽非常相似香伴,首先通過android:name來指定具體注冊(cè)哪一個(gè)廣播接收器,然后再<intent-filter>標(biāo)簽里加入想要接受的廣播就行了具则。
另外即纲,監(jiān)聽系統(tǒng)開機(jī)廣播也是需要聲明權(quán)限的。

發(fā)送自定義廣播

接下來我們來看看怎么在應(yīng)用程序中發(fā)送自定義的廣播博肋。

發(fā)送標(biāo)準(zhǔn)廣播

在發(fā)送廣播之前低斋,我們還是需要先定義一個(gè)廣播接收器來接受廣播才行。

public class MyBroadcastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent){
        Toast.makeText(context, "received in MyBroadcastReceiver", Toast.LENGTH_LONG).show();
    }
}

注冊(cè)一下束昵。
我們一會(huì)兒要發(fā)的就是com.example.broadcasttest.MY_BROADCAST拔稳。

<receiver android:name=".MyBroadcastReceiver">
    <intent-filter>
        <action android:name="com.example.broadcasttest.MY_BROADCAST"/>
    </intent-filter>
</receiver>

發(fā)送有序廣播

廣播是一種跨進(jìn)程的通信方式,這一點(diǎn)從前面接收系統(tǒng)廣播的時(shí)候就可以看出來了锹雏。因此我們?cè)趹?yīng)用程序內(nèi)發(fā)出的廣播,其他的應(yīng)用程序也是可以收到的术奖。
想要發(fā)送有序廣播礁遵,只需要修改一行代碼。
onClick方法中改為sendOrderedBroadcast(intent, null);采记。
這個(gè)方法接受兩個(gè)參數(shù)佣耐,第一個(gè)仍然是Intent,第二個(gè)是與權(quán)限相關(guān)的字符串唧龄。
如何設(shè)定廣播接收器的先后順序呢兼砖?自然是在注冊(cè)的時(shí)候設(shè)定了。
修改AndroidManifest.xml中的代碼:
<intent-filter android:priority="100">既棺,即在intent-filter標(biāo)簽下修改優(yōu)先級(jí)為100讽挟。
然后在接收器重寫的onReceive方法中調(diào)用abortBroadcast方法,這個(gè)方法截?cái)嘟邮盏降膹V播丸冕。

使用本地廣播

前面我們發(fā)送和接受的廣播都是系統(tǒng)的全局廣播耽梅,發(fā)出的廣播可以被其他任何應(yīng)用程序接收到。這樣容易引起安全問題胖烛,比如我們發(fā)送一些攜帶關(guān)鍵性數(shù)據(jù)的廣播眼姐,可能被其他應(yīng)用程序接貨,或者其他的程序不停地想廣播接收器里發(fā)送各種垃圾廣播佩番。
為了解決廣播的安全性問題众旗,Android引入了一套本地廣播的機(jī)制,使用這個(gè)機(jī)制發(fā)出的廣播只能在應(yīng)用程序內(nèi)部進(jìn)行床底趟畏,并且廣播接收器也只能接受來自本應(yīng)用程序發(fā)出的廣播贡歧,這樣就不會(huì)有安全性問題了。
本地廣播并不復(fù)雜,主要就是使用了一個(gè)LocalBroadcastManager來對(duì)廣播進(jìn)行管理艘款,并且提供了發(fā)送廣播和注冊(cè)廣播接收器的方法持际。下面我們就通過具體的實(shí)例來嘗試一下。

public class MainActivity extends AppCompatActivity {

    private IntentFilter intentFilter;
    private LocalReceiver localReceiver;
    private LocalBroadcastManager localBroadcastManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ...
        localBroadcastManager = localBroadcastManager.getInstance(this);

        Button button_broadcast = (Button) findViewById(R.id.button_broadcast);
        button_broadcast.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent("com.example.broadcasttest.LOCAL_BROADCAST");
                localBroadcastManager.sendBroadcast(intent);
            }
        });

        intentFilter = new IntentFilter();
        intentFilter.addAction("com.example.broadcasttest.LOCAL_BROADCAST");
        localReceiver = new LocalReceiver();
        localBroadcastManager.registerReceiver(localReceiver, intentFilter);
    }

    @Override
    protected void onDestroy(){
        super.onDestroy();
        localBroadcastManager.unregisterReceiver(localReceiver);
    }

    class LocalReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent){
            Toast.makeText(context, "received local broadcast", Toast.LENGTH_LONG).show();
        }
    }
}

上面的代碼基本和原先用的動(dòng)態(tài)注冊(cè)接收器和發(fā)送廣播是一樣的哗咆,只不過現(xiàn)在首先是通過LocalBroadcastManagergetInstance方法得到了它的一個(gè)實(shí)例蜘欲,然后再注冊(cè)廣播接收器的時(shí)候調(diào)用的是LocalBroadcastManagerregisterReceiver方法,在發(fā)送廣播的時(shí)候調(diào)用的是LocalBroadcastManagersendBroadcast方法晌柬。
另外注明:本地廣播的無法通過靜態(tài)注冊(cè)的方法來接收的姥份。
最后再來盤點(diǎn)一下本地廣播的優(yōu)勢(shì)吧:

  1. 可以明確地指定正在發(fā)送的廣播不會(huì)離開我們的程序,因此不用擔(dān)心數(shù)據(jù)泄露年碘。
  2. 其他程序無法將廣播發(fā)送到我們程序內(nèi)部澈歉,因此不需要擔(dān)心會(huì)有安全漏洞的隱患。
  3. 發(fā)送本地廣播相比發(fā)送全局廣播更加高效屿衅。

實(shí)踐——實(shí)現(xiàn)強(qiáng)制下線功能

強(qiáng)制下線功能只需要彈出一個(gè)對(duì)話框埃难,讓用戶只能點(diǎn)擊確定按鈕,回到登錄界面涤久。為了避免需要在每一個(gè)活動(dòng)中添加一個(gè)對(duì)話框涡尘,用廣播實(shí)現(xiàn)是一個(gè)好辦法。
關(guān)閉所有的活動(dòng)只需要用AcitivityCollector類來管理所有的活動(dòng)响迂,然后用BaseActivity類作為所有活動(dòng)的父類考抄。
首先我們創(chuàng)建一個(gè)LoginActivity作為登錄界面,用表格布局來實(shí)現(xiàn)一下布局就可以了蔗彤。

<?xml version="1.0" encoding="utf-8"?>
<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:stretchColumns="1">

    <TableRow>
        <TextView
            android:layout_height="wrap_content"
            android:text="Account: "/>
        <EditText
            android:id="@+id/account"
            android:layout_height="wrap_content"
            android:hint="Input you account"/>
    </TableRow>

    <TableRow>
        <TextView
            android:layout_height="wrap_content"
            android:text="Password: " />
        <EditText
            android:id="@+id/password"
            android:layout_height="wrap_content"
            android:inputType="textPassword"/>
    </TableRow>

    <TableRow>
        <Button
            android:id="@+id/login"
            android:layout_height="wrap_content"
            android:layout_span="2"
            android:text="Login"/>
    </TableRow>

</TableLayout>
public class LoginActivity extends BaseActivity {
    private EditText accountEdit;
    private EditText passwordEdit;
    private Button login;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);
        setContentView(R.layout.login);
        accountEdit = (EditText) findViewById(R.id.account);
        passwordEdit = (EditText) findViewById(R.id.password);
        login = (Button) findViewById(R.id.login);
        login.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                String account = accountEdit.getText().toString();
                String password = passwordEdit.getText().toString();
                if (account.equals("254886715") && password.equals("Zh980728xl")){
                    Intent intent = new Intent(LoginActivity.this, FirstActivity.class);
                    startActivity(intent);
                    finish();
                } else
                    Toast.makeText(LoginActivity.this, "account or password is invalid", Toast.LENGTH_LONG).show();
            }
        });
    }
}

LoginActivity里判斷一下賬號(hào)密碼川梅,如果正確就進(jìn)入FirstActivity
后面的活動(dòng)我們只要實(shí)現(xiàn)一下強(qiáng)制下線就可以了然遏。
添加一個(gè)強(qiáng)制下線按鈕贫途,發(fā)送一條強(qiáng)制下線廣播,然后重寫一個(gè)廣播接收器就可以實(shí)現(xiàn)了啦鸣。

//廣播接收器
public class GetOutReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(final Context context, Intent intent){
        AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(context);
        dialogBuilder.setTitle("Warning");
        dialogBuilder.setMessage("You are forced to be offline. Please try to login again.");
        dialogBuilder.setCancelable(false);
        dialogBuilder.setPositiveButton("OK", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                ActivityCollector.finishAll();
                Intent intent = new Intent(context, LoginActivity.class);
                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(intent);
            }
        });
        AlertDialog alertDialog = dialogBuilder.create();
        alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
        alertDialog.show();
    }
}

這個(gè)廣播接收器里顯然不只是之前僅僅一個(gè)Toast那么簡(jiǎn)單潮饱,還加入了AlertDialog.Builder來構(gòu)建一個(gè)對(duì)話框,注意一定要調(diào)用setCancelable方法將對(duì)話框設(shè)置為不可取消诫给,然后使用setPositiveButton方法來給對(duì)話框注冊(cè)確定程序香拉,當(dāng)用戶點(diǎn)擊了確定按鈕,就調(diào)用ActivityCollectfinishAll方法來銷毀所有活動(dòng)中狂,因此一定要給Intent加入FLAG_ACTIVITY_NEW_TASK這個(gè)標(biāo)志凫碌,最后還需要把對(duì)話框里的類型設(shè)置為TYPE_SYSTEM_ALERT,不然會(huì)無法在廣播接收器里彈出胃榕。
這樣盛险,主要邏輯都完成了瞄摊。還需要注冊(cè)一下。
這里有幾點(diǎn)需要注意苦掘,首先由于我們?cè)?code>ForceOfflineReceiver里彈出了一個(gè)系統(tǒng)級(jí)別的對(duì)話框换帜,因此必須要進(jìn)行聲明android.permission.SYSTEM_ALERT_WINDOW權(quán)限,然后對(duì)LoginActivity進(jìn)行注冊(cè)鹤啡,并且把它設(shè)置為主活動(dòng)惯驼。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市递瑰,隨后出現(xiàn)的幾起案子祟牲,更是在濱河造成了極大的恐慌,老刑警劉巖抖部,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件说贝,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡慎颗,警方通過查閱死者的電腦和手機(jī)乡恕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來哗总,“玉大人几颜,你說我怎么就攤上這事⊙肚” “怎么了?”我有些...
    開封第一講書人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵县习,是天一觀的道長涮母。 經(jīng)常有香客問我,道長躁愿,這世上最難降的妖魔是什么叛本? 我笑而不...
    開封第一講書人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮彤钟,結(jié)果婚禮上来候,老公的妹妹穿的比我還像新娘。我一直安慰自己逸雹,他們只是感情好营搅,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著梆砸,像睡著了一般转质。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帖世,一...
    開封第一講書人閱讀 49,071評(píng)論 1 285
  • 那天休蟹,我揣著相機(jī)與錄音,去河邊找鬼。 笑死赂弓,一個(gè)胖子當(dāng)著我的面吹牛绑榴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播盈魁,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼翔怎,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了备埃?” 一聲冷哼從身側(cè)響起姓惑,我...
    開封第一講書人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎按脚,沒想到半個(gè)月后于毙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡辅搬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年唯沮,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片堪遂。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡介蛉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出溶褪,到底是詐尸還是另有隱情币旧,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布猿妈,位于F島的核電站吹菱,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏彭则。R本人自食惡果不足惜鳍刷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望俯抖。 院中可真熱鬧输瓜,春花似錦、人聲如沸芬萍。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽担忧。三九已至芹缔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間瓶盛,已是汗流浹背最欠。 一陣腳步聲響...
    開封第一講書人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來泰國打工示罗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人芝硬。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓蚜点,卻偏偏與公主長得像,于是被迫代替她去往敵國和親拌阴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子绍绘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

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