集成騰訊瀏覽服務TBS以及遇到的問題

序言

騰訊瀏覽服務功能強大,穩(wěn)定屏富,集成還算是比較簡單的晴竞,比原生的webview強。最主要的是可以瀏覽PDF狠半,Word文檔噩死,方便不少颤难。此篇文章主要不是在講集成,雖然集成的篇幅多些已维,但是我寫的最重要的目的是我在實際使用過程中碰到的問題行嗤,以及解決方案。如果已經(jīng)成功集成的了垛耳,可直接看其他問題栅屏,可能會有你想要的。

TBS文檔接入地址

基本上的話照著這個文檔接入是沒有什么問題的堂鲜,但是打開本地文件的時候栈雳,還是出現(xiàn)了一點小問題,因為文檔里面沒有說明缔莲。

基礎配置

現(xiàn)在的Android開發(fā)都使用Android Studio了哥纫,所以只需要在app的build.gradle里面添加依賴,這份文章的日期是2020/9/30酌予,最新id版本是下面這個

api 'com.tencent.tbs.tbssdk:sdk:43939'

權限配置

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />

混淆配置

-dontwarn dalvik.**
-dontwarn com.tencent.smtt.**

-keep class com.tencent.smtt.** {
    *;
}

-keep class com.tencent.tbs.** {
    *;
}

異常上報配置

為了提高合作方的webview場景穩(wěn)定性磺箕,及時發(fā)現(xiàn)并解決x5相關問題,當客戶端發(fā)生crash等異常情況并上報給服務器時請務必帶上x5內核相關信息抛虫。x5內核異常信息獲取接口為:com.tencent.smtt.sdk.WebView.getCrashExtraMessage(context)松靡。以bugly日志上報為例:

UserStrategy strategy = new UserStrategy(appContext);
  strategy.setCrashHandleCallback(new CrashReport.CrashHandleCallback() {
    public Map<String, String> onCrashHandleStart(
            int crashType, 
            String errorType, 
            String errorMessage, 
            String errorStack) {

            LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
            String x5CrashInfo = com.tencent.smtt.sdk.WebView.getCrashExtraMessage(appContext);
            map.put("x5crashInfo", x5CrashInfo);
            return map;
    }
    @Override
    public byte[] onCrashHandleStart2GetExtraDatas(
            int crashType, 
            String errorType, 
            String errorMessage, 
            String errorStack) {
            try {
                return "Extra data.".getBytes("UTF-8");
            } catch (Exception e) {
                return null;
            }
    }
  });

  CrashReport.initCrashReport(appContext, APPID, true, strategy);

首次初始化冷啟動優(yōu)化

TBS內核首次使用和加載時,ART虛擬機會將Dex文件轉為Oat建椰,該過程由系統(tǒng)底層觸發(fā)且耗時較長雕欺,很容易引起anr問題,解決方法是使用TBS的 ”dex2oat優(yōu)化方案“棉姐。

(1). 設置開啟優(yōu)化方案

// 在調用TBS初始化屠列、創(chuàng)建WebView之前進行如下配置 
HashMap map = new HashMap(); 
map.put(TbsCoreSettings.TBS_SETTINGS_USE_SPEEDY_CLASSLOADER, true); 
map.put(TbsCoreSettings.TBS_SETTINGS_USE_DEXLOADER_SERVICE, true); 
QbSdk.initTbsSettings(map);

(2). 增加Service聲明

  1. 在AndroidManifest.xml中增加內核首次加載時優(yōu)化Service聲明。
  2. 該Service僅在TBS內核首次Dex加載時觸發(fā)并執(zhí)行dex2oat任務伞矩,任務完成后自動結束笛洛。
<service 
android:name="com.tencent.smtt.export.external.DexClassLoaderProviderService"
android:label="dexopt"
android:process=":dexopt" >
</service>

初始化X5內核

 QbSdk.setDownloadWithoutWifi(true);
    QbSdk.setTbsListener(
        new TbsListener() {
          @Override
          public void onDownloadFinish(int i) {
            Log.d("QbSdk", "onDownloadFinish -->下載X5內核完成:" + i);
          }

          @Override
          public void onInstallFinish(int i) {
            Log.d("QbSdk", "onInstallFinish -->安裝X5內核進度:" + i);
          }

          @Override
          public void onDownloadProgress(int i) {
            Log.d("QbSdk", "onDownloadProgress -->下載X5內核進度:" + i);
          }
        });

    QbSdk.PreInitCallback cb =
        new QbSdk.PreInitCallback() {
          @Override
          public void onViewInitFinished(boolean arg0) {
            // x5內核初始化完成的回調,true表x5內核加載成功乃坤,否則表加載失敗苛让,會自動切換到系統(tǒng)內核。
            Log.d("QbSdk", " 內核加載 " + arg0);
          }

          @Override
          public void onCoreInitFinished() {}
        };

    // x5內核初始化接口
    QbSdk.initX5Environment(getApplicationContext(), cb);

WebView接入

這部分其實就是將原生webview的東西全部換成帶有com.tencent.smtt包名的湿诊,TBS文檔上有介紹狱杰,這里就不做說明了。

文件接入

這個應該才是重點厅须。

在APP內部打開文件

APP內部打開使用的是TBS里面的TbsReaderView仿畸,在我Demo中有示例。可以看我的TBSDemo

這里有可能會碰到一個問題就是已經(jīng)在一個頁面使用TbsReaderView打開了文件错沽,但是跳轉到另一個界面的時候簿晓,還是使用TbsReaderView再打開文件,這時候就會顯示一直在加載中甥捺。目前我能想到的方法就是在onResume的時候重新初始化TbsReaderView抢蚀,

mFlRoot.removeAllViews();
    mTbsReaderView = new TbsReaderView( mActivity, readerCallback );
    mTbsReaderView.setBackgroundColor(
        ContextCompat.getColor( mActivity, R.color.color_white ) );
    mFlRoot.addView(
        mTbsReaderView,
        new RelativeLayout.LayoutParams(
            RelativeLayout.LayoutParams.MATCH_PARENT,
            RelativeLayout.LayoutParams.MATCH_PARENT ) );

調用打開文件的代碼

private void openFile() {
    String extensionName = FileUtils.getFileType( mReaderFile.getPath() );
    Bundle bundle = new Bundle();
    bundle.putString( TbsReaderView.KEY_FILE_PATH, mReaderFile.getPath() );
    bundle.putString( TbsReaderView.KEY_TEMP_PATH, FileUtils.createCachePath( mActivity ) );
    boolean result = mTbsReaderView.preOpen( extensionName, false );
    MLog.i( "addTbsReaderView: " + result );
    if ( result ) {
      mTbsReaderView.openFile( bundle );
    }
  }

在onPause的時候再調用。

if ( mTbsReaderView != null ) {
      mTbsReaderView.onStop();
    }

使用TBS的openFileReader打開文件

支持格式

TBS已提供9種主流文件格式的本地打開镰禾,如果您需要使用更高級的能力請使用QQ瀏覽器打開文件

  • 接入TBS可支持打開文件格式:doc皿曲、docx、ppt吴侦、pptx屋休、xls、xlsx备韧、pdf劫樟、txt、epub
  • 調用QQ瀏覽器可打開:rar(包含加密格式)织堂、zip(包含加密格式)叠艳、tar、bz2易阳、gz附较、7z(包含加密格式)、doc潦俺、docx拒课、ppt、pptx事示、xls早像、xlsx、txt肖爵、pdf卢鹦、epub、chm劝堪、html/htm法挨、xml、mht幅聘、url、ini窃植、log帝蒿、bat、php巷怜、js葛超、lrc暴氏、jpg、jpeg绣张、png答渔、gif、bmp侥涵、tiff 沼撕、webp、mp3芜飘、m4a务豺、aac、amr嗦明、wav笼沥、ogg、mid娶牌、ra奔浅、wma、mpga诗良、ape汹桦、flac
接口介紹
public static int openFileReader(
    Context context, 
    String filePath, 
    HashMap<String, String> extraParams,
    ValueCallback<String> callback
)

(1)此方法在Qbsdk類下

(2)調用之后,優(yōu)先調起 QQ 瀏覽器打開文件累榜。如果沒有安裝 QQ 瀏覽器营勤,在 X5 內核下調起簡版 QB 打開文 件。如果使用的系統(tǒng)內核壹罚,則調起文件閱讀器彈框葛作。

(3)暫時只支持本地文件打開

context: 調起 miniqbActivitycontext。此參數(shù)只能是 activity 類型的 context猖凛,不能設置為 Application 的 context赂蠢。 filePath: 文件路徑。格式為 android 本地存儲路徑格式辨泳,例如:/sdcard/Download/xxx.doc. 不支持 file:/// 格式虱岂。暫不支持在線文件。 extraParams: miniqb 的擴展功能菠红。為非必填項第岖,若無需特殊配置,默認可傳入null试溯。擴展功能參考“文件功能定制” ValueCallback: 提供 miniqb 打開/關閉時給調用方回調通知,以便應用層做相應處理蔑滓,您可以在出現(xiàn)以下回調時結束您的進程,節(jié)約內存占用。主要回調值如下:

filepath error
TbsReaderDialogClosed 
default browser
fileReaderClosed

返回值:

1:用 QQ 瀏覽器打開
2:用 MiniQB 打開
3:調起閱讀器彈框
-1:filePath 為空 打開失敗 
public static void closeFileReader(Context context)

主動關閉文件打開ui,并清理相應內存占用键袱。

接入示例
HashMap<String, String> params = new HashMap<String, String>(); 
params.put("style", "1"); 
params.put("local", "true"); 
params.put("memuData", jsondata); 
QbSdk.openFileReader(ctx,”/sdcard/xxx.doc”, params,callback);

到這你以為就能順利打開瀏覽文件了嗎燎窘?還是太年輕了,騰訊的文檔不給你挖點坑蹄咖,讓你養(yǎng)成自己解決bug的習慣是不會罷休的褐健。當你滿心歡喜調用QbSdk.openFileReade的時候,log會給你報一個錯澜汤。

QbSdk: Must declare com.tencent.smtt.utils.FileProvider in AndroidManifest above Android 7.0,please view document in x5.tencent.com

意思就是讓你在AndroidManifest.xml中添加provider蚜迅,因為Android版本7.0訪問文件的方式改變了。這時候添加一下就可以了银亲。

首先在AndroidManifest.xml添加以下代碼

    <provider
      android:name="com.tencent.smtt.utils.FileProvider"
      android:authorities="${applicationId}.provider"
      android:exported="false"
      android:grantUriPermissions="true">
      <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/x5webview_file_paths" />
    </provider>

然后在res文件夾下創(chuàng)建xml文件夾慢叨,如果有了則跳過,接著再創(chuàng)建一個x5webview_file_paths.xml的文件务蝠,內容如下

<?xml version="1.0" encoding="utf-8"?>
<paths>
    <external-path name="sdcard" path="."/>
</paths>

再運行拍谐,應該是沒有問題的了,這里需要保證的是文件的路徑是要對的馏段,因為不能在線瀏覽轩拨,只能把文件下載到本地才能調用。這個錯誤我看了很久的文檔都沒有找到院喜,后面在網(wǎng)上搜索亡蓉,給出了以下的代碼,

<provider
    android:name="com.tencent.smtt.utils.FileProvider"
    android:authorities="包名.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/xml文件名" />
</provider>

這錯就錯在android:authorities="包名.fileprovider"喷舀,因為后來我去調用服務開啟的QbSdk的類中砍濒,看這個錯誤發(fā)生的時機,發(fā)現(xiàn)他們是通過類型+“.provider”來校驗的硫麻,所以只要改成android:authorities="包名.provider"就可以了爸邢,這個錯誤調試了很久,還是得在源碼中才能發(fā)現(xiàn)春天拿愧。

其他問題

使用TbsReaderView瀏覽文件夜間模式問題

我在使用小米10至尊版的時候杠河,我的APP中沒有適配深黑模式,使用的主題是Theme.AppCompat.Light.NoActionBar浇辜,但是小米10還是強制性的把我的APP使用了深黑模式券敌。并且我發(fā)現(xiàn),不止是我的APP柳洋,而是我手機上所有的APP都是如此待诅,不管有沒有適配,都使用了深黑模式熊镣,也就是夜間模式咱士。這就導致了一個問題立由,使用TbsReaderView來瀏覽文件的時候,背景是黑色的序厉,字體的顏色也是有點黑,導致文檔看的不清楚毕箍,后來我在閱讀TbsReaderView源碼的時候弛房,發(fā)現(xiàn)可以設置強制不使用夜間模式。加入以下代碼即可而柑。

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
      //不使用黑暗模式
      mTbsReaderView.setForceDarkAllowed(false);
    }

targetAPI為29時

如果Android的targetSdkVersion是29的話文捶,需要在application下面配置android:requestLegacyExternalStorage="true"

targetAPI為Android P時無法下載內核?

由于內核下載安裝和查詢是否可用需要向后臺發(fā)送請求媒咳,目前還有部分請求為http格式粹排,當targetAPI為28時非Https請求將會被block,會導致部分內核功能異常涩澡。您可以手動降低targetAPi到27及以下或者在您的AndroidManifst.xml中的Application標簽中添加

android:networkSecurityConfig="@xml/network_security_config"

并在app的res/xml目錄中添加network_security_config.xml文件顽耳,文件內容為

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true" />
</network-security-config>

由于內核初始化需要時間,在這段時間里需要等待一會再打開文件瀏覽妙同,否則會加載失敗射富。假如出現(xiàn)加載失敗,卸載重新安裝粥帚。

無法下載胰耗,或者加載不成功

    QbSdk.setTbsListener(
        new TbsListener() {
          @Override
          public void onDownloadFinish(int i) {
            //下載結束時的狀態(tài),下載成功時errorCode為100,其他均為失敗芒涡,外部不需要關注具體的失敗原因
            Log.d("QbSdk", "onDownloadFinish -->下載X5內核完成:" + i);
          }

          @Override
          public void onInstallFinish(int i) {
            //安裝結束時的狀態(tài)柴灯,安裝成功時errorCode為200,其他均為失敗,外部不需要關注具體的失敗原因
            Log.d("QbSdk", "onInstallFinish -->安裝X5內核進度:" + i);
          }

          @Override
          public void onDownloadProgress(int i) {
            //下載過程的通知费尽,提供當前下載進度[0-100]
            Log.d("QbSdk", "onDownloadProgress -->下載X5內核進度:" + i);
          }
        });

上面是下載的監(jiān)聽赠群,但是在實際中我經(jīng)常發(fā)現(xiàn)onDownloadFinish返回是110,或者120等依啰。官網(wǎng)上注明只有100是成功乎串。只要不是100,則X5內核加載肯定是失敗的速警。但是官網(wǎng)又沒有說如何解決叹誉。沒辦法只能自己找出路。在十分艱難閱讀了大部分帶有混淆的TBS的jar包后闷旧,連猜帶蒙的我找到了TbsDownloader.startDownload(this);這個方法长豁。可以實現(xiàn)重新下載忙灼,但是如果只是重新下載了還是不一定能保證x5的加載是一定成功的匠襟。所以我又找到了QbSdk.reset(this);這個方法钝侠。可以重置x5的配置酸舍。kill掉APP后就會重新下載跟初始化帅韧。在實際線上的使用情況是十分復雜的,有的人還沒等下載結束就把APPkill掉了啃勉,導致下載沒完成忽舟,或者是下載完成加載沒完成,所以只是使用TbsDownloader.startDownload(this);重新下載的話要結合QbSdk.setTbsListener里的回調淮阐,還有QbSdk.PreInitCallback的回調來綜合判斷叮阅。

    QbSdk.PreInitCallback cb =
        new QbSdk.PreInitCallback() {
          @Override
          public void onViewInitFinished(boolean arg0) {
            // x5內核初始化完成的回調,true表x5內核加載成功泣特,否則表加載失敗浩姥,會自動切換到系統(tǒng)內核。
            Log.d("QbSdk", " 內核加載 " + arg0);
          }

          @Override
          public void onCoreInitFinished() {
            //內核初始化完畢
            Log.d("QbSdk", "內核初始化完畢");
          }
        };

QbSdk.reset(this);是最好的方法状您,簡單粗暴勒叠。可以查看我的demo竞阐,里面有我認為比較好的解決方法缴饭。當然還是得根據(jù)自身的需求要使用。

混淆無法使用

如果使用了混淆骆莹,則要加入以下混淆的規(guī)則

#-optimizationpasses 7
#-optimizations !code/simplification/arithmetic,!field/*,!class/merging/*
-dontoptimize
-dontusemixedcaseclassnames
-verbose
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers 
-dontwarn dalvik.**
-dontwarn com.tencent.smtt.**
#-overloadaggressively

# ------------------ Keep LineNumbers and properties ---------------- #
-keepattributes Exceptions,InnerClasses,Signature,Deprecated,SourceFile,LineNumberTable,*Annotation*,EnclosingMethod
# --------------------------------------------------------------------------

# Addidional for x5.sdk classes for apps

-keep class com.tencent.smtt.export.external.**{
    *;
}

-keep class com.tencent.tbs.video.interfaces.IUserStateChangedListener {
    *;
}

-keep class com.tencent.smtt.sdk.CacheManager {
    public *;
}

-keep class com.tencent.smtt.sdk.CookieManager {
    public *;
}

-keep class com.tencent.smtt.sdk.WebHistoryItem {
    public *;
}

-keep class com.tencent.smtt.sdk.WebViewDatabase {
    public *;
}

-keep class com.tencent.smtt.sdk.WebBackForwardList {
    public *;
}

-keep public class com.tencent.smtt.sdk.WebView {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebView$HitTestResult {
    public static final <fields>;
    public java.lang.String getExtra();
    public int getType();
}

-keep public class com.tencent.smtt.sdk.WebView$WebViewTransport {
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebView$PictureListener {
    public <fields>;
    public <methods>;
}


-keepattributes InnerClasses

-keep public enum com.tencent.smtt.sdk.WebSettings$** {
    *;
}

-keep public enum com.tencent.smtt.sdk.QbSdk$** {
    *;
}

-keep public class com.tencent.smtt.sdk.WebSettings {
    public *;
}


-keepattributes Signature
-keep public class com.tencent.smtt.sdk.ValueCallback {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebViewClient {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.DownloadListener {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebChromeClient {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebChromeClient$FileChooserParams {
    public <fields>;
    public <methods>;
}

-keep class com.tencent.smtt.sdk.SystemWebChromeClient{
    public *;
}
# 1. extension interfaces should be apparent
-keep public class com.tencent.smtt.export.external.extension.interfaces.* {
    public protected *;
}

# 2. interfaces should be apparent
-keep public class com.tencent.smtt.export.external.interfaces.* {
    public protected *;
}

-keep public class com.tencent.smtt.sdk.WebViewCallbackClient {
    public protected *;
}

-keep public class com.tencent.smtt.sdk.WebStorage$QuotaUpdater {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebIconDatabase {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.WebStorage {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.DownloadListener {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.QbSdk {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.QbSdk$PreInitCallback {
    public <fields>;
    public <methods>;
}
-keep public class com.tencent.smtt.sdk.CookieSyncManager {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.Tbs* {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.utils.LogFileUtils {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.utils.TbsLog {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.utils.TbsLogClient {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.CookieSyncManager {
    public <fields>;
    public <methods>;
}

# Added for game demos
-keep public class com.tencent.smtt.sdk.TBSGamePlayer {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.TBSGamePlayerClient* {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.TBSGamePlayerClientExtension {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.sdk.TBSGamePlayerService* {
    public <fields>;
    public <methods>;
}

-keep public class com.tencent.smtt.utils.Apn {
    public <fields>;
    public <methods>;
}
-keep class com.tencent.smtt.** {
    *;
}
# end


-keep public class com.tencent.smtt.export.external.extension.proxy.ProxyWebViewClientExtension {
    public <fields>;
    public <methods>;
}

-keep class MTT.ThirdAppInfoNew {
    *;
}

-keep class com.tencent.mtt.MttTraceEvent {
    *;
}

# Game related
-keep public class com.tencent.smtt.gamesdk.* {
    public protected *;
}

-keep public class com.tencent.smtt.sdk.TBSGameBooter {
        public <fields>;
        public <methods>;
}

-keep public class com.tencent.smtt.sdk.TBSGameBaseActivity {
    public protected *;
}

-keep public class com.tencent.smtt.sdk.TBSGameBaseActivityProxy {
    public protected *;
}

-keep public class com.tencent.smtt.gamesdk.internal.TBSGameServiceClient {
    public *;
}
#---------------------------------------------------------------------------


#------------------  下方是android平臺自帶的排除項颗搂,這里不要動         ----------------

-keep public class * extends android.app.Activity{
    public <fields>;
    public <methods>;
}
-keep public class * extends android.app.Application
{
    public <fields>;
    public <methods>;
}
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference

-keepclassmembers enum * {
    public static **[] values();
    public static ** valueOf(java.lang.String);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet);
}

-keepclasseswithmembers class * {
    public <init>(android.content.Context, android.util.AttributeSet, int);
}

-keepattributes *Annotation*

-keepclasseswithmembernames class *{
    native <methods>;
}

-keep class * implements android.os.Parcelable {
  public static final android.os.Parcelable$Creator *;
}

#------------------  下方是共性的排除項目         ----------------
# 方法名中含有“JNI”字符的,認定是Java Native Interface方法幕垦,自動排除
# 方法名中含有“JRI”字符的丢氢,認定是Java Reflection Interface方法,自動排除

-keepclasseswithmembers class * {
    ... *JNI*(...);
}

-keepclasseswithmembernames class * {
    ... *JRI*(...);
}

-keep class **JNI* {*;}


集成Demo地址

歡迎訂閱我的博客先改,堅持總是會看到希望的疚察。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市仇奶,隨后出現(xiàn)的幾起案子貌嫡,更是在濱河造成了極大的恐慌,老刑警劉巖该溯,帶你破解...
    沈念sama閱讀 217,406評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岛抄,死亡現(xiàn)場離奇詭異,居然都是意外死亡狈茉,警方通過查閱死者的電腦和手機夫椭,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評論 3 393
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來氯庆,“玉大人蹭秋,你說我怎么就攤上這事扰付。” “怎么了仁讨?”我有些...
    開封第一講書人閱讀 163,711評論 0 353
  • 文/不壞的土叔 我叫張陵羽莺,是天一觀的道長。 經(jīng)常有香客問我洞豁,道長禽翼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,380評論 1 293
  • 正文 為了忘掉前任族跛,我火速辦了婚禮,結果婚禮上锐墙,老公的妹妹穿的比我還像新娘礁哄。我一直安慰自己,他們只是感情好溪北,可當我...
    茶點故事閱讀 67,432評論 6 392
  • 文/花漫 我一把揭開白布桐绒。 她就那樣靜靜地躺著,像睡著了一般之拨。 火紅的嫁衣襯著肌膚如雪茉继。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評論 1 301
  • 那天蚀乔,我揣著相機與錄音烁竭,去河邊找鬼。 笑死吉挣,一個胖子當著我的面吹牛派撕,可吹牛的內容都是我干的。 我是一名探鬼主播睬魂,決...
    沈念sama閱讀 40,145評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼终吼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了氯哮?” 一聲冷哼從身側響起际跪,我...
    開封第一講書人閱讀 39,008評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎喉钢,沒想到半個月后姆打,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡出牧,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,649評論 3 334
  • 正文 我和宋清朗相戀三年穴肘,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片舔痕。...
    茶點故事閱讀 39,795評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡评抚,死狀恐怖豹缀,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情慨代,我是刑警寧澤邢笙,帶...
    沈念sama閱讀 35,501評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站侍匙,受9級特大地震影響氮惯,放射性物質發(fā)生泄漏。R本人自食惡果不足惜想暗,卻給世界環(huán)境...
    茶點故事閱讀 41,119評論 3 328
  • 文/蒙蒙 一妇汗、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧说莫,春花似錦杨箭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至辽狈,卻和暖如春慈参,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背刮萌。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評論 1 269
  • 我被黑心中介騙來泰國打工驮配, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人尊勿。 一個月前我還...
    沈念sama閱讀 47,899評論 2 370
  • 正文 我出身青樓僧凤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親元扔。 傳聞我的和親對象是個殘疾皇子躯保,可洞房花燭夜當晚...
    茶點故事閱讀 44,724評論 2 354