Android自動(dòng)化埋點(diǎn)技術(shù)探索-前言

前言:

本篇文章是《Android自動(dòng)化埋點(diǎn)技術(shù)探索》的第一篇鲁冯,主要介紹埋點(diǎn)的基本概念以及幾種埋點(diǎn)技術(shù)實(shí)現(xiàn)方式的原理和差異

埋點(diǎn)基本概念及其意義

當(dāng)一款A(yù)ndroid應(yīng)用上線后,開(kāi)發(fā)人員或者運(yùn)營(yíng)人員,也可能是市場(chǎng)分析人員蔑水、管理人員系枪、亦或者老板希望能收集一些用戶(hù)操作的行為數(shù)據(jù)戴已,比如用戶(hù)在某個(gè)頁(yè)面點(diǎn)擊了多少次,應(yīng)用中的某個(gè)控件被點(diǎn)擊了多少次握础,在某個(gè)頁(yè)面停留了多少時(shí)間等等,這些行為數(shù)據(jù)統(tǒng)一收集起來(lái)之后就可以交給數(shù)據(jù)分析師來(lái)進(jìn)行數(shù)據(jù)的篩選悴品、統(tǒng)計(jì)禀综、分析、決策他匪,而且以便于后期應(yīng)用的方向性調(diào)整和技術(shù)功能調(diào)整菇存。理論上來(lái)講,這些收集統(tǒng)計(jì)的數(shù)據(jù)應(yīng)該出自應(yīng)用的PV(頁(yè)面訪問(wèn)量)或UV(獨(dú)立訪客訪問(wèn)數(shù))邦蜜、或者統(tǒng)計(jì)應(yīng)用中那些具體的頁(yè)面最受歡迎依鸥、那些控件點(diǎn)擊率最高or最低的場(chǎng)景。

舉例悼沈,對(duì)于控件被點(diǎn)擊多少次這個(gè)應(yīng)用場(chǎng)景贱迟,開(kāi)發(fā)人員的一般做法是在控件點(diǎn)擊事件中加入Log代碼,然后將此次的點(diǎn)擊記錄下來(lái)(自增)絮供,最終發(fā)送到服務(wù)端進(jìn)行數(shù)據(jù)上傳衣吠。頁(yè)面的點(diǎn)擊也是類(lèi)似,需要在頁(yè)面生命周期的開(kāi)始加入Log代碼壤靶。但如果業(yè)務(wù)邏輯復(fù)雜缚俏,頁(yè)面眾多,控件較多,那就要在許多地方插入這些數(shù)據(jù)上傳的代碼忧换,因此實(shí)現(xiàn)方式和后期維護(hù)就成為了一個(gè)問(wèn)題恬惯。通過(guò)在具體的功能實(shí)現(xiàn)的時(shí)候,去進(jìn)行數(shù)據(jù)的存儲(chǔ)和上傳亚茬,這種技術(shù)可以簡(jiǎn)單理解為埋點(diǎn) 酪耳。那么有沒(méi)有一種侵入方式低、集成起來(lái)簡(jiǎn)單就可以快速實(shí)現(xiàn)數(shù)據(jù)統(tǒng)計(jì)的埋點(diǎn)技術(shù)刹缝?

目前常見(jiàn)的前端埋點(diǎn)技術(shù)碗暗,一共有三大類(lèi):

  • 在某個(gè)控件操作發(fā)生時(shí)通過(guò)預(yù)先寫(xiě)好的代碼來(lái)發(fā)數(shù)據(jù)的代碼埋點(diǎn)
  • 通過(guò)可視化界面配置控件操作與事件發(fā)生關(guān)系的可視化埋點(diǎn)
  • 收集所有數(shù)據(jù)之后,在后端篩選需要分析的對(duì)象的“無(wú)埋點(diǎn)”

關(guān)于這三種方案梢夯,下面做詳細(xì)的解釋說(shuō)明:

可視化埋點(diǎn)之代碼埋點(diǎn)

我相信這個(gè)可視化埋點(diǎn)技術(shù)是最簡(jiǎn)單也是最容易理解的一種實(shí)現(xiàn)方式言疗,通過(guò)在需要統(tǒng)計(jì)的功能代碼處,直接使用埋點(diǎn)SDK的代碼來(lái)進(jìn)行上傳數(shù)據(jù)的技術(shù)颂砸,例如熟悉的友盟統(tǒng)計(jì):

public void onResume() {  
    super.onResume();
    //統(tǒng)計(jì)頁(yè)面洲守,僅有Activity的應(yīng)用中SDK自動(dòng)調(diào)用,不需要單獨(dú)寫(xiě)沾凄。
    //"SplashScreen"為頁(yè)面名稱(chēng),可自定義
    MobclickAgent.onPageStart("SplashScreen"); 
    //統(tǒng)計(jì)時(shí)長(zhǎng)
    MobclickAgent.onResume(this);         
}
 
public void onPause() {  
    super.onPause();
    //僅有Activity的應(yīng)用中SDK自動(dòng)調(diào)用知允,不需要單獨(dú)寫(xiě)
    //保證 onPageEnd 在onPause 之前調(diào)用,因?yàn)?onPause 中會(huì)保存信息撒蟀。
    //"SplashScreen"為頁(yè)面名稱(chēng),可自定義
    MobclickAgent.onPageEnd("SplashScreen");
    MobclickAgent.onPause(this);
}

簡(jiǎn)而言之這一類(lèi)技術(shù)温鸽,是通過(guò)代碼手動(dòng)設(shè)置的可視化埋點(diǎn)功能代碼保屯,在APP或者界面初始化的時(shí)候,初始化第三方數(shù)據(jù)分析服務(wù)商的SDK涤垫,然后在某個(gè)事件發(fā)生時(shí)就調(diào)用SDK里面相應(yīng)的數(shù)據(jù)發(fā)送接口發(fā)送數(shù)據(jù)姑尺。例如,想統(tǒng)計(jì)APP里面某個(gè)按鈕的點(diǎn)擊次數(shù)蝠猬,則在APP的某個(gè)按鈕被點(diǎn)擊時(shí)切蟋,可以在這個(gè)按鈕對(duì)應(yīng)的 OnClick 函數(shù)里面調(diào)用SDK提供的數(shù)據(jù)發(fā)送接口來(lái)發(fā)送數(shù)據(jù)。

代碼埋點(diǎn)的優(yōu)點(diǎn)是一方面使用者控制精準(zhǔn)榆芦,可以非常精確地選擇什么時(shí)候發(fā)送數(shù)據(jù)柄粹;同時(shí),使用者可以比較方便地設(shè)置自定義屬性匆绣、自定義事件驻右,傳遞比較豐富的數(shù)據(jù)到服務(wù)端。

當(dāng)然崎淳,代碼埋點(diǎn)的劣勢(shì)在于:首先堪夭,埋點(diǎn)代價(jià)比較大,每一個(gè)控件的埋點(diǎn)都需要添加相應(yīng)的代碼,工作量會(huì)增大森爽,而且限定了實(shí)現(xiàn)該功能的角色必須是技術(shù)人員才能完成恨豁;其次是功能更新的代價(jià)較大,每一次更新埋點(diǎn)方案拗秘,都須要改代碼圣絮,更新完之后還要通過(guò)各個(gè)應(yīng)用市場(chǎng)進(jìn)行分發(fā),并且總有一定數(shù)量的用戶(hù)不喜歡更新APP雕旨,這樣埋點(diǎn)代碼也就得不到更新了扮匠;最后,就是所有前端埋點(diǎn)方案都會(huì)面臨的數(shù)據(jù)傳輸時(shí)效性和可靠性的問(wèn)題了凡涩,這個(gè)問(wèn)題就只能通過(guò)在后端收集數(shù)據(jù)來(lái)解決了棒搜。

可視化埋點(diǎn)之頁(yè)面配置埋點(diǎn)

通過(guò)頁(yè)面配置來(lái)實(shí)現(xiàn)埋點(diǎn)的技術(shù),其實(shí)是對(duì)第一種埋點(diǎn)技術(shù)-可視化代碼埋點(diǎn)技術(shù)的一種升級(jí)活箕,這種方式的實(shí)現(xiàn)過(guò)程如下:

  • 在嵌入了埋點(diǎn) SDK 的 APP 開(kāi)啟可視化埋點(diǎn)模式力麸,SDK 會(huì)請(qǐng)求然后響應(yīng)服務(wù)端的要求,APP內(nèi)部定期(例如每秒)做一次截圖育韩,而 SDK 在為 App 截圖的同時(shí)克蚂,會(huì)從Window 對(duì)象開(kāi)始進(jìn)行遍歷頁(yè)面的子view,得到當(dāng)前視圖下所有View對(duì)象的層級(jí)關(guān)系筋讨。

  • 拿到View對(duì)象之后就可以獲取一系列數(shù)據(jù)

  • 服務(wù)端根據(jù)截屏和可視化信息來(lái)重新進(jìn)行頁(yè)面渲染埃叭,并且根據(jù)控件的類(lèi)型,來(lái)識(shí)別哪些控件是可以增加可埋點(diǎn)的悉罕,并且將之標(biāo)識(shí)出來(lái)赤屋。

  • 當(dāng)使用者在后臺(tái)的截屏畫(huà)面上點(diǎn)擊了某個(gè)可埋點(diǎn)的控件時(shí),后臺(tái)會(huì)要求使用者做一些事件關(guān)聯(lián)方面的配置壁袄,并且將配置信息進(jìn)行保存和部署类早。

  • SDK 在啟動(dòng)或者例行輪詢(xún)時(shí)拿到這些配置信息,則會(huì)通過(guò)設(shè)定的接口嗜逻,為每個(gè)關(guān)聯(lián)的控件添加的點(diǎn)擊或者編輯行為的監(jiān)聽(tīng)涩僻,并在回掉函數(shù)里面調(diào)用 SDK內(nèi)部的接口發(fā)送相應(yīng)事件的 track 信息來(lái)反饋埋點(diǎn)數(shù)據(jù)

至此,通過(guò)頁(yè)面來(lái)進(jìn)行配置埋點(diǎn)的技術(shù)大概實(shí)現(xiàn)過(guò)程就是這樣栈顷。這種通過(guò)頁(yè)面來(lái)進(jìn)行配置的可視化埋點(diǎn)技術(shù)很好地解決了代碼埋點(diǎn)的埋點(diǎn)代價(jià)較大以及更新代價(jià)大兩個(gè)問(wèn)題令哟。但是,通過(guò)頁(yè)面來(lái)進(jìn)行配置的可視化技術(shù)能夠覆蓋的功能有限妨蛹,目前并不是所有的控件操作都可以通過(guò)這種方案進(jìn)行定制屏富;同時(shí),這種可視化埋點(diǎn)技術(shù)方案對(duì)自己設(shè)置屬性有一定的缺陷蛙卤,例如狠半,一個(gè)界面上有一個(gè)文本框和一個(gè)按鈕噩死,通過(guò)可視化埋點(diǎn)設(shè)置點(diǎn)擊按鈕為一個(gè)“提交”事件時(shí),并不能將文本框的內(nèi)容作為事件的屬性進(jìn)行上傳的神年,因此已维,對(duì)于可視化埋點(diǎn)這種方案,在上傳事件時(shí)已日,就只能上傳 SDK 自動(dòng)收集的設(shè)備垛耳、地域、網(wǎng)絡(luò)等默認(rèn)屬性飘千,以及一些通過(guò)代碼設(shè)置的全局公共屬性了堂鲜;最后,作為前端埋點(diǎn)的一種方案护奈,可視化埋點(diǎn)也依然沒(méi)有解決傳輸時(shí)效性和數(shù)據(jù)可靠性的問(wèn)題缔莲。

自動(dòng)化埋點(diǎn)

自動(dòng)化埋點(diǎn),也叫無(wú)埋點(diǎn)霉旗、無(wú)碼埋點(diǎn)痴奏、全埋點(diǎn)。自動(dòng)化埋點(diǎn)是指預(yù)先收集用戶(hù)的所有行為數(shù)據(jù)厌秒,然后再根據(jù)實(shí)際分析需求從中提取行為數(shù)據(jù)读拆。自動(dòng)化埋點(diǎn)技術(shù)的整體解決思路,首先就是要找到那個(gè)被點(diǎn)擊的View的點(diǎn)擊處理邏輯(也叫原處理邏輯)鸵闪,然后利用一定的技術(shù)建椰,對(duì)原處理邏輯進(jìn)行“攔截”,或者在原處理邏輯的前面或者后面“插入”相應(yīng)的埋點(diǎn)代碼岛马,從而達(dá)到自動(dòng)埋點(diǎn)的效果。

那么如何做到自動(dòng)“攔截” View 的原點(diǎn)擊處理邏輯屠列?一般是參考 Android 系統(tǒng) View 點(diǎn)擊事件處理機(jī)制來(lái)進(jìn)行的啦逆。至于如何做到自動(dòng)“插入”埋點(diǎn)代碼,基本上都是參考編譯器對(duì) Java 代碼的處理流程來(lái)進(jìn)行的笛洛,即:JavaCode --> .java --> .class --> .dex

由于無(wú)埋點(diǎn)技術(shù)會(huì)涉及到apk的構(gòu)建流程夏志,這里先貢獻(xiàn)一張APK的構(gòu)建流程圖:

APK構(gòu)建流程

在理解構(gòu)建流程之前,首先要了解構(gòu)建過(guò)程中各個(gè)工具的意義和主要功能苛让,下面就對(duì)功能做詳細(xì)的敘述:

名字 功能 詳細(xì)介紹
aapt Android資源打包工具 可以查看沟蔑,創(chuàng)建, 更新ZIP格式的文檔附件(zip, jar, apk)狱杰。也可將資源文件編譯成二進(jìn)制文件瘦材。
aidl Android接口描述語(yǔ)言轉(zhuǎn)化為.java文件的工具 將android中我們用到的接口類(lèi)描述語(yǔ)言,例如跨進(jìn)程的aidl文件轉(zhuǎn)化為java文件仿畸。
javac Java Compiler java語(yǔ)言編程編譯器食棕。全稱(chēng)javacompilation朗和。javac工具讀由java語(yǔ)言編寫(xiě)的類(lèi)和接口的定義,并將它們編譯成字節(jié)代碼的class文件簿晓。javac 可以隱式編譯一些沒(méi)有在命令行中提及的源文件眶拉。
dex 轉(zhuǎn)化.class文件為Davik VM能識(shí)別的.dex文件 把所有的字節(jié)碼文件轉(zhuǎn)成Android DEX文件(classes.dex)。它是Android平臺(tái)上可執(zhí)行文件的類(lèi)型憔儿。dx工具的主要工作是將Java字節(jié)碼轉(zhuǎn)成成Dalvik字節(jié)碼忆植、壓縮常量池、消除冗余信息等谒臼。
apkbuilder 生成apk包 將所有沒(méi)有編譯的資源(如images等)朝刊、編譯過(guò)的資源和.dex文件都會(huì)打包到最終的.apk文件中。
jarsigner jar文件的簽名工具 工具利用密鑰倉(cāng)庫(kù)中的信息來(lái)產(chǎn)生或校驗(yàn) Java 存檔 (JAR) 文件的數(shù)字簽名
zipalign 字節(jié)碼對(duì)齊工具 它能夠?qū)Υ虬膽?yīng)用程序進(jìn)行優(yōu)化屋休。

那么坞古,APK構(gòu)建的執(zhí)行步驟分別就是:

步驟1.

使用aapt工具生成R.java文件

Resource文件(就是工程中res中的文件)、Assets文件(相當(dāng)于另外一種資源劫樟,這種資源Android系統(tǒng)并不像對(duì)res中的文件那樣優(yōu)化它)痪枫、AndroidManifest.xml文件(包名就是從這里讀取的,因?yàn)樯蒖.java文件需要包名)叠艳、Android基礎(chǔ)類(lèi)庫(kù)(Android.jar文件)打包成資源(一般在Android工程的bin目錄可以看到一個(gè)叫resources.ap_的文件就是它了)奶陈、R.java文件(在gen目錄中)。

步驟 2.

處理AIDL文件附较,生成對(duì)應(yīng)的.java文件

將源碼文件吃粒、aidl文件、framework.aidl等應(yīng)用到aidl的描述語(yǔ)言文件轉(zhuǎn)化為java文件拒课。

步驟 3.

編譯Java文件徐勃,生成對(duì)應(yīng)的.class文件

將源碼文件(包括R.java和AIDL生成的.java文件)、庫(kù)文件(.jar文件)編譯為.class文件早像。

步驟 4.

把.class文件轉(zhuǎn)化成Davik VM支持的.dex文件

將任何第三方的libraries和.class文件都會(huì)被轉(zhuǎn)換成.dex文件僻肖。dex工具生成可供Android系統(tǒng)Dalvik虛擬機(jī)執(zhí)行的classes.dex文件。

步驟 5.

打包生成APK文件

所有沒(méi)有編譯的資源(如images等)卢鹦、編譯過(guò)的資源和.dex文件都會(huì)被apkbuilder工具打包到最終的.apk文件中臀脏。

步驟 6.

對(duì)APK文件進(jìn)行簽名

一旦APK文件生成,它必須被簽名才能被安裝在設(shè)備上冀自。在開(kāi)發(fā)過(guò)程中揉稚,主要用到的就是兩種簽名的keystore。一種是用于調(diào)試的debug.keystore熬粗,它主要用于調(diào)試搀玖,在Eclipse或者Android Studio中直接run以后跑在手機(jī)上的就是使用的debug.keystore。另一種就是用于發(fā)布正式版本的keystore驻呐。

步驟 7.

對(duì)簽名后的APK文件進(jìn)行對(duì)齊處理

如果發(fā)布的apk是正式版的話巷怜,就必須用到的工具zipalign對(duì)APK進(jìn)行對(duì)齊處理葛超。對(duì)齊的主要過(guò)程是將APK包中所有的資源文件距離文件起始偏移為4字節(jié)整數(shù)倍,這樣通過(guò)內(nèi)存映射訪問(wèn)apk文件時(shí)的速度會(huì)更快延塑。對(duì)齊的作用就是減少運(yùn)行時(shí)內(nèi)存的使用绣张。

因此,無(wú)埋點(diǎn)技術(shù)實(shí)現(xiàn)的基本原理关带,就是利用某些技術(shù)對(duì)某些方法(View 被點(diǎn)擊時(shí)的處理邏輯)進(jìn)行代理(或者叫 Hook)侥涵,或者叫在指定的時(shí)機(jī) 插入代碼。

那么宋雏,如何進(jìn)行代理芜飘,又該如何在指定的時(shí)機(jī)進(jìn)行 插入代碼?

按照 “在什么時(shí)候去代理或者插入代碼”這個(gè)條件來(lái)區(qū)分的話磨总,Android無(wú)埋點(diǎn)技術(shù)可以大致分為下面兩種方式 :

靜態(tài)代理

所謂靜態(tài)代理嗦明,就是指通過(guò) Gradle Plugin 在 編譯期間 “插入”或者修改代碼(.class 文 件)。比如 AspectJ蚪燕、 ASM娶牌、javassist、AST 等方案均是這種方式來(lái)實(shí)現(xiàn)在編譯期間“插入”或者修改代碼

動(dòng)態(tài)代理

所謂動(dòng)態(tài)代理馆纳,就是指在 代碼運(yùn)行 的時(shí)候去進(jìn)行代理诗良。比如開(kāi)發(fā)中比較常見(jiàn)的代理 View.OnClickListener、Window.Call-back鲁驶、以及View.AccessibilityDelegate 等方案均是這種方式鉴裹。

總之:不同的方案,其處理和運(yùn)行效率也有很大的差異钥弯,對(duì) App的浸入程度以及對(duì) App 的整體性能的影響也各不相同径荔。而且Android系統(tǒng)的不斷升級(jí),不管是 Android 系統(tǒng)本身脆霎,還是與 Android App 開(kāi)發(fā)相關(guān)的組件和技術(shù)总处,都在與時(shí)俱進(jìn)。因此針對(duì)不同的應(yīng)用場(chǎng)景绪穆,要具體問(wèn)題具體分析。

本篇文章是《Android自動(dòng)化埋點(diǎn)技術(shù)探索》的第一篇虱岂,主要介紹埋點(diǎn)的基本概念與幾種實(shí)現(xiàn)方式差異進(jìn)行對(duì)比玖院,接下來(lái)的文章主要對(duì)自動(dòng)化埋點(diǎn)技術(shù)這一種實(shí)現(xiàn)方式進(jìn)行分析和探索。

文章部分內(nèi)容選自:神策數(shù)據(jù)用戶(hù)行為洞察研究院《安卓全埋點(diǎn)技術(shù)白皮書(shū)》第岖,感謝技術(shù)分享难菌!

如果這篇文章對(duì)您有開(kāi)發(fā)or學(xué)習(xí)上的些許幫助,希望各位看官留下寶貴的star蔑滓,謝謝郊酒。

Ps:著作權(quán)歸作者所有,轉(zhuǎn)載請(qǐng)注明作者, 商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán)遇绞,非商業(yè)轉(zhuǎn)載請(qǐng)注明出處(開(kāi)頭或結(jié)尾請(qǐng)?zhí)砑愚D(zhuǎn)載出處,添加原文url地址),文章請(qǐng)勿濫用,也希望大家尊重筆者的勞動(dòng)成果燎窘!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末摹闽,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子褐健,更是在濱河造成了極大的恐慌付鹿,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,968評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蚜迅,死亡現(xiàn)場(chǎng)離奇詭異舵匾,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)谁不,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)坐梯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人刹帕,你說(shuō)我怎么就攤上這事吵血。” “怎么了轩拨?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,220評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵践瓷,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我亡蓉,道長(zhǎng)晕翠,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,416評(píng)論 1 279
  • 正文 為了忘掉前任砍濒,我火速辦了婚禮淋肾,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘爸邢。我一直安慰自己樊卓,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布杠河。 她就那樣靜靜地躺著碌尔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪券敌。 梳的紋絲不亂的頭發(fā)上唾戚,一...
    開(kāi)封第一講書(shū)人閱讀 49,144評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音待诅,去河邊找鬼叹坦。 笑死,一個(gè)胖子當(dāng)著我的面吹牛卑雁,可吹牛的內(nèi)容都是我干的募书。 我是一名探鬼主播绪囱,決...
    沈念sama閱讀 38,432評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼莹捡!你這毒婦竟也來(lái)了鬼吵?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,088評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤道盏,失蹤者是張志新(化名)和其女友劉穎而柑,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體荷逞,經(jīng)...
    沈念sama閱讀 43,586評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡媒咳,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了种远。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涩澡。...
    茶點(diǎn)故事閱讀 38,137評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖坠敷,靈堂內(nèi)的尸體忽然破棺而出妙同,到底是詐尸還是另有隱情,我是刑警寧澤膝迎,帶...
    沈念sama閱讀 33,783評(píng)論 4 324
  • 正文 年R本政府宣布粥帚,位于F島的核電站,受9級(jí)特大地震影響限次,放射性物質(zhì)發(fā)生泄漏芒涡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評(píng)論 3 307
  • 文/蒙蒙 一卖漫、第九天 我趴在偏房一處隱蔽的房頂上張望费尽。 院中可真熱鬧,春花似錦羊始、人聲如沸旱幼。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,333評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)柏卤。三九已至,卻和暖如春匀油,著一層夾襖步出監(jiān)牢的瞬間缘缚,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,559評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工钧唐, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留忙灼,地道東北人匠襟。 一個(gè)月前我還...
    沈念sama閱讀 45,595評(píng)論 2 355
  • 正文 我出身青樓钝侠,卻偏偏與公主長(zhǎng)得像该园,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帅韧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評(píng)論 2 345

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