Android自定義快速設(shè)置

Android自定義快速設(shè)置

Customizer Quick Setting

自定義快速設(shè)置

Android N/7.0 牛軋?zhí)?/p>

前言

Android N在2016年5月的Google I/O大會(huì)上發(fā)布,按照過往歷史赦邻,同樣會(huì)用一種水果的名稱稱呼這個(gè)新的Andrid版本设塔,但是Google I/O上,并沒有為Android N定好名字匣吊,直到6月份通過投票的形式正式命名為“牛軋?zhí)恰薄ndroid N在安全和用戶體驗(yàn)上都有較大的更新,如多窗口支持、通知增強(qiáng)功能宗收、配置文件指導(dǎo)的 JIT/AOT 編譯、隨時(shí)隨地低電耗模式和Quick Settings Tile等等亚兄。本文對(duì)Android N的新功能Quick Settings Tile(快速設(shè)置圖塊)的應(yīng)用進(jìn)行詳解混稽。

所謂快速設(shè)置圖塊,即下拉通知欄時(shí)的快速設(shè)置按鈕审胚,通常用于直接從通知欄顯示關(guān)鍵設(shè)置和操作匈勋,非常簡單。如Wifi的開關(guān)膳叨、數(shù)據(jù)連接洽洁、飛行模式和藍(lán)牙等等。當(dāng)然這個(gè)功能在Andorid中一直都有菲嘴,Android N做了那些升級(jí)更新呢饿自?如下:

  • 額外的“快速設(shè)置”圖塊添加了更多空間,用戶可以通過向左或向右滑動(dòng)跨分頁的顯示區(qū)域訪問它們龄坪。我們還讓用戶可以控制顯示哪些“快速設(shè)置”圖塊以及顯示的位置 — 用戶可以通過拖放圖塊來添加或移動(dòng)圖塊昭雌。
  • 對(duì)于開發(fā)者,Android 7.0 還添加了一個(gè)新的 API健田,從而讓您可以定義自己的“快速設(shè)置”圖塊烛卧,使用戶可以輕松訪問您應(yīng)用中的關(guān)鍵控件和操作。

第一點(diǎn)更新妓局,如下圖总放,用戶可以左右滑動(dòng)快速設(shè)置面板,比之前的版本增大了一倍的空間:

20170221113312839.png

第二點(diǎn)更新好爬,也就是本文要介紹的功能更新局雄,它讓APP開發(fā)者也可以為自己的應(yīng)用定制一個(gè)快速設(shè)置圖塊,而之前的版本只能對(duì)系統(tǒng)的功能進(jìn)行設(shè)置抵拘,這對(duì)用戶常用的APP哎榴,可能會(huì)帶來很大的方便性型豁。

既然是快速設(shè)置,所以Google建議:對(duì)于急需或頻繁使用的控件和操作尚蝌,保留“快速設(shè)置”圖塊迎变,且不應(yīng)將其用作啟動(dòng)應(yīng)用的快捷方式。所以APP開發(fā)者飘言,應(yīng)該遵行Google的功能設(shè)計(jì)初衷衣形,以便讓用戶能夠有更好地用戶體驗(yàn)。

自定義快速設(shè)置圖塊

APP要實(shí)現(xiàn)自定義快速設(shè)置圖塊很簡單姿鸿,只需需要兩步即可:

第一步:定義一個(gè)MyQSTileService繼承frameworks/base/core/java/android/service/quicksettings/TileService.java谆吴,如下:

public class MyQSTileService extends TileService {
    //Called when the user adds this tile to Quick Settings.
    @Override
    public void onTileAdded() {
        super.onTileAdded();
    }

    //Called when the user removes this tile from Quick Settings.
    @Override
    public void onTileRemoved() {
        super.onTileRemoved();
    }

    //Called when this tile moves into a listening state.
    @Override
    public void onStartListening() {
        super.onStartListening();
    }

    //Called when this tile moves out of the listening state.
    @Override
    public void onStopListening() {
        super.onStopListening();
    }

    //Called when the user clicks on this tile.
    @Override
    public void onClick() {
        super.onClick();
    }
}

如上面的代碼,創(chuàng)建一個(gè)MyQSTileService繼承TileService苛预,復(fù)寫onTileAdded()句狼、onTileRemoved()、onStartListening()热某、onStopListening()和onClick()方法腻菇。

第二步:在項(xiàng)目的AndroidManifest.xml文件中添加如下代碼:

<service
    android:name=".MyQSTileService"
    android:label="@string/my_default_tile_label"
    android:icon="@drawable/my_default_icon_label"
    android:permission="android.permission.BIND_QUICK_SETTINGS_TILE">
    <intent-filter>
        <action android:name="android.service.quicksettings.action.QS_TILE" />
    </intent-filter>
</service>

上述代碼,android:name和android:label就不多說了昔馋,這里側(cè)重看android:icon筹吐,android:permission和action。android:icon雖然是老版本就有的秘遏,但是
TileService必須指明這個(gè)屬性丘薛,快速設(shè)置才會(huì)生效。既然是快速設(shè)置圖塊邦危,就需要一張圖片洋侨,所以這個(gè)icon肯定不能為空啦,要不還怎么顯示铡俐。本例子添加的圖片如下高亮的圖片:


20170221113346936.png

然后必須在TileService中聲明權(quán)限android.permission.BIND_QUICK_SETTINGS_TILE凰兑,這是Android安全的套路妥粟。最后action也是必不可少审丘,系統(tǒng)就是通過android.service.quicksettings.action.QS_TILE這個(gè)Action來尋找所有APP的TileService,后文會(huì)贅述這個(gè)過程勾给。

只需兩步滩报,即可實(shí)現(xiàn)自定義的Tile顯示在下拉菜單的快速設(shè)置面板中。如下圖所以:

20170221113407593.png

如上圖播急,最后一個(gè)便是本例子自定義的快速設(shè)置圖塊脓钾,當(dāng)然,現(xiàn)在這個(gè)圖塊只是在備選區(qū)域桩警,用戶可以把這個(gè)圖塊拖動(dòng)到快速設(shè)置面板可训,就可以實(shí)現(xiàn)真正的快速設(shè)置了,如下圖中間的圖塊:


20170221113428497.png

實(shí)現(xiàn)自定義快速設(shè)置圖塊,就是這么簡單握截,但是只是這樣飞崖,對(duì)用戶使用體驗(yàn)不是很舒服,因?yàn)檫@個(gè)圖塊只有一種顏色谨胞,用戶不知道當(dāng)前是關(guān)固歪,或者是開的狀態(tài)。因此胯努,還需要根據(jù)實(shí)際開/關(guān)的狀態(tài)牢裳,改變圖塊的顏色。當(dāng)用戶點(diǎn)擊一次圖塊叶沛,狀態(tài)就要發(fā)生變化蒲讯。實(shí)現(xiàn)代碼如下:

public class MyQSTileService extends TileService {
    @Override
    public void onTileAdded() {
        Log.d("MyQSTileService", "onTileAdded()");
    }
    ......
    
    @Override
    public void onClick() {
        Log.d("MyQSTileService", "onClick()");
        //獲取自定義的Tile.
        Tile tile = getQsTile();
        if (tile == null) {
            return;
        }
        Log.d("MyQSTileService", "Tile state: " + tile.getState());
        switch (tile.getState()) {
            case Tile.STATE_ACTIVE:
                //當(dāng)前狀態(tài)是開,設(shè)置狀態(tài)為關(guān)閉.
                tile.setState(Tile.STATE_INACTIVE);
                //更新快速設(shè)置面板上的圖塊的顏色灰署,狀態(tài)為關(guān).
                tile.updateTile();
                //do close somethings.
                break;
            case Tile.STATE_UNAVAILABLE:
                break;
            case Tile.STATE_INACTIVE:
                //當(dāng)前狀態(tài)是關(guān)伶椿,設(shè)置狀態(tài)為開.
                tile.setState(Tile.STATE_ACTIVE);
                //更新快速設(shè)置面板上的圖塊的顏色,狀態(tài)為開.
                tile.updateTile();
                //do open somethings.
                break;
            default:
                break;
        }
    }
}

如上面的代碼氓侧,當(dāng)用戶點(diǎn)擊的自定義的圖塊脊另,將會(huì)回調(diào)onClick()方法,在這個(gè)方法里约巷,首先獲取到當(dāng)前的Tile偎痛,調(diào)用Tile的getState()方法獲取當(dāng)期Tile的狀態(tài),如果狀態(tài)正處于打開的狀態(tài)独郎,調(diào)用setState()的方法改變狀態(tài)為關(guān)閉踩麦,然后一定要調(diào)用updateTile()這個(gè)方法,快速設(shè)置面板上的圖塊顏色才會(huì)改變氓癌。如下圖谓谦,CusTile為打開的狀態(tài):


20170221113458857.png

下圖是CusTile是關(guān)閉的狀態(tài):


20170221113520639.png

除此之外,Tile還提供如下兩個(gè)方法贪婉,以便APP可以給用戶更為舒適的用戶體驗(yàn)反粥。檢測當(dāng)前設(shè)備是否處于鎖屏狀態(tài),方法如下:

//Checks if the lock screen is showing.
public final boolean isLocked() {
    try {
        return mService.isLocked();
    } catch (RemoteException e) {
        return true;
    }
}

檢測當(dāng)期設(shè)備是否處于安全模式疲迂,如圖案解鎖才顿,方法如下:

//Checks if the device is in a secure state.
public final boolean isSecure() {
    try {
        return mService.isSecure();
    } catch (RemoteException e) {
        return true;
    }
}

用戶在操作時(shí),APP應(yīng)該使用這兩個(gè)方法判斷一下是否應(yīng)該改變APP的行為尤蒿。另外郑气,TileService還提供startActivityAndCollapse()等方法讓APP開發(fā)者可以用更少的代碼實(shí)現(xiàn)超棒的用戶體驗(yàn),這也是一個(gè)非常棒的方法腰池。讀者可以自行閱讀幫助文檔了解TileService提供的功能尾组,以便更好地開發(fā)自己的應(yīng)用忙芒。

深入理解TileService

TileService的結(jié)構(gòu)

快速設(shè)置面板是SystemUI提供的功能,如果讀者不熟悉SystemUI的讳侨,可以閱讀文章《SystemUI架構(gòu)分析 》匕争,也就是說自定義快速設(shè)置圖塊的點(diǎn)擊等行為已經(jīng)發(fā)生了跨進(jìn)程通信,SystemUI是如果調(diào)用到APP的呢爷耀?以Anroid四大組件之一的Service如何建立IPC通信開始甘桑,從Service的生命周期onBind()說起:

public class TileService extends Service {
    public IBinder onBind(Intent intent) {
        mService = IQSService.Stub.asInterface(intent.getIBinderExtra(EXTRA_SERVICE));
        try {
            ComponentName component = intent.getParcelableExtra(EXTRA_COMPONENT);
            mTile = mService.getTile(component);
        } catch (RemoteException e) {
            throw new RuntimeException("Unable to reach IQSService", e);
        }
        if (mTile != null) {
            mTile.setService(mService);
            mHandler.sendEmptyMessage(H.MSG_START_SUCCESS);
        }
        return new IQSTileService.Stub() {
            @Override
            public void onTileRemoved() throws RemoteException {
                mHandler.sendEmptyMessage(H.MSG_TILE_REMOVED);
            }

            @Override
            public void onTileAdded() throws RemoteException {
                mHandler.sendEmptyMessage(H.MSG_TILE_ADDED);
            }

            @Override
            public void onStopListening() throws RemoteException {
                mHandler.sendEmptyMessage(H.MSG_STOP_LISTENING);
            }

            @Override
            public void onStartListening() throws RemoteException {
                mHandler.sendEmptyMessage(H.MSG_START_LISTENING);
            }

            @Override
            public void onClick(IBinder wtoken) throws RemoteException {
                mHandler.obtainMessage(H.MSG_TILE_CLICKED, wtoken).sendToTarget();
            }

            @Override
            public void onUnlockComplete() throws RemoteException{
                mHandler.sendEmptyMessage(H.MSG_UNLOCK_COMPLETE);
            }
        };
    }
}

如上面的代碼,如上這些方法是不是很熟悉呢歹叮。當(dāng)SystemUI啟動(dòng)TileService時(shí)跑杭,回調(diào)onBind()方法,TileService創(chuàng)建一個(gè)IQSTileService.Stub的實(shí)例咆耿,IQSTileService正好就是實(shí)現(xiàn)了AIDL標(biāo)準(zhǔn)的IPC通信的接口德谅,所以,onBind()方法把IQSTileService的句柄返回給SystemUI萨螺,因此SystemUI便可實(shí)現(xiàn)對(duì)TileService的遠(yuǎn)程調(diào)用窄做。SystemUI通過橋梁IQSTileService便可和APP實(shí)現(xiàn)緊密快速的通信。

TileService的加載

通過文章《SystemUI架構(gòu)分析 》可知慰技,負(fù)責(zé)快速設(shè)置面板顯示的控件是rameworks/base/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java椭盏,自定義快速設(shè)置圖塊的APP安裝到系統(tǒng)后,當(dāng)用戶點(diǎn)擊編輯快速設(shè)置面板的編輯按鈕時(shí)吻商,調(diào)用QSPanel的showEdit()方法掏颊,如下:

public class QSPanel extends LinearLayout implements Tunable, Callback {
    private void showEdit(final View v) {
        v.post(new Runnable() {
            @Override
            public void run() {
                ......
                        mCustomizePanel.show(x, y);
                    }
                }
            }
        });
    }
}

接著上面的代碼,然后調(diào)用通過QSCustomizer實(shí)例mCustomizePanel調(diào)用show()方法艾帐,后面接著會(huì)生成一個(gè)TileQueryHelper的對(duì)象乌叶,調(diào)用addSystemTiles()方法,這個(gè)過程就不贅述了柒爸,下面直接看addSystemTiles()的代碼:

public class TileQueryHelper {
    private void addSystemTiles(final QSTileHost host) {
        ......
        qsHandler.post(new Runnable() {
            @Override
            public void run() {
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        new QueryTilesTask().execute(host.getTiles());
                    }
                });
            }
        });
    }
}

上面的代碼啟動(dòng)了多線程任務(wù)類QueryTilesTask准浴,看在新的線程里,如果加載自定義的快速設(shè)置圖塊捎稚,代碼如下:

public class TileQueryHelper {
        private class QueryTilesTask extends
            AsyncTask<Collection<QSTile<?>>, Void, Collection<TileInfo>> {
        @Override
        protected Collection<TileInfo> doInBackground(Collection<QSTile<?>>... params) {
            List<TileInfo> tiles = new ArrayList<>();
            PackageManager pm = mContext.getPackageManager();
            List<ResolveInfo> services = pm.queryIntentServicesAsUser(
                    new Intent(TileService.ACTION_QS_TILE), 0, ActivityManager.getCurrentUser());
            for (ResolveInfo info : services) {
                String packageName = info.serviceInfo.packageName;
                ComponentName componentName = new ComponentName(packageName, info.serviceInfo.name);
                final CharSequence appLabel = info.serviceInfo.applicationInfo.loadLabel(pm);
                String spec = CustomTile.toSpec(componentName);
                State state = getState(params[0], spec);
                if (state != null) {
                    addTile(spec, appLabel, state, false);
                    continue;
                }
                if (info.serviceInfo.icon == 0 && info.serviceInfo.applicationInfo.icon == 0) {
                    continue;
                }
                Drawable icon = info.serviceInfo.loadIcon(pm);
                if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
                    continue;
                }
                if (icon == null) {
                    continue;
                }
                icon.mutate();
                icon.setTint(mContext.getColor(android.R.color.white));
                CharSequence label = info.serviceInfo.loadLabel(pm);
                addTile(spec, icon, label != null ? label.toString() : "null", appLabel, mContext);
            }
            return tiles;
        }


}

上面的代碼有點(diǎn)多乐横,從上到下,慢慢來看阳藻,首先晰奖,是通過PackageManager查詢action為TileService.ACTION_QS_TILE的service,看TileService.ACTION_QS_TILE這個(gè)值:

public static final String ACTION_QS_TILE = "android.service.quicksettings.action.QS_TILE";

正好是上文中的例子中的APP中MyQSTileService在AndroidManifest.xml中聲明的action一致腥泥,往下看一個(gè)if語句:

if (info.serviceInfo.icon == 0 && info.serviceInfo.applicationInfo.icon == 0) {
    continue;
}

這條if語句就是判斷TileService中是否聲明了icon,如果沒有啃匿,則無法添加快速設(shè)置圖塊蛔外,所以AndroidManifest.xml中對(duì)MyQSTileService一定要聲明icon蛆楞。再往下看另外一個(gè)if語句:

if (!permission.BIND_QUICK_SETTINGS_TILE.equals(info.serviceInfo.permission)) {
    continue;
}

這里檢測了permission.BIND_QUICK_SETTINGS_TILE全新,因此AndroidManifest.xml中對(duì)MyQSTileService一定要聲明android.permission.BIND_QUICK_SETTINGS_TILE權(quán)限夹厌。再往下看豹爹,有icon.setTint(mContext.getColor(android.R.color.white)),這個(gè)方法就是把圖塊強(qiáng)制繪制成白色矛纹,這個(gè)在Android的扁平化設(shè)計(jì)中強(qiáng)制的行為臂聋,所以APP用一些五顏六色圖片時(shí)沒有用的,最終都會(huì)變成白色或南。最后調(diào)用addTile()方法添加到快速設(shè)置面板了孩等。TileService的加載就分析到這里。下面看看TileService是如何啟動(dòng)的采够?什么時(shí)候啟動(dòng)肄方?

TileService的啟動(dòng)

在frameworks/base/packages/SystemUI/src/com/android/systemui/qs/external/TileLifecycleManager.java中,會(huì)注冊(cè)一個(gè)監(jiān)聽APK安裝與卸載的廣播接收者蹬癌,當(dāng)自定義了快速設(shè)置圖塊的APK被安裝時(shí)权她,會(huì)觸發(fā)這個(gè)廣播接收者:

public class TileLifecycleManager extends BroadcastReceiver ...... {
    public void onReceive(Context context, Intent intent) {
        ......
        if (Intent.ACTION_PACKAGE_CHANGED.equals(intent.getAction()) && mChangeListener != null) {
            mChangeListener.onTileChanged(mIntent.getComponent());
        }
        stopPackageListening();
        if (mBound) {
            // Trying to bind again will check the state of the package before bothering to bind.
            if (DEBUG) Log.d(TAG, "Trying to rebind");
            setBindService(true);
        }
    }
}

APK安裝時(shí)觸發(fā)廣播接收器,調(diào)用setBindService(true)方法逝薪,如下:

    public void setBindService(boolean bind) {
        mBound = bind;
        ......
            try {
                mIsBound = mContext.bindServiceAsUser(mIntent, this,
                        Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE_WHILE_AWAKE,
                        mUser);
            ......
        }
    }

如上面的代碼隅要,通過bindServiceAsUser()啟動(dòng)了TileService,Service連接后董济,回調(diào)ServiceConnection的onServiceConnected()拾徙,如下:

public void onServiceConnected(ComponentName name, IBinder service) {
    .....
    final QSTileServiceWrapper wrapper = new QSTileServiceWrapper(Stub.asInterface(service));
    .....
    mWrapper = wrapper;
    handlePendingMessages();
}

如上面的代碼,IBinder保存到QSTileServiceWrapper中感局,Stub.asInterface(service)正是TileService的遠(yuǎn)程調(diào)用句柄尼啡,本質(zhì)是上文中提到的IQSTileService.Stub。然后快速這只的一切事件將會(huì)通過QSTileServiceWrapper的實(shí)例wrapper調(diào)用询微,如下:

public class QSTileServiceWrapper {
    private static final String TAG = "IQSTileServiceWrapper";

    private final IQSTileService mService;

    public QSTileServiceWrapper(IQSTileService service) {
        mService = service;
    }

    public IBinder asBinder() {
        return mService.asBinder();
    }

    public boolean onTileAdded() {
        try {
            mService.onTileAdded();
            return true;
        } catch (Exception e) {
            Log.d(TAG, "Caught exception from TileService", e);
            return false;
        }
    }

    public boolean onTileRemoved() {
        ......
    }

    public boolean onStartListening() {
        ......
    }

    public boolean onStopListening() {
        ......
    }

    public boolean onClick(IBinder token) {
        ......
    }

    public boolean onUnlockComplete() {
        ......
    }
}

TileService的啟動(dòng)就分析到這里崖瞭,SystemUI對(duì)快速設(shè)置圖塊的添加、移除和點(diǎn)擊等等事件撑毛,通過wrapper最后調(diào)用到APP的TileService书聚。

總結(jié)

本文詳細(xì)描述了Android N的新功能自定義設(shè)置圖塊的實(shí)現(xiàn)方法,以及原理藻雌,這個(gè)功能的核心是TileService雌续,提供了SystemUI和自定義設(shè)置圖塊的APP進(jìn)行緊密的通信的基礎(chǔ)。作為APP的開發(fā)者胯杭,或許快速設(shè)置圖塊將會(huì)是一個(gè)APP提升用戶體驗(yàn)的一種重要途徑驯杜。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市做个,隨后出現(xiàn)的幾起案子鸽心,更是在濱河造成了極大的恐慌滚局,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,490評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件顽频,死亡現(xiàn)場離奇詭異藤肢,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)糯景,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門嘁圈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人蟀淮,你說我怎么就攤上這事最住。” “怎么了灭贷?”我有些...
    開封第一講書人閱讀 165,830評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵温学,是天一觀的道長。 經(jīng)常有香客問我甚疟,道長仗岖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評(píng)論 1 295
  • 正文 為了忘掉前任览妖,我火速辦了婚禮轧拄,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘讽膏。我一直安慰自己檩电,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,974評(píng)論 6 393
  • 文/花漫 我一把揭開白布府树。 她就那樣靜靜地躺著俐末,像睡著了一般。 火紅的嫁衣襯著肌膚如雪奄侠。 梳的紋絲不亂的頭發(fā)上卓箫,一...
    開封第一講書人閱讀 51,754評(píng)論 1 307
  • 那天,我揣著相機(jī)與錄音垄潮,去河邊找鬼烹卒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛弯洗,可吹牛的內(nèi)容都是我干的旅急。 我是一名探鬼主播,決...
    沈念sama閱讀 40,464評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼牡整,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼藐吮!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,357評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤炎码,失蹤者是張志新(化名)和其女友劉穎盟迟,沒想到半個(gè)月后秋泳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體潦闲,經(jīng)...
    沈念sama閱讀 45,847評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,995評(píng)論 3 338
  • 正文 我和宋清朗相戀三年迫皱,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了歉闰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,137評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡卓起,死狀恐怖和敬,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情戏阅,我是刑警寧澤昼弟,帶...
    沈念sama閱讀 35,819評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站奕筐,受9級(jí)特大地震影響舱痘,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜离赫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,482評(píng)論 3 331
  • 文/蒙蒙 一芭逝、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渊胸,春花似錦旬盯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至切厘,卻和暖如春萨咳,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背迂卢。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評(píng)論 1 272
  • 我被黑心中介騙來泰國打工某弦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人而克。 一個(gè)月前我還...
    沈念sama閱讀 48,409評(píng)論 3 373
  • 正文 我出身青樓靶壮,卻偏偏與公主長得像,于是被迫代替她去往敵國和親员萍。 傳聞我的和親對(duì)象是個(gè)殘疾皇子腾降,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,086評(píng)論 2 355

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