PendingIntent产生以及响应

PendingIntent
PendingIntent 将会发生的意图
主要有四种Activity、BroadcastReceiver、Service
Activity(BroadcastReceiver、Service类似只是在type不同)

/*
flags有5种
public static final int FLAG_ONE_SHOT = 1<<30; send()只会执行一次,再次send()会失败
public static final int FLAG_NO_CREATE = 1<<29; PendingIntent不存在,直接是null
public static final int FLAG_CANCEL_CURRENT = 1<<28; PendingIntent存在,生成新的会把旧的取消掉
public static final int FLAG_UPDATE_CURRENT = 1<<27; PendingIntent存在,只更新Intent
public static final int FLAG_IMMUTABLE = 1<<26; PengdingIntent存在后就不变了。
*/
public static PendingIntent getActivity(Context context, int requestCode,
            @NonNull Intent intent, @Flags int flags, @Nullable Bundle options) {
    String packageName = context.getPackageName();
    String resolvedType = intent != null ? intent.resolveTypeIfNeeded(
        context.getContentResolver()) : null;
    try {
        intent.migrateExtraStreamToClipData();
        intent.prepareToLeaveProcess(context);
        IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
            ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
            null, null, requestCode, new Intent[] { intent },
            resolvedType != null ? new String[] { resolvedType } : null,
            flags, options, UserHandle.myUserId());
        //new出PendingIntent参数是target(IIntentSender客户端)
        return target != null ? new PendingIntent(target) : null;
    } catch (RemoteException e) {
    }
    return null;
}


IIntentSender target =
            ActivityManagerNative.getDefault().getIntentSender(
            ActivityManager.INTENT_SENDER_ACTIVITY, packageName,
            null, null, requestCode, new Intent[] { intent },
            resolvedType != null ? new String[] { resolvedType } : null,
            flags, options, UserHandle.myUserId());

/*
type 三种
public static final int INTENT_SENDER_BROADCAST = 1;
public static final int INTENT_SENDER_ACTIVITY = 2;
public static final int INTENT_SENDER_SERVICE = 4;
*/
public IIntentSender getIntentSender(int type,
                                     String packageName, IBinder token, String resultWho,
                                     int requestCode, Intent[] intents, String[] resolvedTypes,
                                     int flags, Bundle bOptions, int userId) {}

PendingIntentRecord是IIntentSender的服务端
内部类Key(重写了equals,hashCode)保存从IIntentSender客户端传来的参数数据

//ActivityManagerService.java 中保存了PendingIntent传来的参数数据在PendingIntentRecord
//使用hashmap,以PendingIntentRecord.Key做key,PendingIntentRecord弱引用做value
final HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>> mIntentSenderRecords
            = new HashMap<PendingIntentRecord.Key, WeakReference<PendingIntentRecord>>();
//IIntentSender客户端传来的参数数据保存到PendingIntentRecord.Key
PendingIntentRecord.Key key = new PendingIntentRecord.Key(
                type, packageName, activity, resultWho,
                requestCode, intents, resolvedTypes, flags, bOptions, userId);
//生成PendingIntentRecord
rec = new PendingIntentRecord(this, key, callingUid);
//把key,value放入hashmap中
mIntentSenderRecords.put(key, rec.ref);

在PendingIntent的getActivity(或Service,BroadcastReceiver),把参数封装在AMS中的mIntentSenderRecords属性中。
PendingIntent主要结合NotificationManager进行使用的。
分析一波NotificationManager
app端主要 使用的是NotificationManager(其他的管理器获取使用类似)

NotificationManager.java
/*package*/ NotificationManager(Context context, Handler handler)
{
    mContext = context;
}

/** {@hide} */
public static NotificationManager from(Context context) {
    return (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
}

主要通过ContextImpl.java

context.getSystemService(Context.NOTIFICATION_SERVICE);

ContextImpl.java
@Override
public Object getSystemService(String name) {
     return SystemServiceRegistry.getSystemService(this, name);
}

SystemServiceRegistry动态注册许多App端使用的各种Manager(ActivityManager,AlarmManager,NotificationManager)

    //先静态注册许多服务管理器    
    registerService(Context.NOTIFICATION_SERVICE, NotificationManager.class,
                new CachedServiceFetcher<NotificationManager>() {
            @Override
            public NotificationManager createService(ContextImpl ctx) {
                final Context outerContext = ctx.getOuterContext();
                return new NotificationManager(Context,Handler);
            }});
//外部调用,获取提前静态注册的管理器

    public static Object getSystemService(ContextImpl ctx, String name) {
      ServiceFetcher<?> fetcher = SYSTEM_SERVICE_FETCHERS.get(name);
      return fetcher != null ? fetcher.getService(ctx) : null;
    }

在获取到NotificationManager,就已经实例化了。
Notification保存要执行的参数属性(pojo)
直接实例化或通过建造者模式实例化
参数

public long when;
public int icon;
public PendingIntent contentIntent;//PendingIntent
public Uri sound;//音频
....

通过Notification封装了PendingIntent
NotificationManager通过notify把Notification发送到状态栏中

NotificationManager.java   
public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
    {
        int[] idOut = new int[1];
        INotificationManager service = getService();
        。。。。。。
        final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
        try {
            //通过aidl转到INotificationManager的服务端中在NotificationManagerService的属性
            // private final IBinder mService = new INotificationManager.Stub() {}
            service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
                    copy, idOut, user.getIdentifier());
            if (localLOGV && id != idOut[0]) {
                Log.v(TAG, "notify: id corrupted: sent " + id + ", got back " + idOut[0]);
            }
        } catch (RemoteException e) {
            throw e.rethrowFromSystemServer();
        }
    }

//service的赋值
    static public INotificationManager getService()
    {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService("notification");
        sService = INotificationManager.Stub.asInterface(b);
        return sService;
    }

在NotificationManagerService的类中
联系点1
关注

//INotificationManager的服务端的实现
private final IBinder mService = new INotificationManager.Stub() {
    @Override
    //INotificationManager的实现的接口方法
    //作用是把跨进程的INotificationListener接口实现对象 注册进来
   
    public void registerListener(final INotificationListener listener,
        final ComponentName component, final int userid) {
        enforceSystemOrSystemUI("INotificationManager.registerListener");
        //进一步调用ManagedServices,registerService 封装起来
        mListeners.registerService(listener, component, userid);
    }
}
//是ManagedServices的子类的实现
private NotificationListeners mListeners;

NotificationListeners类是ManagedServices的子类
关注

ManagedServices.java
protected final ArrayList<ManagedServiceInfo> mServices = new ArrayList<ManagedServiceInfo>();
//抽象方法子类NotificationListeners实现
abstract protected void onServiceAdded(ManagedServiceInfo info);

public void registerService(IInterface service, ComponentName component, int userid) {
    checkNotNull(service);
    //把INotificationListener接口实现对象
    //封装到ManagedServiceInfo 
    ManagedServiceInfo info = registerServiceImpl(service, component, userid);
    if (info != null) {
        //抽象类子类实现
        onServiceAdded(info);
    }
}
NotificationListeners子类实现ManagedServices
public void onServiceAdded(ManagedServiceInfo info) {
    //ManagedServiceInfo 获取service
    final INotificationListener listener = (INotificationListener) info.service;
    final NotificationRankingUpdate update;
    synchronized (mNotificationList) {
        updateNotificationGroupsDesiredLocked();
        update = makeRankingUpdateLocked(info);
    }
    try {
        //进行跨进程回调
        //跨进程INotificationListener回调
        listener.onListenerConnected(update);
    } catch (RemoteException e) {
        // we tried
    }
}

ManagedServiceInfo类(pojo)存储信息,并使用service(IInterface )进行回调
关注属性

public IInterface service;
public ServiceConnection connection;

介绍完上面,接下来介绍如何启动状态栏PhoneStatusBar,BaeStatusBar,会操作Nitiofication
首先从SystemServer#startOtherServices
然后通过AMS的

mActivityManagerService.systemReady(new Runnable() {
    @Override
    public void run() {
        。。。。。。
        try {
            startSystemUi(context);
        } catch (Throwable e) {
            reportWtf("starting System UI", e);
        }
        。。。。。。
    }
}
//拉起一个服务开启系统UI的服务
static final void startSystemUi(Context context) {
    Intent intent = new Intent();
    intent.setComponent(new ComponentName("com.android.systemui",
                "com.android.systemui.SystemUIService"));
    //Slog.d(TAG, "Starting service: " + intent);
    //把SystemUIApplication进程启动起来
    //进程名字android:process="com.android.systemui"
    context.startServiceAsUser(intent, UserHandle.OWNER);
}

拉起SystemUIService把SytemUI的app启动

SystemUIService.java
@Override
public void onCreate() {
    super.onCreate();
    //调用SystemUIApplication#startServicesIfNeeded
    ((SystemUIApplication) getApplication()).startServicesIfNeeded();
}

SystemUIApplication.java

//要启动的SystemUI
private final Class<?>[] SERVICES = new Class[] {
        com.android.systemui.tuner.TunerService.class,
        com.android.systemui.keyguard.KeyguardViewMediator.class,
        com.android.systemui.recents.Recents.class,
        com.android.systemui.volume.VolumeUI.class,
        com.android.systemui.statusbar.SystemBars.class,
        com.android.systemui.usb.StorageNotification.class,
        com.android.systemui.power.PowerUI.class,
        com.android.systemui.media.RingtonePlayer.class,
        com.android.systemui.keyboard.KeyboardUI.class,
};

//这个通过主线程才能调用
public void startServicesIfNeeded() {
    if (mServicesStarted) {
        return;
    }
。。。。。。。
    final int N = SERVICES.length;
    //一个一个把SysytemUI的子类进行实现
    //并执行对应的方法
    for (int i=0; i<N; i++) {
        Class<?> cl = SERVICES[i];
        if (DEBUG) Log.d(TAG, "loading: " + cl);
        try {
            mServices[i] = (SystemUI)cl.newInstance();
        } catch (IllegalAccessException ex) {
            throw new RuntimeException(ex);
        } catch (InstantiationException ex) {
            throw new RuntimeException(ex);
        }
        mServices[i].mContext = this;
        //hashmap的<Class,Object>
        mServices[i].mComponents = mComponents;
        mServices[i].start();

        if (mBootCompleted) {
            mServices[i].onBootCompleted();
        }
    }
    mServicesStarted = true;
}

通过各个子类实现start()方法,执行各个子类定制的属性和逻辑关系
关注子类SystemBars类
SystemBars.java且实现了ServiceMonitor.Callbacks

@Override
public void start() {
    if (DEBUG) Log.d(TAG, "start");
    //实例化ServiceMonitor
    mServiceMonitor = new ServiceMonitor(TAG, DEBUG,
            mContext, Settings.Secure.BAR_SERVICE_COMPONENT, this);
    // will call onNoService if no remote service is found
    mServiceMonitor.start(); 
     
}
/*
ServiceMonitor#start()
主要作用,设置了动态广播,绑定服务,以及正常的逻辑
使用handler进行线程调度,确保线程是在主线程上
通过handler来完成ServiceMonitor.Callbacks的实例的回调
主要回调onNoService(),子类实现
*/

//子类实现ServiceMonitor.Callbacks#onNoService()
@Override
public void onNoService() {
    if (DEBUG) Log.d(TAG, "onNoService");
    createStatusBarFromConfig();  // fallback to using an in-process implementation
}

private void createStatusBarFromConfig() {
    ........
    //config_statusBarComponent保存的字符串是
    //com.android.systemui.statusbar.phone.PhoneStatusBar
    //父类是com.android.systemui.statusbar.BaseStatusBar
    final String clsName = mContext.getString(R.string.config_statusBarComponent);
    ......
    Class<?> cls = null;
    try {
        //反射
        cls = mContext.getClassLoader().loadClass(clsName);
    } catch (Throwable t) {
        throw andLog("Error loading status bar component: " + clsName, t);
    }
    try {
        //实例化
        mStatusBar = (BaseStatusBar) cls.newInstance();
    } catch (Throwable t) {
        throw andLog("Error creating status bar component: " + clsName, t);
    }
    mStatusBar.mContext = mContext;
    mStatusBar.mComponents = mComponents;
    //启动start()
    //最终把PhoneStatusBar以及父类BaseStatusBar实例化并启动
    mStatusBar.start();
    if (DEBUG) Log.d(TAG, "started " + mStatusBar.getClass().getSimpleName());
}

在BaseStatusBar#start()
关注

BaseStatusBar.java
public void start() {
    .....
    //状态栏服务IStatusBarService客户端mBarService
    //由于是单例与StatusBarManager获得 IStatusBarService客户端同一个
    mBarService = IStatusBarService.Stub.asInterface(
        ServiceManager.getService(Context.STATUS_BAR_SERVICE));
    //为已经启动的SystemUI的子类Recent设置回调函数
    //Recent触发RecentsActivity
    mRecents = getComponent(Recents.class);
    mRecents.setCallback(this);
    ....
    // Connect in to the status bar manager service
    StatusBarIconList iconList = new StatusBarIconList();
    //CommandQueue是IStatusBar接口跨进程,目的是回调
    //CommandQueue.CallBack内部接口,在PhoneStatusBar进行实现
    mCommandQueue = new CommandQueue(this, iconList);
    int[] switches = new int[8];
    ArrayList<IBinder> binders = new ArrayList<IBinder>();
    try {
        //把IStatusBar接口实例注册到IStatusBarService接口中
        //便于回调IStatusBarService方法,间接回调IStatusBar方法
        //再次回调CommandQueue.CallBack内部接口方法
        mBarService.registerStatusBar(mCommandQueue, iconList, switches, binders);
    } catch (RemoteException ex) {
        // If the system process isn't there we're doomed anyway.
    }
    //添加状态栏
    createAndAddWindows();
    .......
    // Set up the initial notification state.
    try {
        //调用NotificationListenerService 的registerAsSystemService
        mNotificationListener.registerAsSystemService(mContext,
                new ComponentName(mContext.getPackageName(), getClass().getCanonicalName()),
                UserHandle.USER_ALL);
    } catch (RemoteException e) {
        Log.e(TAG, "Unable to register notification listener", e);
    }
    。。。。。
}
//子类实现
protected abstract void createAndAddWindows();

private NotificationClicker mNotificationClicker = new NotificationClicker();

//在BaseStatusBar很多内部类
private final class NotificationClicker implements View.OnClickListener {
    public void onClick(final View v) {
        ......
        //获取状态栏下滑的点击的区域view
        final ExpandableNotificationRow row = (ExpandableNotificationRow) v;
        //得到对应的StatusBarNotification 封装这Notification
        //Notification又封装PendingIntent
        final StatusBarNotification sbn = row.getStatusBarNotification();
        .....
        final PendingIntent intent = sbn.getNotification().contentIntent;
        。。。。。
        
        if (intent != null) {
            //最终执行PendingIntent,响应activity,receiver service
            try {
                intent.send();
            } catch (PendingIntent.CanceledException e) {
                。。。。。
            }
            。。。。。。
        }
    }
}

//和Notification相关的内部类
//这是一个服务,
private final NotificationListenerService mNotificationListener =
        new NotificationListenerService() {
    @Override
    public void onListenerConnected() {
       。。。。。
                    //父类空方法,子类重写
                    addNotification(sbn, currentRanking, null /* oldEntry */);
           。。。。。。。
    }

    @Override
    public void onNotificationPosted(final StatusBarNotification sbn,
            final RankingMap rankingMap) {
        ......
                    if (isUpdate) {
                        updateNotification(sbn, rankingMap);
                    } else {
                        addNotification(sbn, rankingMap, null /* oldEntry */);
                    }
          .......
    }

    @Override
    public void onNotificationRemoved(StatusBarNotification sbn,
            final RankingMap rankingMap) {
        if (DEBUG) Log.d(TAG, "onNotificationRemoved: " + sbn);
        if (sbn != null) {
            final String key = sbn.getKey();
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    removeNotification(key, rankingMap);
                }
            });
        }
    }

    @Override
    public void onNotificationRankingUpdate(final RankingMap rankingMap) {
        if (DEBUG) Log.d(TAG, "onRankingUpdate");
        if (rankingMap != null) {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                updateNotificationRanking(rankingMap);
            }
        });
    }                            }

};

//与上面分析的 联系点1 进行关联
// 当回调INotificationListener的方法,就会在这里具体执行
//间接调用NotificationListenerService的方法,子类在BaseStatusBar的内部NotificationListenerService重写
//又间接调用BaseStatusBar自己的方法,由子类再次PhoneStatusBar重写实现

关于Click事件监听
主要通过上面流程,把Notification拿出来,封装在View中,设置点击相应PendingIntent
大功告成

NotificationListenerService.java
 //这个服务通过xml静态注册,

@SystemApi
public void registerAsSystemService(Context context, ComponentName componentName,
        int currentUser) throws RemoteException {
    mSystemContext = context;
    if (mWrapper == null) {
        //实例化内部类
        mWrapper = new INotificationListenerWrapper();
    }
    //获得客户端INotificationManager 
    INotificationManager noMan = getNotificationInterface();
    //把INotificationListener接口实例注册到INotificationManager 接口中
    //与上面分析的联系点1进行关联
    noMan.registerListener(mWrapper, componentName, currentUser);
    mCurrentUser = currentUser;
}



 //内部类INotificationListener服务端
 private class INotificationListenerWrapper extends INotificationListener.Stub {
    @Override
    public void onNotificationPosted(IStatusBarNotificationHolder sbnHolder,
            NotificationRankingUpdate update) {
        StatusBarNotification sbn;
        try {
            sbn = sbnHolder.get();
        } catch (RemoteException e) {
            Log.w(TAG, "onNotificationPosted: Error receiving StatusBarNotification", e);
            return;
        }
.......
        // protect subclass from concurrent modifications of (@link mNotificationKeys}.
        synchronized (mWrapper) {
            applyUpdate(update);
            try {
                if (sbn != null) {
                    NotificationListenerService.this.onNotificationPosted(sbn, mRankingMap);
                } else {
                    // still pass along the ranking map, it may contain other information
                    NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
                }
            } catch (Throwable t) {
                Log.w(TAG, "Error running onNotificationPosted", t);
            }
        }
    }
    @Override
    public void onNotificationRemoved(IStatusBarNotificationHolder sbnHolder,
            NotificationRankingUpdate update) {
        StatusBarNotification sbn;
        try {
            sbn = sbnHolder.get();
        } catch (RemoteException e) {
            Log.w(TAG, "onNotificationRemoved: Error receiving StatusBarNotification", e);
            return;
        }
        // protect subclass from concurrent modifications of (@link mNotificationKeys}.
        synchronized (mWrapper) {
            applyUpdate(update);
            try {
                NotificationListenerService.this.onNotificationRemoved(sbn, mRankingMap);
            } catch (Throwable t) {
                Log.w(TAG, "Error running onNotificationRemoved", t);
            }
        }
    }
    @Override
    public void onListenerConnected(NotificationRankingUpdate update) {
        // protect subclass from concurrent modifications of (@link mNotificationKeys}.
        synchronized (mWrapper) {
            applyUpdate(update);
            try {
                NotificationListenerService.this.onListenerConnected();
            } catch (Throwable t) {
                Log.w(TAG, "Error running onListenerConnected", t);
            }
        }
    }
    @Override
    public void onNotificationRankingUpdate(NotificationRankingUpdate update)
            throws RemoteException {
        // protect subclass from concurrent modifications of (@link mNotificationKeys}.
        synchronized (mWrapper) {
            applyUpdate(update);
            try {
                NotificationListenerService.this.onNotificationRankingUpdate(mRankingMap);
            } catch (Throwable t) {
                Log.w(TAG, "Error running onNotificationRankingUpdate", t);
            }
        }
    }
    @Override
    public void onListenerHintsChanged(int hints) throws RemoteException {
        try {
            NotificationListenerService.this.onListenerHintsChanged(hints);
        } catch (Throwable t) {
            Log.w(TAG, "Error running onListenerHintsChanged", t);
        }
    }

    @Override
    public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException {
        try {
            NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter);
        } catch (Throwable t) {
            Log.w(TAG, "Error running onInterruptionFilterChanged", t);
        }
    }
}

PhoneStatusBar.java

@Override
public void createAndAddWindows() {
    addStatusBarWindow();
}

private void addStatusBarWindow() {
    //创建状态栏view
    makeStatusBarView();
    //创建状态栏管理器,持有WindowManager
    mStatusBarWindowManager = new StatusBarWindowManager(mContext);
    //把状态栏的mStatusBarWindow view,addview到WindowManager
    //进行显示
    mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
}

@Override
public void start() {
    mDisplay = ((WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE))
            .getDefaultDisplay();
    updateDisplaySize();
    mScrimSrcModeEnabled = mContext.getResources().getBoolean(
            R.bool.config_status_bar_scrim_behind_use_src);

    super.start(); // calls createAndAddWindows()
    。。。。
    //添加导航栏
    addNavigationBar();
    。。。。。。
}

//添加在WindowManager并显示
private void addNavigationBar() {
    if (DEBUG) Log.v(TAG, "addNavigationBar: about to add " + mNavigationBarView);
    if (mNavigationBarView == null) return;

    prepareNavigationBarView();

    mWindowManager.addView(mNavigationBarView, getNavigationBarLayoutParams());
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,533评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,055评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,365评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,561评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,346评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,889评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,978评论 3 439
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,118评论 0 286
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,637评论 1 333
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,558评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,739评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,246评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,980评论 3 346
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,362评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,619评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,347评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,702评论 2 370

推荐阅读更多精彩内容