iOS遠(yuǎn)程推送原理及實(shí)現(xiàn)過程

該文章是我16年在公司博客上寫的雁芙,除了證書注冊(cè)的過程大致沒有改變,像接收通知的方法都有所改變熬荆,所以將iOS 10 之后的接收通知及注冊(cè)通知的方法在文章中補(bǔ)全舟山,希望對(duì)正在處理遠(yuǎn)程推送的伙伴們有所幫助

一 、推送原理

  • 推送通知卤恳,是現(xiàn)在的應(yīng)用必不可少的功能累盗。那么在 iOS 中,我們是如何實(shí)現(xiàn)遠(yuǎn)程推送的呢突琳?iOS 的遠(yuǎn)程推送原理又是什么呢若债?在做 iOS 遠(yuǎn)程推送時(shí),我們會(huì)遇到各種各樣的問題拆融。那么首先讓我們準(zhǔn)備一些做推送需要的東西蠢琳。我們需要一個(gè)付費(fèi)的蘋果開發(fā)者賬號(hào)(免費(fèi)的不可以做遠(yuǎn)程推送),有了開發(fā)者賬號(hào)镜豹,我們可以去蘋果開發(fā)者網(wǎng)站傲须,配置自己所需要的推送的相關(guān)證書。然后下載證書趟脂,供我們后面使用泰讽,詳細(xì)的證書配置過程,我們下面再說。

  • 首先我們要說說iOS推送通知的基本原理:
    蘋果的推送服務(wù)通知是由自己專門的推送服務(wù)器APNs (Apple Push Notification service)來完成的已卸,其過程是 APNs 接收到我們自己的應(yīng)用服務(wù)器發(fā)出的被推送的消息佛玄,將這條消息推送到指定的 iOS 的設(shè)備上,然后再由 iOS設(shè)備通知到我們的應(yīng)用程序咬最,我們將會(huì)以通知或者聲音的形式收到推送回來的消息翎嫡。 iOS 遠(yuǎn)程推送的前提是,裝有我們應(yīng)用程序的 iOS 設(shè)備永乌,需要向 APNs 服務(wù)器注冊(cè)惑申,注冊(cè)成功后,APNs 服務(wù)器將會(huì)給我們返回一個(gè) devicetoken翅雏,我們獲取到這個(gè) token 后會(huì)將這個(gè) token 發(fā)送給我們自己的應(yīng)用服務(wù)器圈驼。當(dāng)我們需要推送消息時(shí),我們的應(yīng)用服務(wù)器將消息按照指定的格式進(jìn)行打包望几,然后結(jié)合 iOS 設(shè)備的 devicetoken 一起發(fā)給 APNs 服務(wù)器绩脆。我們的應(yīng)用會(huì)和 APNs 服務(wù)器維持一個(gè)基于 TCP 的長(zhǎng)連接,APNs 服務(wù)器將新消息推送到iOS 設(shè)備上橄抹,然后在設(shè)備屏幕上顯示出推送的消息靴迫。

  • 設(shè)備注冊(cè)APNs的流程圖:


    注冊(cè)APNs的流程圖.png
  • 上圖完成了如下步驟:
  1. Device(設(shè)備)連接APNs服務(wù)器并攜帶設(shè)備序列號(hào)(UUID)

  2. 連接成功,APNs經(jīng)過打包和處理產(chǎn)生devicetoken并返回給注冊(cè)的Device(設(shè)備)

  3. Device(設(shè)備)攜帶獲取的devicetoken發(fā)送到我們自己的應(yīng)用服務(wù)器

  4. 完成需要被推送的Device(設(shè)備)在APNs服務(wù)器和我們自己的應(yīng)用服務(wù)器的注冊(cè)

  • 推送過程圖:
推送過程圖.png
  • 推送的過程經(jīng)過如下步驟:
  1. 首先楼誓,我們的設(shè)備安裝了具有推送功能的應(yīng)用(應(yīng)用程序要用代碼注冊(cè)消息推動(dòng))玉锌,我們的 iOS設(shè)備在有網(wǎng)絡(luò)的情況下會(huì)連接APNs推送服務(wù)器,連接過程中疟羹,APNS 服務(wù)器會(huì)驗(yàn)證devicetoken主守,連接成功后維持一個(gè)基于TCP 的長(zhǎng)連接;

  2. Provider(我們自己的應(yīng)用服務(wù)器)收到需要被推送的消息并結(jié)合被推送的 iOS設(shè)備的devicetoken一起打包發(fā)送給APNS服務(wù)器榄融;

  3. APNS服務(wù)器將推送信息推送給指定devicetoken的iOS設(shè)備参淫;

  4. iOS設(shè)備收到推送消息后通知我們的應(yīng)用程序并顯示和提示用戶(聲音、彈出框)

  • 比較直觀的流程圖:
直觀的流程圖.png
  • 信息包結(jié)構(gòu)圖:
信息包結(jié)構(gòu)圖.png
  • 上圖顯示的這個(gè)消息體就是我們的應(yīng)用服務(wù)器(Provider)發(fā)送給APNs服務(wù)器的消息結(jié)構(gòu)愧杯,APNs驗(yàn)證這個(gè)結(jié)構(gòu)正確并提取其中的信息后涎才,再將消息推送到指定的iOS設(shè)備。這個(gè)結(jié)構(gòu)體包括五個(gè)部分力九,第一個(gè)部分是命令標(biāo)示符耍铜,第二個(gè)部分是我們的devicetoken的長(zhǎng)度,第三部分是我們的devicetoken字符串畏邢,第四部分是推送消 息體(Payload)的長(zhǎng)度,最后一部分也就是真正的消息內(nèi)容了检吆,里面包含了推送消息的基本信息舒萎,比如消息內(nèi)容,應(yīng)用Icon右上角顯示多少數(shù)字以及推送消息到達(dá)時(shí)所播放的聲音等

  • Payload(消息體)的結(jié)構(gòu):

{
     “aps”:{
     “alert”:“聽云給您發(fā)送了新消息”,
     “badge”:1,
     “sound”:“default”
     },
}
  • 這其實(shí)就是個(gè)JSON結(jié)構(gòu)體,alert標(biāo)簽的內(nèi)容就是會(huì)顯示在用戶手機(jī)上的推送信息臂寝,badge顯示的數(shù)量(注意是整型)是會(huì)在應(yīng)用Icon右上角顯示的數(shù)量章鲤,提示有多少條未讀消息等,sound就是當(dāng)推送信息送達(dá)是手機(jī)播放的聲音咆贬,傳defalut就標(biāo)明使用系統(tǒng)默認(rèn)聲音败徊。

二、證書及推送實(shí)現(xiàn)過程

  1. 首先我們要新建一個(gè)Certificate Signing Request(也就是CSR)的請(qǐng)求文件
  • 在應(yīng)用程序里的使用工具中找到鑰匙串訪問掏缎,選擇從證書頒發(fā)機(jī)構(gòu)請(qǐng)求證書




  • 保存位置在 tingyun(指定自己的文件夾皱蹦,這里我選擇的是我的文件夾),點(diǎn)擊存儲(chǔ)。

  • 然后點(diǎn)擊完成后我們會(huì)在 tingyun 里看到一個(gè)CertificateSigningRequest.certSigningRequest的請(qǐng)求文件眷蜈,也就是我們說的CSR文件沪哺。在我們生成CSR文件的同時(shí),會(huì)在鑰匙串訪問中生成一對(duì)秘鑰酌儒,名稱為剛才我們填寫的常用名辜妓。

  1. 配置AppID
  • 到蘋果開發(fā)者網(wǎng)站https://developer.apple.com

  • 點(diǎn)擊Account


  • 選擇 Certificates,identifiers&Profiles


  • 選擇 Identifiers ->App IDs 點(diǎn)擊上方的+號(hào)創(chuàng)建一個(gè) App ID.


  • Name: 填寫 App 的名字就行

  • App ID Suffix 選擇不用通配符的及 Explicit App ID

  • Bundle ID:填寫自己應(yīng)用的 Bundle ID 一定要和自己應(yīng)用的一致.


  • 在下面的 App Services 中選擇自己需要的服務(wù),我們需要推送服務(wù),所以在Push Notifications上打勾忌怎,然后點(diǎn)擊continue籍滴。


  1. 創(chuàng)建證書
  • 證書需要?jiǎng)?chuàng)建兩種,一種是開發(fā)的榴啸、一種是發(fā)布的孽惰,開發(fā)的是做測(cè)試用的。

  • 選擇Development 點(diǎn)擊右上角的+號(hào),創(chuàng)建證書,我們首先創(chuàng)建開發(fā)證書


  • 選擇Apple Push Notification service SSL (Sandbox),創(chuàng)建推送服務(wù)證書點(diǎn)擊下一步


  • 這兒的 App ID 選擇我們剛才創(chuàng)建的 App ID插掂,然后點(diǎn)擊下一步,下一步

  • 這兒點(diǎn)擊 Choose File,選擇我們剛才創(chuàng)建的 CSR 文件灰瞻,然后點(diǎn)擊生成(Generate)。最后點(diǎn)擊下載,下載證書辅甥。將下載的證書酝润,放到指定位置。
  • 發(fā)布證書的創(chuàng)建和開發(fā)證書一樣,選擇Production->Apple Push Notification service SSL (Production)璃弄,后面和開發(fā)證書一樣要销。


  1. 添加 Devices (一個(gè)公司賬號(hào)、企業(yè)賬號(hào)或者個(gè)人賬號(hào)夏块,可添加100個(gè)設(shè)備):
  • 首先選中你要添加哪種設(shè)備疏咐,然后在左上角點(diǎn)擊“+”號(hào)。


  • Name 填寫一個(gè)設(shè)備名字脐供,UDID 填寫自己需要加入測(cè)試的設(shè)備的 UDID浑塞,然后點(diǎn)擊下一步。

  • 然后點(diǎn)擊 Register 即可
  • 點(diǎn)擊Done政己。


  1. 查找設(shè)備的 UDID:
  • 用自己的 iOS 設(shè)備連接到電腦上酌壕,打開 iTunes。在設(shè)備摘要處可以看見一個(gè)序列號(hào),點(diǎn)擊序列號(hào)就會(huì)變成 UDID卵牍。
  1. 生成配置文件
  • 配置文件也有兩種果港,一種是開發(fā)的,一種是發(fā)布的糊昙,開發(fā)的使我們做測(cè)試需要的辛掠,發(fā)布的是我們?cè)?Appstore 上發(fā)布時(shí)需要的,我們都需要生成释牺。

  • 我們先生成開發(fā)配置文件,選擇Provisioning Profiles->Development點(diǎn)擊右上角的+號(hào)萝衩。

  • 選擇iOS App Development 點(diǎn)擊下一步


  • 這兒的 App ID 仍然選擇我們剛才創(chuàng)建的 App ID


  • 這兒選擇我們開發(fā)者的證書,如果不知道是哪個(gè)選擇全部即可


  • 這兒選擇我們的測(cè)試設(shè)備,如果沒有則在前面的Devices里面添加即可



  • 隨便取個(gè)名字即可,然后下載下來


  • 發(fā)布配置文件和開發(fā)配置文件一樣創(chuàng)建,選擇Distribution->Ad Hoc即可,后面與發(fā)布配置文件一樣船侧。


三欠气、證書配置完成,打開我們創(chuàng)建的應(yīng)用項(xiàng)目

  • 打開AppDelegate.m 文件,在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 方法中添加下面代碼,注冊(cè)消息推送
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    /*
     注冊(cè)通知(推送)
     申請(qǐng)App需要接受來自服務(wù)商提供推送消息
     */
    
    if ([[UIDevice currentDevice].systemVersion floatValue] >= 10.0) {
        //iOS10特有
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        // 必須寫代理,不然無法監(jiān)聽通知的接收與點(diǎn)擊
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionAlert | UNAuthorizationOptionBadge | UNAuthorizationOptionSound) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (granted) {
                // 點(diǎn)擊允許
                //NSLog(@"注冊(cè)成功");
                [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
                    //NSLog(@"%@", settings);
                }];
            } else {
                // 點(diǎn)擊不允許
                // NSLog(@"注冊(cè)失敗");
            }
        }];
    }
    else if ([[UIDevice currentDevice].systemVersion floatValue] >8.0){
        //iOS8 - iOS10
        [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeSound | UIUserNotificationTypeBadge categories:nil]];
        
    }
    else
    {
        UIRemoteNotificationType apn_type = (UIRemoteNotificationType)(UIRemoteNotificationTypeAlert |UIRemoteNotificationTypeSound |
                                                                       UIRemoteNotificationTypeBadge);
        [[UIApplication sharedApplication] registerForRemoteNotificationTypes:apn_type];
    }
    // 注冊(cè)獲得device Token
    [[UIApplication sharedApplication] registerForRemoteNotifications];
    return YES;
}

//下面方法是返回 ANPs 蘋果推送服務(wù)器生成的唯一標(biāo)識(shí)
/** 接收服務(wù)器傳回的設(shè)備唯一標(biāo)識(shí) token */
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
    
    // 第一次運(yùn)行獲取到DeviceToken時(shí)間會(huì)比較長(zhǎng)镜撩!
    // 將deviceToken轉(zhuǎn)換成字符串孵构,以便后續(xù)使用
    NSString *token = [deviceToken description];
    NSLog(@"description %@", token);
}

//下面方法是當(dāng)注冊(cè)推送服務(wù)失敗時(shí),接收錯(cuò)誤信息
/** 注冊(cè)推送服務(wù)失敗 */
-(void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"注冊(cè)失敗 %@",error);
}

//下面方法是當(dāng)有消息推送回來時(shí),接收推送消息 
/** 設(shè)備接收到來自蘋果推送服務(wù)器的消息時(shí)觸發(fā)的,用來顯示推送消息 */

// iOS 10收到通知(前臺(tái))
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler{
    NSDictionary * userInfo = notification.request.content.userInfo;
    UNNotificationRequest *request = notification.request; // 收到推送的請(qǐng)求
    UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
    NSNumber *badge = content.badge;  // 推送消息的角標(biāo)
    NSString *body = content.body;    // 推送消息體
    UNNotificationSound *sound = content.sound;  // 推送消息的聲音
    NSString *subtitle = content.subtitle;  // 推送消息的副標(biāo)題
    NSString *title = content.title;  // 推送消息的標(biāo)題
    
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 前臺(tái)收到遠(yuǎn)程通知:%@", [self logDic:userInfo]);
        
    }
    else {
        // 判斷為本地通知
        NSLog(@"iOS10 前臺(tái)收到本地通知:{\\\\nbody:%@终吼,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@,\\\\nsound:%@,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
    }
    completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert); // 需要執(zhí)行這個(gè)方法锨亏,選擇是否提醒用戶皂甘,有Badge廓握、Sound伴鳖、Alert三種類型可以設(shè)置
}

//iOS 10  通知的點(diǎn)擊事件(點(diǎn)擊通知)
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)())completionHandler{
    
    NSDictionary * userInfo = response.notification.request.content.userInfo;
    UNNotificationRequest *request = response.notification.request; // 收到推送的請(qǐng)求
    UNNotificationContent *content = request.content; // 收到推送的消息內(nèi)容
    NSNumber *badge = content.badge;  // 推送消息的角標(biāo)
    NSString *body = content.body;    // 推送消息體
    UNNotificationSound *sound = content.sound;  // 推送消息的聲音
    NSString *subtitle = content.subtitle;  // 推送消息的副標(biāo)題
    NSString *title = content.title;  // 推送消息的標(biāo)題
    if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 收到遠(yuǎn)程通知:%@", [self logDic:userInfo]);
        
    }
    else {
        // 判斷為本地通知
        NSLog(@"iOS10 收到本地通知:{\\\\nbody:%@,\\\\ntitle:%@,\\\\nsubtitle:%@,\\\\nbadge:%@锯梁,\\\\nsound:%@即碗,\\\\nuserInfo:%@\\\\n}",body,title,subtitle,badge,sound,userInfo);
    }
    
    // Warning: UNUserNotificationCenter delegate received call to -userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler: but the completion handler was never called.
    completionHandler();  // 系統(tǒng)要求執(zhí)行這個(gè)方法

}

//iOS 6 及以下系統(tǒng)通知
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo {
    NSLog(@"iOS6及以下系統(tǒng),收到通知:%@",userInfo);
}

//iOS 7 及以上系統(tǒng)通知(前臺(tái)/后臺(tái))
- (void)application:(UIApplication *)application
didReceiveRemoteNotification:(NSDictionary *)userInfo
fetchCompletionHandler:
(void (^)(UIBackgroundFetchResult))completionHandler {
    
    NSLog(@"iOS7及以上系統(tǒng)陌凳,收到通知:%@",userInfo);
    completionHandler(UIBackgroundFetchResultNewData);
}

四剥懒、服務(wù)器端(Java服務(wù)器)

  • 服務(wù)器端我們需要,一個(gè)后綴為. p12的證書,以及需要的 jar 包

  • 服務(wù)器端的證書生成方式:

1、打開我們前面下載的證書,在鑰匙串中找到它


2合敦、點(diǎn)擊鼠標(biāo)右鍵選擇導(dǎo)出


3初橘、導(dǎo)出后綴為.p12的文件保存到自己的電腦上,需要輸入一個(gè)密碼,在 Java 服務(wù)器端要用到


4、Java服務(wù)器端需要的 Jar 包

5充岛、Java 服務(wù)器端代碼:

import javapns.back.PushNotificationManager;
import javapns.back.SSLConnectionHelper;
import javapns.data.Device;
import javapns.data.PayLoad;
public class pushService {
    public static void main(String[] args) {
           
           
          try {

                          //這個(gè)token  就是客戶端從APNs服務(wù)器獲取到的devicetoken
                   String deviceToken = "eab6df47eb4f81e0aaa93bb208cffd7dc3884fd346ea0743fcf93288018cfcb6";
                   //被推送的iphone應(yīng)用程序標(biāo)示符      
                   PayLoad payLoad = new PayLoad();
                   payLoad.addAlert("測(cè)試我的push消息");
                   payLoad.addBadge(1);
                   payLoad.addSound("default");
                            
                   PushNotificationManager pushManager = PushNotificationManager.getInstance();
                   pushManager.addDevice("iphone", deviceToken);
                   
                                   //測(cè)試推送服務(wù)器地址:gateway.sandbox.push.apple.com /2195 
                   //產(chǎn)品推送服務(wù)器地址:gateway.push.apple.com / 2195 
                   String host="gateway.sandbox.push.apple.com";  //測(cè)試用的蘋果推送服務(wù)器
                   int port = 2195;
                   String certificatePath = "/Users/hsw/Desktop/PushTest/PushTest.p12"; //剛才在mac系統(tǒng)下導(dǎo)出的證書
                   
                   String certificatePassword= "123456";
                  
                   pushManager.initializeConnection(host, port, certificatePath,certificatePassword, SSLConnectionHelper.KEYSTORE_TYPE_PKCS12);
                             
                   //Send Push
                   Device client = pushManager.getDevice("iphone");
                   pushManager.sendNotification(client, payLoad); //推送消息
                   pushManager.stopConnection();
                   pushManager.removeDevice("iphone");
                  }
                  catch (Exception e) {
                   e.printStackTrace();
                   System.out.println("push faild!");
                    return;
                  }
                  System.out.println("push succeed!");
                 }

}

注意保檐,我有看到轉(zhuǎn)載的提問,服務(wù)端是否需要deviceToken崔梗,這個(gè)肯定是需要的夜只,在上面Java的代碼中也有寫到。deviceToken是設(shè)備唯一的推送標(biāo)識(shí)蒜魄,服務(wù)端只有知道這個(gè)標(biāo)識(shí)扔亥,才能夠?qū)⑼ㄖ扑偷侥愕脑O(shè)備上爪膊。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市砸王,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌峦阁,老刑警劉巖谦铃,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異榔昔,居然都是意外死亡驹闰,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門撒会,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嘹朗,“玉大人,你說我怎么就攤上這事诵肛∫倥啵” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵怔檩,是天一觀的道長(zhǎng)褪秀。 經(jīng)常有香客問我,道長(zhǎng)薛训,這世上最難降的妖魔是什么媒吗? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮乙埃,結(jié)果婚禮上闸英,老公的妹妹穿的比我還像新娘。我一直安慰自己介袜,他們只是感情好甫何,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著米酬,像睡著了一般沛豌。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上赃额,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天加派,我揣著相機(jī)與錄音,去河邊找鬼跳芳。 笑死芍锦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的飞盆。 我是一名探鬼主播娄琉,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼次乓,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了孽水?” 一聲冷哼從身側(cè)響起票腰,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎女气,沒想到半個(gè)月后杏慰,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡炼鞠,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年缘滥,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谒主。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡朝扼,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出霎肯,到底是詐尸還是另有隱情擎颖,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布观游,位于F島的核電站肠仪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏备典。R本人自食惡果不足惜异旧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望提佣。 院中可真熱鬧吮蛹,春花似錦、人聲如沸拌屏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽倚喂。三九已至每篷,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間端圈,已是汗流浹背焦读。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舱权,地道東北人矗晃。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像宴倍,于是被迫代替她去往敵國(guó)和親张症。 傳聞我的和親對(duì)象是個(gè)殘疾皇子仓技,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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