Service重啟流程

本文檔適合對Service的啟動和停止的fwk流程有一定了解的查看。

基礎知識

ServiceRecord


    boolean fgRequired;    // 是否請求的是前臺Service,完成后設置為false。

    boolean startRequested; //  是否是start方式啟動,在start權限校驗后才會賦值為true,Service stop后會賦值為false

    boolean isForeground;  // 當前Service是否是前臺Service,startForeground后賦值為true,stopForeground賦值為false

    boolean stopIfKilled;  // 跟onStartCommand返回值有關,START_STICKY_COMPATIBILITY/START_STICKY等為false;表示Service被殺后是否停止重啟;

    boolean callStart;      //  決定Service重啟后是否執(zhí)行onStartCommand,START_STICKY_COMPATIBILITY時會賦值為false

    int crashCount;        // number of times proc has crashed with service running

    int restartCount;      // 連續(xù)執(zhí)行的重啟次數(shù)

    long restartDelay;      // 下一次重啟的delay,scheduleServiceRestartLocked 賦值,啟動/停止/綁定時會重置為0

    long restartTime;      //上次調(diào)用realStartServiceLocked的時間

    long nextRestartTime;  // 當前時間+restartDelay

    int totalRestartCount;  // 不得不重啟的次數(shù)

    final ArrayList<StartItem> deliveredStarts = new ArrayList<StartItem>(); // 在sendServiceArgsLocked中會添加StartItem到這個列表中,執(zhí)行完serviceDoneExecutingLocked/或stop后會從該列表中移除,返回值為START_REDELIVER_INTENT時不會從列表中移除.

    final ArrayList<StartItem> pendingStarts = new ArrayList<StartItem>(); // startServiceInnerLocked時添加進列表,sendServiceArgsLocked 中移除;

StartItem


        long deliveredTime; // 在sendServiceArgsLocked中賦值,START_REDELIVER_INTENT返回值時,重啟時會根據(jù)這個計算延時時間

        int deliveryCount;  // 調(diào)用一次 sendServiceArgsLocked增加一次計數(shù),如果onStartCommand執(zhí)行失敗的次數(shù)超過兩次,后面就不會為這個intent重發(fā),主要針對START_REDELIVER_INTENT

        int doneExecutingCount;  //如果返回START_REDELIVER_INTENT時,則該引用計數(shù)+1

Service重啟時序圖

常見問題問答

image

什么情況下進程被殺后Service能重啟?

  1. start方式啟動時onStartCommand返回值是START_STICKY_COMPATIBILITY/START_STICKY/START_REDELIVER_INTENT之一

  2. Servive有flag是BIND_AUTO_CREATE的連接

  3. 進程被殺時Service還沒執(zhí)行完onStartCommand方法,導致deliverStarts中的額StartItem沒有被移除


    boolean canStopIfKilled(boolean isStartCanceled) {

        // onStartCommand返回值是START_STICKY_COMPATIBILITY/START_STICKY時,stopIfKilled為false;

        //  onStartCommand返回值是START_REDELIVER_INTENT時,這里的pendingStarts不為空

        return startRequested && (stopIfKilled || isStartCanceled) && pendingStarts.isEmpty();

    }

// Servive有flag是BIND_AUTO_CREATE的連接

    public boolean hasAutoCreateConnections() {

        for (int conni=connections.size()-1; conni>=0; conni--) {

            ArrayList<ConnectionRecord> cr = connections.valueAt(conni);

            for (int i=0; i<cr.size(); i++) {

                if ((cr.get(i).flags&Context.BIND_AUTO_CREATE) != 0) {

                    return true;

                }

            }

        }

        return false;

    }


    /** @return {@code true} if the restart is scheduled. */

    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {

            .......

            if (allowCancel) {

                // start方式啟動,返回值是START_STICKY_COMPATIBILITY/START_STICKY/START_REDELIVER_INTENT之一時,shouldStop為false

                final boolean shouldStop = r.canStopIfKilled(canceled);

                if (shouldStop && !r.hasAutoCreateConnections()) {

                    // Nothing to restart.

                    return false;

                }

                reason = (r.startRequested && !shouldStop) ? "start-requested" : "connection";

            } else {

                reason = "always";

            }

      .......

        return true;

    }

onStartCommand不同返回值有什么不同的效果?


@IntDef(flag = false, prefix = { "START_" }, value = {

        START_STICKY_COMPATIBILITY, // 重啟后只執(zhí)行onCreate

        START_STICKY, // 重啟后執(zhí)行onCreate、onStartCommand,但intent為null

        START_NOT_STICKY, // 不重啟

        START_REDELIVER_INTENT, //重啟后執(zhí)行onCreate、onStartCommand、intent不為null、onStartCommand可能執(zhí)行多次,重啟delay時間較長。

})

START_NOT_STICKY

進程被殺后Service不會被重啟 : 因為這里stopIfKilled賦值為true。


    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,

            boolean enqueueOomAdj) {

        boolean inDestroying = mDestroyingServices.contains(r);

        if (r != null) {

            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {

                // This is a call from a service start...  take care of

                // book-keeping.

                // 表明默認重啟后需要回調(diào)onStartCommand方法

                r.callStart = true;

                switch (res) {

                  ......

                    case Service.START_NOT_STICKY: {

                        // 查找并將當前StartItem從deliveredStarts列表中移除

                        r.findDeliveredStart(startId, false, true);

                        if (r.getLastStartId() == startId) {

                            // There is no more work, and this service

                            // doesn't want to hang around if killed.

                            r.stopIfKilled = true;

                        }

                        break;

                    }

            ......

            }.......

    }

START_STICKY_COMPATIBILITY

Service被殺死后會重啟(執(zhí)行了onCreate方法),但是onStartCommand方法沒有被執(zhí)行。


system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested

system_process I/ActivityManager: Start proc 7675:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication

com.example.myapplication D/MyService: onCreate


    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,

            boolean enqueueOomAdj) {

        boolean inDestroying = mDestroyingServices.contains(r);

        if (r != null) {

            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {

                // This is a call from a service start...  take care of

                // book-keeping.

                r.callStart = true;

                switch (res) {

                    case Service.START_STICKY_COMPATIBILITY:

                    case Service.START_STICKY: {

                        // We are done with the associated start arguments.

                        // 查找并將當前StartItem從deliveredStarts列表中移除

                        r.findDeliveredStart(startId, false, true);

                        // Don't stop if killed.

                        r.stopIfKilled = false;

                        break;

                    }

                .......

                }

                // 這里callStart賦值為false, 決定Service重啟后不執(zhí)行onStartCommand方法。

                if (res == Service.START_STICKY_COMPATIBILITY) {

                    r.callStart = false;

                }

            }.......

    }


    private void realStartServiceLocked(ServiceRecord r, ProcessRecord app,

            IApplicationThread thread, int pid, UidRecord uidRecord, boolean execInFg,

            boolean enqueueOomAdj) throws RemoteException {

        ......

        // callStart為false,則StartItem不會添加到pendingStarts列表;sendServiceArgsLocked方法中傳遞到app端的ServiceStartArgs列表會為空,導致不會遍歷執(zhí)行到onStartCommand方法

        if (r.startRequested && r.callStart && r.pendingStarts.size() == 0) {

            r.pendingStarts.add(new ServiceRecord.StartItem(r, false, r.makeNextStartId(),

                    null, null, 0));

        }

        // 從這個方法中會觸發(fā)app端回調(diào)Service的onStartCommand方法

        sendServiceArgsLocked(r, execInFg, true);

        .......

    }

START_STICKY

進程被殺后Service會被重啟,執(zhí)行onCreate和onStartCommand,重啟后的Intent為null。

具體代碼同START_STICKY_COMPATIBILITY。


com.example.myapplication D/MyService: onCreate

com.example.myapplication D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1

com.example.myapplication D/MyService: startResult= 1

system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 1000ms for start-requested

system_process I/ActivityManager: Start proc 4522:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication

com.example.myapplication D/MyService: onCreate

com.example.myapplication D/MyService: onStartCommand intent=null startId=2 // startID不一致,代表不是同一個實例,intent為null

com.example.myapplication D/MyService: startResult= 1

START_REDELIVER_INTENT

Service被殺死后會重啟(執(zhí)行了onCreate方法),并且onStartCommand方法會執(zhí)行。從startId可以看出兩個Service對象是同一個,并且onStartCommand方法中的intent和前一個intent值是一致的。


com.example.myapplication D/MyService: onCreate

com.example.myapplication D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1

com.example.myapplication D/MyService: startResult= 3

system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService in 17938ms for start-requested

system_process I/ActivityManager: Start proc 6307:com.example.myapplication/u0a270 for service {com.example.myapplication/com.example.myapplication.MyService} caller=com.example.myapplication

com.example.myapplication D/MyService: onCreate

com.example.myapplication D/MyService: onStartCommand intent=Intent { cmp=com.example.myapplication/.MyService (has extras) } startId=1

com.example.myapplication D/MyService: startResult= 3


    void serviceDoneExecutingLocked(ServiceRecord r, int type, int startId, int res,

            boolean enqueueOomAdj) {

        boolean inDestroying = mDestroyingServices.contains(r);

        if (r != null) {

            if (type == ActivityThread.SERVICE_DONE_EXECUTING_START) {

                // This is a call from a service start...  take care of

                // book-keeping.

                r.callStart = true;

                switch (res) {

                  ......

                    case Service.START_REDELIVER_INTENT: {鎖

                      // 這個返回值,執(zhí)行完Service的onStartCommand方法后,不會從deliverStarts列表中移除當前的StartItem,Service重啟時會遍歷deliverStarts列表,并將該列表中item添加到pendingStarts

                        ServiceRecord.StartItem si = r.findDeliveredStart(startId, false, false);

                        if (si != null) {

                            // 賦值為0,非0的話則表示app端的onStartCommand方法未正常執(zhí)行

                            si.deliveryCount = 0;

                            // 標明該StartItem的執(zhí)行成功的次數(shù)

                            si.doneExecutingCount++;

                            r.stopIfKilled = true;

                        }

                        break;

                    }

              .......

            }.......

    }


    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {

      .......

          // 非persistent app才會判斷重不重啟,persistent app直接重啟

        if ((r.serviceInfo.applicationInfo.flags

                &ApplicationInfo.FLAG_PERSISTENT) == 0) {

        ......

            final int N = r.deliveredStarts.size();

            // 針對START_REDELIVER_INTENT返回值,deliveredStarts不為空; 也有可能是進程被殺后onStartCommand方法還沒執(zhí)行完。

            if (N > 0) {

                for (int i=N-1; i>=0; i--) {

                    ServiceRecord.StartItem si = r.deliveredStarts.get(i);

                    si.removeUriPermissionsLocked();

                    if (si.intent == null) {

                        // We'll generate this again if needed.

                        // 同一個StartItem重啟失敗<3次或成功<6次才會繼續(xù)重啟

                    } else if (!allowCancel || (si.deliveryCount < ServiceRecord.MAX_DELIVERY_COUNT //3

                            && si.doneExecutingCount < ServiceRecord.MAX_DONE_EXECUTING_COUNT)) { //6

                        // 將列表中item添加到pendingStarts

                        r.pendingStarts.add(0, si);

                        long dur = SystemClock.uptimeMillis() - si.deliveredTime;

                        dur *= 2;

                        // minDuration和resetTime賦值,一般是當前時間到deliver的時間間隔(下面稱作devliver Duration),所以重啟delay時間會很長,超過1s。

                        if (minDuration < dur) minDuration = dur;

                        if (resetTime < dur) resetTime = dur;

                    } else {

                        // 否則直接取消重啟

                        Slog.w(TAG, "Canceling start item " + si.intent + " in service "

                                + r.shortInstanceName);

                        canceled = true;

                    }

                }

                // 清空Service的deliveredStarts的列表

                r.deliveredStarts.clear();

            }

Bind情況下如何重啟?

Service有BIND_AUTO_CREATE的連接


com.example.testapplication D/MainActivity: flags= 1

com.example.myapplication D/MyService2: onCreate

com.example.myapplication D/MyService2: onBind

com.example.testapplication D/MainActivity: onServiceConnected

com.example.testapplication D/MainActivity: onServiceDisconnected

ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService2 in 10043ms for connection

ActivityManager: Start proc 10102:com.example.myapplication:remote/u0a253 for service {com.example.myapplication/com.example.myapplication.MyService2} caller=com.example.testapplication

com.example.myapplication D/MyService2: onCreate

com.example.myapplication D/MyService2: onBind

com.example.testapplication D/MainActivity: onServiceConnected

先bindService再startService


com.example.myapplication D/MyService2: onCreate

com.example.myapplication D/MyService2: onBind

com.example.myapplication D/MyService2: onStartCommand

com.example.testapplication D/MainActivity: onServiceConnected

com.example.testapplication D/MainActivity: onServiceDisconnected

system_process W/ActivityManager: Scheduling restart of crashed service com.example.myapplication/.MyService2 in 1000ms for start-requested

system_process I/ActivityManager: Start proc 13953:com.example.myapplication:remote/u0a253 for service {com.example.myapplication/com.example.myapplication.MyService2} caller=com.example.myapplication

com.example.myapplication D/MyService2: onCreate

com.example.myapplication D/MyService2: onBind

com.example.testapplication D/MainActivity: onServiceConnected

com.example.myapplication D/MyService2: onStartCommand

重啟時間如何計算?

首次重啟

1. 如果是START_REDELIVER_INTENT返回值,重啟delay時間一般為 (當前時間 - 上次deliver時間)*2,這個時間一般較長。

1. 其它重啟時間為1s。

app發(fā)生過crash

重啟delay時間為1800s*(crashCount -1)

非首次重啟

1. START_REDELIVER_INTENT返回值, 當前時間距離上次重啟 > 60s(或deliverDuration) ,則重啟delay一般為deliverDuration;否則重啟delay*60s。

1. 其它,當前時間距離上次重啟 > 60s,則重啟delay為1s,否則delay * 60s。

最后需要保證兩個重啟的Service時間間隔不得<10s


    /** @return {@code true} if the restart is scheduled. */

    private final boolean scheduleServiceRestartLocked(ServiceRecord r, boolean allowCancel) {

        ......

        final long now = SystemClock.uptimeMillis();

        final String reason;

        if ((r.serviceInfo.applicationInfo.flags

                &ApplicationInfo.FLAG_PERSISTENT) == 0) {

            long minDuration = mAm.mConstants.SERVICE_RESTART_DURATION; //1s

            long resetTime = mAm.mConstants.SERVICE_RESET_RUN_DURATION; //60s

            boolean canceled = false;

            ........

            // 第一次重啟

            if (r.restartDelay == 0) {

                r.restartCount++;

                r.restartDelay = minDuration;

                // crash重啟時間為1800s * n

            } else if (r.crashCount > 1) {

                r.restartDelay = mAm.mConstants.BOUND_SERVICE_CRASH_RESTART_DURATION

                        * (r.crashCount - 1);

            } else {

                // 如果這次重啟距離上次重啟>60s(或者deliverDuration),重置delay為minDuration(非Deliver一般為1s)

                if (now > (r.restartTime+resetTime)) {

                    r.restartCount = 1;

                    r.restartDelay = minDuration;

                } else {

                    // 如果重啟后很快又被殺,則delay需要* 60s的系數(shù),增大重啟延時

                    r.restartDelay *= mAm.mConstants.SERVICE_RESTART_DURATION_FACTOR;

                    if (r.restartDelay < minDuration) {

                        r.restartDelay = minDuration;

                    }

                }

            }

            if (isServiceRestartBackoffEnabledLocked(r.packageName)) {

                // 計算下次重啟時間

                r.nextRestartTime = now + r.restartDelay;

                // Make sure that we don't end up restarting a bunch of services

                // all at the same time.

                boolean repeat;

                final long restartTimeBetween = mAm.mConstants.SERVICE_MIN_RESTART_TIME_BETWEEN; //10s

                do {

                    // 避免一次重啟太多的Service,至少保證10s的時間間隔

                    repeat = false;

                    for (int i = mRestartingServices.size() - 1; i >= 0; i--) {

                        final ServiceRecord r2 = mRestartingServices.get(i);

                        if (r2 != r

                                && r.nextRestartTime >= (r2.nextRestartTime - restartTimeBetween)

                                && r.nextRestartTime < (r2.nextRestartTime + restartTimeBetween)) {

                            r.nextRestartTime = r2.nextRestartTime + restartTimeBetween;

                            r.restartDelay = r.nextRestartTime - now;

                            repeat = true;

                            break;

                        }

                    }

                } while (repeat);

            } else {

                // It's been forced to ignore the restart backoff, fix the delay here.

                r.restartDelay = mAm.mConstants.SERVICE_RESTART_DURATION;

                r.nextRestartTime = now + r.restartDelay;

            }

        } else {

            // Persistent processes are immediately restarted, so there is no

            // reason to hold of on restarting their services.

            // persistent app立刻被拉起

            r.totalRestartCount++;

            r.restartCount = 0;

            r.restartDelay = 0;

            r.nextRestartTime = now;

            reason = "persistent";

        }

        if (!mRestartingServices.contains(r)) {

            r.createdFromFg = false;

            mRestartingServices.add(r);

            synchronized (mAm.mProcessStats.mLock) {

                r.makeRestarting(mAm.mProcessStats.getMemFactorLocked(), now);

            }

        }

        cancelForegroundNotificationLocked(r);

        // 開始shedule重啟

        performScheduleRestartLocked(r, "Scheduling", reason, SystemClock.uptimeMillis());

        return true;

    }

如何規(guī)避非預期的Service重啟

背景

一鍵清理時會先執(zhí)行removeTask操作,未添加FLAG_STOP_WITH_TASK flag的Service會觸發(fā)執(zhí)行一次onStartCommand方法,且在sendServiceArgsLocked中執(zhí)行完后將新創(chuàng)建的StartItem從pendingStarts列表移動到deliveredStarts列表。這時候再執(zhí)行殺進程會導致app端未能及時告知system server端執(zhí)行serviceDoneExecutingLocked方法去移除deliveredStarts中的StartItem,導致進程被殺后還會立刻通過Service拉起來。


10-12 15:52:22.108 2489 3967 I ProcessManager: OneKeyClean: kill com.miui.huanji:backup Adj=100 State=4

10-12 15:52:22.122 2489 3967 I ProcessManager: OneKeyClean: kill com.miui.huanji Adj=50 State=4

10-12 15:52:22.144 2489 7247 W ActivityManager: Scheduling restart of crashed service com.miui.huanji/.backup.BackupService in 1000ms for connection

10-12 15:52:22.292 2489 7443 W ActivityManager: Scheduling restart of crashed service com.miui.huanji/.scanner.ScannerService in 50853ms for start-requested

代碼邏輯

image

    void cleanUpServices(int userId, ComponentName component, Intent baseIntent) {

        ArrayList<ServiceRecord> services = new ArrayList<>();

        ArrayMap<ComponentName, ServiceRecord> alls = getServicesLocked(userId);

        for (int i = alls.size() - 1; i >= 0; i--) {

            ServiceRecord sr = alls.valueAt(i);

            if (sr.packageName.equals(component.getPackageName())) {

                services.add(sr);

            }

        }

        // Take care of any running services associated with the app.

        boolean needOomAdj = false;

        for (int i = services.size() - 1; i >= 0; i--) {

            ServiceRecord sr = services.get(i);

            if (sr.startRequested) {

                if ((sr.serviceInfo.flags&ServiceInfo.FLAG_STOP_WITH_TASK) != 0) {

                    Slog.i(TAG, "Stopping service " + sr.shortInstanceName + ": remove task");

                    needOomAdj = true;

                    stopServiceLocked(sr, true);

                } else {

                    // 讓app端觸發(fā)onTaskRemoved方法

                    sr.pendingStarts.add(new ServiceRecord.StartItem(sr, true,

                            sr.getLastStartId(), baseIntent, null, 0));

                    if (sr.app != null && sr.app.getThread() != null) {

                        // We always run in the foreground, since this is called as

                        // part of the "remove task" UI operation.

                        try {

                            sendServiceArgsLocked(sr, true, false);

                        } catch (TransactionTooLargeException e) {

                            // Ignore, keep going.

                        }

                    }

                }

            }

        }

        if (needOomAdj) {

            mAm.updateOomAdjPendingTargetsLocked(OomAdjuster.OOM_ADJ_REASON_UNBIND_SERVICE);

        }

    }

解決方案

后期cleanUpService是異步執(zhí)行的不會有這個問題(即殺進程會在cleanUpServices之前,沒有Service會被遍歷到),當時讓app在功能清單文件中配置android.R.attr#stopWithTask。

Service重啟三千問

1. 什么情況下進程被殺后Service能重啟?Start方式和bind方式的區(qū)別?

1. onStartCommand返回值START_STICKY_COMPATIBILITY/START_STICKY和START_REDELIVER_INTENT實現(xiàn)Service重啟 有什么區(qū)別?

1. onStartCommand不同返回值有什么不同的效果?

1. 什么返回值Service重啟后不執(zhí)行onStartCommand?

1. 什么返回值Service重啟不用重新發(fā)送intent?

1. 哪些情況下Service會被更快的重啟?

1. START_REDELIVER_INTENT 重啟時app的Service會執(zhí)行幾次onStartCommand?

1. start方式啟動的Service的stopIfKilled為true時,Service一定不可以重啟么?

1. deliveredStarts 什么時候添加?什么時候移除?

1. pendingStarts 什么時候添加?什么時候移除?

1. Service重啟的restartDelay的計算邏輯?

1. 什么情況下START_REDELIVER_INTENT返回值不再執(zhí)行重啟?

參考文檔:http://www.lxweimin.com/p/7a659ca38510

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

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