Android Notification

段子

经常熬夜有三大害处:第一,记忆力越来越差;第二,数学水平下降;第四,记忆力越来越差。

前言

Notification在Android中使用的还是挺多的,我们公司的项目基本都用到了。这篇文章依然保持我的风格,用写Demo的方式来学习,这样记忆最深。

Demo

我们写一个小Demo,把各种类型的Notification全部展示一遍,首先看下demo截图


demo

简单看下,大概会有这么二十多种写法的Notification,下面一个一个来看。

普通通知

Android3.0是一个分水岭,在其之前构建Notification推荐使用NotificationCompate.Builder,它位于android.support.v4.app.NotificationCompat.Builder,是一个Android向下版本的兼容包,而在Android3.0之后,一般推荐使用Notification.Builder构建。本博客主要介绍的是Android4.x的开发,所以在这里使用Notification.Builder进行讲解演示。

通知一般通过NotificationManager服务发送一个Notification对象来完成通知,NotificationManager是一个重要的系统级服务,该对象位于应用程序的框架层中,应用程序可以通过它向系统发送全局的通知。使用通知的时候,需要创建一个Notification对象用来承载通知的内容,但是一般不会直接通过Notification的构造方法来得到对象,而是使用它的内部类Notification.Builder来实例化一个Builder对象,并设置通知的各项属性,最后通过Notification.Builder.builder()方法得到一个Notification对象,当获得这个Notification对象之后,就可以使用NotificationManager.notify()方法发送通知。

NotificationManager类是一个通知管理器类,这个对象是由系统维护的服务,是以单例模式的方式获得,所以一般并不直接实例化这个对象。在Activity中,可以使用Activity.getSystemService(String)方法获取NotificationManager对象,Activity.getSystemService(String)方法可以通过Android系统级服务的句柄,返回对应的对象。在这里需要返回NotificationManager,所以直接传递Context.NOTIFICATION_SERVICE即可。

虽然通知中提供了各种属性的设置,但是一个通知对象,有几个属性是必须要设置的,其他的属性均是可选的,必须设置的属性如下:

  • 小图标,使用setSamllIcon()方法设置。
  • 标题,使用setContentTitle()方法设置。
  • 文本内容,使用setContentText()方法设置。
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setContentTitle("普通通知")
        .setContentText("这是一条普通通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

NOTIFICATION_ID是一个自己定义值,一个id表示一个notification,如果两次发出的notification是相同的id,那就会更新之前的那一个,这是id的用处之一。id另外一个用处就是用于移除notification。

mNotificationManager.cancel(NOTIFICATION_ID);

当然除了可以用id移除notification以外,还可以通过Tag移除

mNotificationManager.cancel("tag", NOTIFICATION_ID);

或者一次移除所有notification

mNotificationManager.cancelAll();
普通通知

设置属性

最普通的notification肯定是没法满足我们的,因为既没有点击效果,展示信息也很少,所以我们要看看notification给我们提供了哪些api可以设置参数。

大小图标

setSmallIcon(R.drawable.icon_small)
setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))

当 setSmallIcon() 与 setLargeIcon() 同时存在时, smallIcon 显示在通知的右下角, largeIcon 显示在左侧;当只设置 setSmallIcon() 时, smallIcon 显示在左侧。看下图你就明白了。对于部分 ROM ,可能修改过源码,如 MIUI 上通知的大图标和小图标是没有区别的。

图标

Ticker提示语句

setTicker("来了一条设置属性通知")

在来一条notification时,默认情况通知栏上会显示一个小icon,但是不是很显眼,并且不下拉通知栏就不知道具体是来了什么消息,Ticker就可以显示一句提示语句。

Ticker

设置时间
这个可设可不设,默认也会取系统时间

setWhen(System.currentTimeMillis())

点击自动移除
这个最好还是设置成true,我自己测试的手机默认是不会自动移除的,一条notification被点击了,我们就默认为查看了,就不应该再显示。

setAutoCancel(true)

设置数量
就是右下角显示的数字

setNumber(23)
number

设置数据
这个数据主要是携带给跳转Activity用的,比如我们推送了一部小说,携带了小说id等重要信息,用户点击后可以跳转对应的小说详情去。

setExtras(new Bundle())

设置跳转
这个是最重要的属性了,没有这个属性,通知基本就没什么意思了。

Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);

setContentIntent(pendingIntent)

flag参数有四个取值

  • FLAG_CANCEL_CURRENT:如果构建的PendingIntent已经存在,则取消前一个,重新构建一个。
  • FLAG_NO_CREATE:如果前一个PendingIntent已经不存在了,将不再构建它。
  • FLAG_ONE_SHOT:表明这里构建的PendingIntent只能使用一次。
  • FLAG_UPDATE_CURRENT:如果构建的PendingIntent已经存在,则替换它,常用。

最后看下全部的代码

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setTicker("来了一条设置属性通知")
        .setContentIntent(pendingIntent)
        .setWhen(System.currentTimeMillis())
        .setNumber(23)
        .setAutoCancel(true)
        .setExtras(new Bundle())
        .setContentTitle("设置属性通知")
        .setContentText("这是一条设置属性通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

大图模式

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.head_image);

Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setStyle(new Notification.BigPictureStyle().bigPicture(bitmap))
        .setContentTitle("大图模式通知")
        .setContentText("这是一条大图模式通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);
大图

文本段模式

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);

Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setNumber(12)
        .setStyle(new Notification.BigTextStyle()
                .setBigContentTitle("这是一段长文本")
                .setSummaryText("这是总结")
                .bigText("打南边来了个哑巴,腰里别了个喇叭;打北边来了个喇嘛,手里提了个獭犸。提着獭犸的喇嘛要拿獭犸换别着喇叭的哑巴的喇叭;别着喇叭的哑巴不愿拿喇叭换提着獭犸的喇嘛的獭犸。不知是别着喇叭的哑巴打了提着獭犸的喇嘛一喇叭;还是提着獭犸的喇嘛打了别着喇叭的哑巴一獭犸。喇嘛回家炖獭犸;哑巴嘀嘀哒哒吹喇叭"))
        .setContentTitle("长文本通知")
        .setContentText("这是一条长文本通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);
文本段

文本块模式

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);

Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setNumber(12)
        .setStyle(new Notification.InboxStyle()
                .setBigContentTitle("这是一个文本段")
                .setSummaryText("这是总结")
                .addLine("文本行111")
                .addLine("文本行222")
                .addLine("文本行333")
                .addLine("文本行444")
                .addLine("文本行555")
                .addLine("文本行666"))
        .setContentTitle("设置属性通知")
        .setContentText("这是一条文本段通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);
文本块

精确进度条

这个用的多一些,展示精确的进度值,setProcess()方法第一个参数是最大进度值,第二个参数是当前进度值,步长是1,第三个参数false表示的就是精确进度条,true表示的是模糊进度条。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification.Builder mProgressBuilder = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setProgress(100, 0, false)
        .setContentTitle("进度条通知")
        .setContentText("这是一条进度条通知");
new Thread() {
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            mProgressBuilder.setProgress(100, i, false);
            mNotificationManager.notify(NOTIFICATION_ID, mProgressBuilder.build());
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}.start();
progress

模糊进度条

第三个参数false表示的就是精确进度条,true表示的是模糊进度条。如果是模糊进度条,那就不存在最大值和当前值,所以前两个参数传0即可。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setProgress(0, 0, true)
        .setContentTitle("模糊进度条通知")
        .setContentText("这是一条模糊进度条通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);
progress

震动、音效、呼吸灯

这个很简单,Android提供了三种效果:震动、音效、呼吸灯,以及它们三者的任意组合。

// 默认震动
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setDefaults(Notification.DEFAULT_VIBRATE)
        .setContentTitle("震动通知")
        .setContentText("这是一条震动通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

// 默认音效
setDefaults(Notification.DEFAULT_SOUND)

// 默认呼吸灯
setDefaults(Notification.DEFAULT_LIGHTS)

没有图,这三个效果真没法配图。。。


还可以选择全效果,震动+音效+呼吸灯

setDefaults(Notification.DEFAULT_ALL)

自定义音效

我写demo的这个音效来自腾讯,我有一次在港式餐厅里喝咖啡,正好旁边一个腾讯的工程师,聊到我最近要写一个Notification的博客,缺少一个音效文件,他就推荐了我这个,在此非常感谢腾讯的这位朋友。

好了,不装逼了。。。是我从QQ apk里解压出来的。。。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setSound(Uri.parse("android.resource://com.makeunion.notificationdemo/" + R.raw.qq))
        .setContentTitle("自定义音效通知")
        .setContentText("这是一条自定义音效通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

从代码中应该也能看出来,音效文件是放在raw目录下的。

自定义震动

这里我们需要传一个long[]数组参数,这个参数真的是日了够了,我看到的解释是这样的:
第一个0表示手机静止的时长
第二个300表示手机震动的时长
第三个300表示手机静止的时长
第四个300表示手机震动的时长

所以这里表示手机先震动300毫秒,然后静止300毫秒,然后再震动300毫秒

但是,我实际的效果总是有一点出入,我自己猜想应该是notification总的提示时间是有限制的,所以会对最终效果有影响。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
long[] vibrate = new long[]{0, 300, 300, 300};
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setVibrate(vibrate)
        .setContentTitle("自定义震动通知")
        .setContentText("这是一条自定义震动通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

自定义呼吸灯

这个呼吸灯也是日了够了,完全看不到效果,我不知道是我用的不对,还是现在Android手机都阉割了这个功能。。。我觉得第二种可能性大些。

第一个参数表示的是颜色
第二个参数表示的是灯亮的时间
第三个参数表示的是灯灭的时间

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setLights(0xFF0000, 1000, 500)
        .setContentTitle("自定义呼吸灯通知")
        .setContentText("这是一条自定义呼吸灯通知").build();
notification.flags = Notification.FLAG_SHOW_LIGHTS;
mNotificationManager.notify(NOTIFICATION_ID, notification);

只提示一次

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setSound(Uri.parse("android.resource://com.makeunion.notificationdemo/" + R.raw.qq))
        .setContentTitle("无限循环通知")
        .setContentText("这是一条无限循环通知").build();
notification.flags |= Notification.FLAG_INSISTENT;
mNotificationManager.notify(NOTIFICATION_ID, notification);

慎用!!!你会听到一段疯狂的提示音。

也可以设置成只提示一次

notification.flags |= Notification.FLAG_ONLY_ALERT_ONCE;

顶部悬浮

API21之后,Android提供了顶部悬浮显示Notification,这种显示方式的好处是更加显眼,可以直接看到通知的内容,而且不影响当前app的使用。要实现顶部悬浮效果有两种方式:

  • setFullScreenIntent
  • PRIORITY_HIGH高优先级
NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setFullScreenIntent(pendingIntent, false)
        .setSound(Uri.parse("android.resource://com.makeunion.notificationdemo/" + R.raw.qq))
        .setContentTitle("顶部悬浮通知通知")
        .setContentText("这是一条顶部悬浮通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

或者

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setPriority(Notification.PRIORITY_HIGH)
        .setSound(Uri.parse("android.resource://com.makeunion.notificationdemo/" + R.raw.qq))
        .setContentTitle("顶部悬浮通知")
        .setContentText("这是一条顶部悬浮通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

锁屏Notification

同样是API21之后,Android可以实现在锁屏状态下显示通知,对于大多数app而言,在锁屏状态显示是用户友好的,因为因为用户不用打开手机就能看到通知内容,但是对于一些敏感信息,比如短信之类的,最好不要在锁屏显示具体的信息内容。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setContentIntent(pendingIntent)
        .setNumber(23)
        .setAutoCancel(true)
        .setVisibility(Notification.VISIBILITY_PUBLIC)
        .setContentTitle("锁屏通知")
        .setContentText("这是一条锁屏通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

Action

API20之后新增的功能,这是一个很好的功能,我们通常一个通知的作用就是展示,最多给整体设置一个pendingIntent,这样扩展性就比较差了,但是有了Action,我们就能在通知上自定义功能键了。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.icon_big))
        .setFullScreenIntent(pendingIntent, false)
        .addAction(new Notification.Action(R.drawable.icon_share, "分享", pendingIntent))
        .addAction(new Notification.Action(R.drawable.icon_zan, "收藏", pendingIntent))
        .addAction(new Notification.Action(R.drawable.icon_message, "消息", pendingIntent))
        .setSound(Uri.parse("android.resource://com.makeunion.notificationdemo/" + R.raw.qq))
        .setContentTitle("action功能通知")
        .setContentText("这是一条action功能通知").build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

这里有几点需要说明:

  • Action的icon最好不要设计成有颜色的,按照MaterialDesign的规范,最好是白色内容,透明背景。如果有别的颜色,也会被着色成白色。(但是有的定制机又不会)
  • Action不要太多,3个已经足够了,太多了显示有可能出问题
  • api20才支持,旧版本使用会报错

自定义小视图

自定义视图用的还是挺多的,毕竟原生视图太丑。

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 100, intent, PendingIntent.FLAG_CANCEL_CURRENT);
RemoteViews remoteViews = new RemoteViews("com.makeunion.notificationdemo", R.layout.layout_remote_view);
remoteViews.setOnClickPendingIntent(R.id.play_pause_img, pendingIntent);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setAutoCancel(true)
        .setContentIntent(pendingIntent)
        .setContent(remoteViews).build();
mNotificationManager.notify(NOTIFICATION_ID, notification);

layout布局的代码我就不贴了,很简单,没什么说的



是不是婉如一个真的音乐播放器。(原谅我最近玩抖音玩入迷了~)

自定义大视图

NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
RemoteViews remoteViews = new RemoteViews("com.makeunion.notificationdemo", R.layout.layout_remote_view);
RemoteViews bigRemoteViews = new RemoteViews("com.makeunion.notificationdemo", R.layout.layout_big_remote_view);
Notification notification = new Notification.Builder(this)
        .setSmallIcon(R.drawable.icon_small)
        .setOngoing(true)
        .setTicker("来了一条伸缩布局通知")
        .build();
notification.bigContentView = bigRemoteViews;
notification.contentView = remoteViews;
mNotificationManager.notify(NOTIFICATION_ID, notification);

这是一个大图模式和小图模式的切换,效果还不错,但是兼容性不行,在有些手机上显示效果不对,还需要继续研究。和定制机也有一定关系。

总结

好啦,这就是本期的Notification,总的来说内容比较简单,但很实用。后面还会有一系列很实用的Android文章出炉。

说到这,我想起一个很久前的故事,某日我写了一篇博客,一个心怀梦想的年轻人看了我的博客,并给我打了2块钱的赏,今后几年他事业顺利,婚姻幸福,身体健康,越来越帅,从此走上人生巅峰。

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

推荐阅读更多精彩内容