iOS 普通推送和静默推送【公司要求用个推】

写在前面:应用场景很重要

如果你的公司有这样一个硬性的需求:用户将APP退出到后台的时候,当该用户收到推送的时候,不让用户感觉到推送过来了,不想打扰用户,但是还想拿到推送内容做一些事情。
在开发人员看来就是要实现如下功能:通知栏没有文字、没有内容、也没有声音,同时还要能实现客户端退出到后台时,还能执行xcode中的某个特定方法,那么此时就可以用到静默推送


必须知道个推中这些名词的含义,后面再出现这些名词就不做阐述了

离线:APP在后台运行/APP未启动/APP被杀死。
在线:APP在前台运行。
iOS 个推透传机制

iOS消息推送方式只有两种:

APNs的通知栏消息
个推的透传消息


以下说的是普通推送和静默推送的不同之处:

普通推送:当APP离线时,当有推送下达的时候,走的是APNs,所以手机会有铃声、手机顶部出现横幅/通知栏会收到通知。

  • APP离线时,相关方法什么时候执行,看下面1-4就知道了:
    1.只有点开通知栏中的通知进入APP/点开横幅中的通知进入APP,才会执行方法AAA;不点击不执行。
    2.点击应用图标进入APP,一定不会执行方法AAA。
    3.APP离线收到推送,点击应用图标进入APP/点开通知栏中的通知/点开横幅中的通知进入APP,会执行个推提供的 方法BBB的离线的透传消息
    4.APP在线收到推送,就不走APNs,会直接执行个推提供的 方法BBB的在线的透传消息

  • 总结:综合1-4,只要点开APNs发来的通知,那么先执行方法AAA,再执行个推的方法BBB


方法AAA
iOS 10之前,点通知,会调用如下方法。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
     ...   
  做你想做的操作。例如更新UI,跳转界面,文字转语音并读出来,顶部弹框,操作userInfo中的内容。
     ...
}


iOS 10 及以后版本,点击通知,会调用如下方法
-(void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)(void))completionHandler{
    
      ...
     做你想做的操作。例如更新UI,跳转界面,文字转语音并读出来,顶部弹框,操作userInfo中的内容。
      ...

    NSLog(@"didReceiveNotification:%@", response.notification.request.content.userInfo);
    // [ GTSdk ]:将收到的APNs信息传给个推统计
    [GeTuiSdk handleRemoteNotification:response.notification.request.content.userInfo];
    completionHandler();
    
}
方法BBB
  • 离线的透传消息:程序离线收到推送时候,当由离线进入在线的时候会执行(offLine为YES)。离线的时候不会执行该方法。
  • 在线的透传消息:程序在线收到推送的时候会执行(offLine为NO)。
接收个推推送的透传消息,就会执行如下代理方法
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {

   拿到payloadData并转成字符串,然后做你想做的操作 :更新UI,跳转界面,文字转语音并读出来,顶部弹框

   if (!offLine) {// offLine为NO表示在线的透传消息。
       
    }else{// offLine为YES表示离线的透传消息。
    
   }
}

普通推送->服务端格式:
    $alertmsg=new DictionaryAlertMsg();//  必须有。    声明DictionaryAlertMsg的对象alertmsg
    $alertmsg->body=$msgContent;//  必须有。   为body赋值
    $alertmsg->title=SYS_ZH_NAME;//  必须有。   为title赋值

    $apn = new IGtAPNPayload();// 必须有。   声明IGtAPNPayload的对象apn
    $apn->alertMsg=$alertmsg;// 必须有alertmsg,且alertmsg中一定有title以及和body,因为这就是客户端在通知栏/横幅看到的标题和内容。
    $apn->contentAvailable=0;// 必须为0 
    $apn->sound=$client_notice;// 必须有sound
    $apn->badge=1;// 角标,可有可无
    $apn->add_customMsg("msg",$msgContent);// msg,可有可无
普通推送->客户端格式:
{
  "aps" : {
    "sound" : "notice_type1.caf",// 必须有sound
    "alert" : { // 必须有。    服务器端一定要有alertmsg
      "title" : "一秒招聘",// 必须有
      "body" : "有一条新的招工信息,点击查看详情" // 必须有 
    },
      "badge" : 1,// 角标,可有可无
  },
      "msg" : "有一条新的招工信息,点击查看详情"// msg可有可无
}

静默推送(安安静静的、用户感知不到):当APP离线时,当有推送下达的时候,通知栏/横幅中没有文字,同时也不会发出声音)

  • 1.应用被杀死或者应用未启动,不会执行如下的代码。
  • 2.应用退出到后台,当收到通知的时候(不点开通知,也不打开APP哦),就会立刻执行如下的代码CCC。 所以静默推送的定义也就出现了:应用收到通知后在后台(background)状态下可以执行下面一段代码CCC,可用于从服务器获取内容更新,做你想做的任何操作(跳转界面,文字转语音并读出声音),所以静默推送不同于其他推送,其他推送不能执行代码CCC。
  • 3.APP离线收到推送,点击应用图标进入APP/点开通知栏中的通知/点开横幅中的通知进入APP,会执行个推提供的 方法DDD的离线的透传消息
  • 4.APP在线收到推送,就不走APNs,会直接执行个推提供的 方法DDD的在线的透传消息
代码CCC
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
  ...   
做你想做的操作:这里我用苹果自带的文字转语音播放userInfo里面的指定内容
  ...
}
方法DDD
  • 离线的透传消息:程序离线收到推送时候,当由离线进入在线的时候会执行(offLine为YES)。离线的时候不会执行该方法。
  • 在线的透传消息:程序在线收到推送的时候会执行(offLine为NO)。
接收个推推送的透传消息,就会执行如下代理方法
- (void)GeTuiSdkDidReceivePayloadData:(NSData *)payloadData andTaskId:(NSString *)taskId andMsgId:(NSString *)msgId andOffLine:(BOOL)offLine fromGtAppId:(NSString *)appId {

   拿到payloadData并转成字符串,然后做你想做的操作 :更新UI,跳转界面,文字转语音并读出来,顶部弹框

   if (!offLine) {// offLine为NO表示在线的透传消息。
       
    }else{// offLine为YES表示离线的透传消息。
    
   }
}
静默推送->服务端格式:
    $apn = new IGtAPNPayload();
    $apn->alertMsg="";
    $apn->sound="com.gexin.ios.silence";
    $apn->contentAvailable=1;
    $apn->badge=1;
    $apn->add_customMsg("msg",$msgContent);
静默推送->客户端格式:
{
  "aps" : {
    "content-available" : 1,// 必须为1
    "badge" : 1 // 角标,可有可无
     // 一定不能有alert,因为alert如果有内容,在客户端的通知栏/横幅上会有通知。
  },
  "msg" : "有一条新的招工信息,点击查看详情" // 可有可无
}

服务端(我们公司是PHP)配置静默推送的格式如下(非常严格,非常严格,非常严格,一项不满足,就不是静默推送,那就变成了普通的有文字有声音的推送):

1.传入的alertMsg对应的值一定为空或者压根就不传alertMsg字段。

$apn->alertMsg="";
  1. contentAvailable的值一定为1
$apn->contentAvailable=1;

3.sound对应的值一定为com.gexin.ios.silence.改成其他的字符串的话,应用在后台收到推送时,会听到"铛"的一声。 或者sound对应的值为任意常量也可以实现静音(真机测试过一次,发现确实没有声音。测试次数过少,不是太敢断定,如果有想测试的,可以将sound的值设置成常量试一下)。


$apn->sound="com.gexin.ios.silence";

4.其他的倒无关紧要了,不影响静默推送的格式。


综合1.2.3.4,静默推送,php服务端要设置的核心代码必定是下面的这种格式:
    $apn->alertMsg="";// alertMsg一定不要有值
    $apn->sound="com.gexin.ios.silence";
    $apn->contentAvailable=1;// 一定为1

以我们项目中静默推送的实战演练

关键代码如下:
function IGtTransmissionTemplateDemo($appid,$appkey,$msgContent,$keyType,$keyId,$temp_ietm="",$client_notice="default"){
    $msg = array(
        'keyType' => $keyType,
        'keyId' => $keyId,
        'msg' => $msgContent,
        'nickname' => $temp_ietm
    );
    $msg = json_encode($msg);
    $template =  new IGtTransmissionTemplate();
    $template->set_appId($appid);//应用appid
    $template->set_appkey($appkey);//应用appkey
    $template->set_transmissionType(2);//透传消息类型
    $template->set_transmissionContent($msg);//透传内容
  
    $apn = new IGtAPNPayload();
    $alertmsg=new DictionaryAlertMsg();
    $alertmsg->body=$msgContent;
    $alertmsg->actionLocKey="ActionLockey";
    $alertmsg->locKey=$msgContent;
    $alertmsg->locArgs=array("locargs");
    $alertmsg->launchImage="launchimage";
    //        IOS8.2 支持
    $alertmsg->title=SYS_ZH_NAME;
    $alertmsg->titleLocKey=SYS_ZH_NAME;
    $alertmsg->titleLocArgs=array("TitleLocArg");
    // $apn->alertMsg=$alertmsg;
    $apn->alertMsg="";
    $apn->sound="com.gexin.ios.silence";
    $apn->contentAvailable=1;
    $apn->badge=1;
    $apn->add_customMsg("payload","payload");
    $apn->add_customMsg("keyType",$keyType);
    $apn->add_customMsg("keyId",$keyId);
    $apn->add_customMsg("nickname",$nickname);
    $apn->add_customMsg("msg",$msgContent);
 
    $apn->category="ACTIONABLE";
    $template->set_apnInfo($apn);

    return $template;
}

来来来,一起截图圈重点。
image.png
以我们公司做的产品为例:雇主在使用iOS客户端发单的时候,后台监听到雇主成功发单后,会访问个推提供的某个SDK,经过一系列的操作。最终iOS客户端在后台收到推送通知的时候,一定会执行xcode中的如下代码
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{  
    NSLog(@"%@",userInfo);
}

经过真机调试,符合静默推送(因为我的iOS真机设备在后台收到推送时,没有声音,没有文字,并且还执行了一段xcode中的方法,方法就在下面),

以下截图是采用静默推送的方式,iOS客户端在后台收到通知时,执行xcode中的下面的方法,打印的userInfo中的内容。

  • (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler;
// userInfo中的内容
{
  "_gurl_" : "sdk.open.extension.getui.com:8123",
  "_gmid_" : "OSL-0613_EK270rsK7ZA3frD1xut5B5:6b5a07fe4ef9477caa22c01a93aed697:4f561d975e202fcdb57a47068c5b956b",
  "keyId" : "1134",
  "aps" : {
    "content-available" : 1,
    "mutable-content" : 1,
    "badge" : 1,
    "category" : "ACTIONABLE"
  },
  "keyType" : "7",
  "payload" : "payload",
  "msg" : "有一条新的招工信息,点击查看详情",
  "_ge_" : "1"
}

image.png

PS:既然已经走到了这里,那么我们就可以实现这种恶搞的效果了:

用户已经将App退出到后台,此刻来了一个推送,通知栏没有标题和内容,但是用户能听到一段语音。用户很懵逼,不知道是哪个APP发出的声音。
实现方法:按照上面的一模一样的步骤配置成静默推送。然后配置如下方法,因为下面的这个方法是静默推送必定走的方法(我们在里面偷偷地写上了文字转语音的代码,哈哈哈~~~)

- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler{
   // 拿到userInfo中的关键内容,然后用苹果自带的功能进行文字转语音
}
image.png

静默推送遇到的坑(静默推送硬生生的做成了普通推送)。

下面就来看看由于我们公司的后台,设置静默推送不规范导致的iOS客户端在后台收到推送时,有声音有文字的情况。本质上变成了普通推送(有声音有文字)。

我们公司的后台说是 设置的是静默推送,但实际上从他给我PHP文件来看,没按照静默推送的格式来。导致客户端在后台时,通知栏会有通知的内容展示,同时也会有声音。
这与静默推送(收到推送,没有声音没有文字)的标准相悖了,导致一直在这个问题上卡了很久。
在此记录下来,以备不时之需,希望有遇到和我一样问题的朋友,少走一些坑。


后台设置的有问题的代码
function IGtTransmissionTemplateDemo($appid,$appkey,$msgContent,$keyType,$keyId,$temp_ietm="",$client_notice="default"){
    $msg = array(
        'keyType' => $keyType,
        'keyId' => $keyId,
        'msg' => $msgContent,
        'nickname' => $temp_ietm
    );
    $msg = json_encode($msg);
    $template =  new IGtTransmissionTemplate();
    $template->set_appId($appid);//应用appid
    $template->set_appkey($appkey);//应用appkey
    $template->set_transmissionType(2);//透传消息类型
    $template->set_transmissionContent($msg);//透传内容
   

    $apn = new IGtAPNPayload();
    $alertmsg=new DictionaryAlertMsg();
    $alertmsg->body=$msgContent;
    $alertmsg->actionLocKey="ActionLockey";
    $alertmsg->locKey=$msgContent;
    $alertmsg->locArgs=array("locargs");
    $alertmsg->launchImage="launchimage";
    //        IOS8.2 支持
    $alertmsg->title=SYS_ZH_NAME;
    $alertmsg->titleLocKey=SYS_ZH_NAME;
    $alertmsg->titleLocArgs=array("TitleLocArg");

    $apn->alertMsg=$alertmsg;
    $apn->contentAvailable=1;
    $apn->sound=$client_notice;
    $apn->badge=1;
    $apn->add_customMsg("payload","payload");
    $apn->add_customMsg("keyType",$keyType);
    $apn->add_customMsg("keyId",$keyId);
    $apn->add_customMsg("nickname",$nickname);
    $apn->add_customMsg("msg",$msgContent);
    $apn->category="ACTIONABLE";
    $template->set_apnInfo($apn);

    return $template;
}

截图展示后台设置的有问题的关键代码
image.png

分析静默推送格式不规范会出现哪些问题

以下情况满足的前提条件:②的值为1,即静默推送

  • ①是变量,当①有值时,iOS客户端在后台收到推送时,通知栏会有推送标题和内容的展示。

  • ①是变量,当①没有值时,iOS客户端在后台收到推送时,通知栏没有推送标题和内容的展示。

  • ③是变量,当③有值时:

    • 如果xcode中放置的音频文件和sound对应的值一样,那么iOS客户端在后台收到推送时,就会自动
      读出音频文件的声音。
      - 的是的撒的
    • 如果xcode中放置的音频文件和sound对应的值不一样,或者xcode中根本没有音频文件,那么iOS客户端在后台收到推送时,就会听见铛的一声。
  • ③是变量,当③没有值时,那么iOS客户端在后台收到推送时,就会听见铛的一声。

PS:以下①和③不是变量的情况。当然仍满足②是静默推送
PHP后台代码中,将①设置成空字符串,iOS客户端在后台收到推送时,通知栏没有推送标题和内容的展示
PHP后台代码中,将③设置成非com.gexin.ios.silence的任意字符串或者不和xcode中的音频文件重名的,这时iOS客户端在后台收到推送的时候,就会听见铛的一声。


打印的内容如下: 经过测试iOS客户端在后台收到推送时,会读取xcode中存放的音频文件notice_type1.caf,同时通知栏会展示标题(一秒招聘) 和 内容(有一条新的招工信息,点击查看详情)
{
  "_gurl_" : "sdk.open.extension.getui.com:8123",
  "_gmid_" : "OSL-0613_WzPFJBFf1BAXhORnt7bRn2:e34f8f8517034efa9773415a8d33190f:ada94b80070b9be823f25f8ea4577b92",
  "keyId" : "1131",
  "aps" : {
    "sound" : "notice_type1.caf",
    "content-available" : 1,
    "alert" : {
      "loc-args" : [
        "locargs"
      ],
      "title" : "一秒招聘",
      "title-loc-args" : [
        "TitleLocArg"
      ],
      "title-loc-key" : "一秒招聘",
      "action-loc-key" : "ActionLockey",
      "body" : "有一条新的招工信息,点击查看详情",
      "loc-key" : "有一条新的招工信息,点击查看详情",
      "launch-image" : "launchimage"
    },
    "mutable-content" : 1,
    "category" : "ACTIONABLE",
    "badge" : 1
  },
  "keyType" : "7",
  "payload" : "payload",
  "msg" : "有一条新的招工信息,点击查看详情",
  "_ge_" : "1"
}
以上xcode控制台输出的json数据若要符合静默推送,那么必须做如下修改:对应的让服务端改掉对应的内容即可
image.png

注意:本地存放的音频文件一定要放在该工作目录下
image.png

PS:当然,如果返回的json数据里面sound的值为"1"或者任意字符串就会出现铛的一声,如果sound的值能和xcode的该路径下的音频文件匹配上,那么iOS客户端在后台收到推送时,会自动读出匹配到的音频。


写到这里我在想,如果公司没有强制说要用户在后台的时候,不许在通知栏中展示内容和标题以及发出声音,那么你可以设置成在展示内容和标题以及会发出声音。此时content-available设置为0和1就没有区别了,因为你只要保证如下条件满足即可:


   // alert里面有内容 ; 必须保证有值
   $apn->alertMsg=$alertmsg;
    // 静默推送 1
    $apn->contentAvailable=1;
    // sound对应的值是字符串com.gexin.ios.silence或者sound对应的值是常量会静音。 
    // sound对应的值是常量,比如$apn->sound=1;会听见铛的一声。
    // sound对应的值是变量,如果xcode中的音频文件名能和变量对应起来,推送来的时候,会自动检索xcode中的音频文件,检索到就会读出来
    $apn->sound=$client_notice;

我们项目中有这么个需求,APP中所有的音频要么采用文字转语音,要么用录制好的音频文件,但是因为推送的内容有变量,比如xxx签到了您的家政服务工作,所以不能用录制好的音频文件。所以需求就这么出现了:
当推送过来的时候(在线、离线),有通知、系统推送来的铛的一声没做要求、 文字转语音。明确规定,要对推送过来的通知内容进行文字转语音,不能用录制好的音频文件

分析(在线走个推,所以肯定能文字转语音,这里就不说了,以下分析的是离线(APP在后台运行/APP未启动/APP被杀死)的情况),不考虑点击通知进入APP的情况:
  • 如果单纯采用标准的静默推送,肯定达不到效果:因为只要符合静默推送的格式,来推送的时候,没有通知也没有声音(铛的一声)。

    • 当程序在后台的时候,推送来的时候,还能执行一段方法(可以文字转语音读出来)。效果:通知栏没有通知、铛的一声有无(看后台配置的sound对应的值)、文字转语音。所以不符合
    • APP被杀死或者APP未启动的时候,推送来的时候,不会执行这段方法(代码都不走了,肯定没法进行文字转语音了)。效果:通知栏没有通知、铛的一声有无(看后台配置的sound对应的值)、没有文字转语音。所以不符合
  • 如果单纯采用标准的普通推送,肯定达不到效果

    • 当程序离线(APP在后台运行/APP未启动/APP被杀死)的时候,推送来的时候,有通知,有声音(铛的一声,不是文字转语音的声音),由于不能用录制好的音频文件,所以我将xcode里面的音频文件删除了,因此不会读音频文件。普通推送不点击通知,离线不会走xcode项目里面的任何代码,所以没法进行文字转语音。效果:通知栏有通知、铛的一声有无(看后台配置的sound对应的值)、没有文字转语音。所以不符合
  • 采用普通推送+静默推送混合的方式,APP在后台运行能符合要求,APP未启动/APP被杀死不符合要求:
    先说一下普通推送+静默推送混合的后台大致格式,具体参考上面的代码:

    // alert里面有内容 。普通推送alert中有内容
    $apn->alertMsg=$alertmsg;
    // 静默推送 1  之所以设置为1,是为了走xcode里面的某个方法
    $apn->contentAvailable=1;
    // sound对应的值是字符串com.gexin.ios.silence或者sound对应的值是常量会静音。 
    // sound对应的值是常量,比如$apn->sound=1;会听见铛的一声。
    // sound对应的值是变量,如果xcode中的音频文件名能和变量对应起来,推送来的时候,会自动检索xcode中的音频文件,检索到就会读出来
    $apn->sound=1;// 有铛的声音
  • 当程序在后台的时候,推送来的时候,有通知,铛的一声有无(看后台配置的sound对应的值),同时还能执行xcode里面的一段方法(该段方法里面写了文字转语音的代码)。效果:通知栏有通知、铛的一声有无(看后台配置的sound对应的值)、文字转语音。所以符合
  • APP被杀死或者APP未启动的时候,推送来的时候,通知栏有通知、铛的一声有无(看后台配置的sound对应的值)、没有文字转语音。所以不符合
所以,针对我们公司的要求,只能采用普通推送+静默推送混合的方式,这种方式APP在后台的时候满足公司的需求,APP被杀死或者APP未启动的时候,不满足需求,这是苹果的机制问题,这是最能契合公司需求的做法了,目前只能这么做,如果有其他方法,朋友们麻烦@一下我哦。

................................

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

推荐阅读更多精彩内容