Android Studio 2.3.3 圖解配置NDK開發(fā)環(huán)境以及Hello Word To jni~

LZ-Says:半夜睡覺滾了地上了徘六,無奈之下醒來了针炉,想想最近幾天因為一個括號導致JNI遲遲不能開展男摧,心里面無奈又崩潰洛搀,索性直接起來整完得了~

前言

當前畢業(yè)的時候敢茁,感覺自己掌握了全世界,隨著參加工作的時間一天天的增長留美,突然覺得丫的彰檬,啥都不會啊,要學的東西還是太多太多了谎砾。不過近來被飛大姐洗腦成功逢倍,<font color=#FF0000>萬事不過幾行代碼而已,干它~

So 今天為大家?guī)砗唵蔚膉ni配置景图,使用较雕,以及運行我們的第一個簡單小demo`

Hi Jni

總是再說jni,jni挚币,那么jni到底是什么東西亮蒋,我們一起來看看:

JNI是Java Native Interface的縮寫,它提供了若干的API實現(xiàn)了Java和其他語言的通信(主要是C&C++)妆毕。從Java1.1開始慎玖,JNI標準成為java平臺的一部分,它允許Java代碼和其他語言寫的代碼進行交互笛粘。

JNI標準至少要保證本地代碼能工作在任何Java 虛擬機環(huán)境趁怔。

下面為大家附上官方Android平臺架構圖:

<center>
這里寫圖片描述
這里寫圖片描述

可以看到Android上層的Application和ApplicationFramework都是使用Java編寫远舅,底層包括系統(tǒng)和使用眾多的Libraries都是C/C++編寫的,所以上層Java要調用底層的C/C++函數(shù)庫必須通過Java的JNI來實現(xiàn)痕钢。

Jni使用場景

當你開始著手準備一個使用JNI的項目時图柏,請確認是否還有替代方案。應用程序使用JNI會帶來一些副作用任连。下面給出幾個方案蚤吹,可以避免使用JNI的時候,達到與本地代碼進行交互的效果:

1随抠、JAVA程序和本地程序使用TCP/IP或者IPC進行交互裁着。
2、當用JAVA程序連接本地數(shù)據(jù)庫時拱她,使用JDBC提供的API二驰。
3、JAVA程序可以使用分布式對象技術秉沼,如JAVA IDL API桶雀。

這些方案的共同點是,JAVA和C處于不同的線程唬复,或者不同的機器上矗积。這樣,當本地程序崩潰時敞咧,不會影響到JAVA程序棘捣。

下面這些場合中,同一進程內JNI的使用無法避免:

1休建、程序當中用到了JAVA API不提供的特殊系統(tǒng)環(huán)境才會有的特征乍恐。而跨進程操作又不現(xiàn)實。
2测砂、你可能想訪問一些己有的本地庫茵烈,但又不想付出跨進程調用時的代價,如效率邑彪,內存瞧毙,數(shù)據(jù)傳遞方面胧华。
3寄症、JAVA程序當中的一部分代碼對效率要求非常高桐猬,如算法計算臼闻,圖形渲染等。

<font color=#FF0000>總之芬膝,只有當你必須在同一進程中調用本地代碼時悲没,再使用JNI篮迎。

Jni缺陷

一旦使用JNI,JAVA程序就喪失了JAVA平臺的兩個優(yōu)點:

1、程序不再跨平臺甜橱。要想跨平臺逊笆,必須在不同的系統(tǒng)環(huán)境下重新編譯本地語言部分。
2岂傲、程序不再是絕對安全的难裆,本地代碼的不當使用可能導致整個程序崩潰。一個通用規(guī)則是镊掖,你應該讓本地方法集中在少數(shù)幾個類當中乃戈。這樣就降低了JAVA和C之間的耦合性

Jni作用

JNI可以這樣與本地程序進行交互:

1、你可以使用JNI來實現(xiàn)“本地方法”(native methods)亩进,并在JAVA程序中調用它們症虑。

2、JNI支持一個“調用接口”(invocation interface)归薛,它允許你把一個JVM嵌入到本地程序中谍憔。本地程序可以鏈接一個實現(xiàn)了JVM的本地庫,然后使用“調用接口”執(zhí)行JAVA語言編寫的軟件模塊主籍。

簡單了解以上內容后韵卤,我們開啟正題,在Android開發(fā)中崇猫,我們該怎么使用jni沈条,或者說是在Android Studio中,我們該怎么使用jni呢诅炉?表急蜡歹,往下瞅瞅~

話說,我們開發(fā)android應用程序基礎不就是下載官方相關的SDK涕烧,ADT啥啥啥的月而,同理jni也一樣。

現(xiàn)在為大家簡單介紹NDK~如下议纯。

Hi NDK

Android NDK 是一套允許使用原生代碼語言(例如 C 和 C++)實現(xiàn)部分應用的工具集父款。在開發(fā)某些類型應用時,這有助于重復使用以這些語言編寫的代碼庫瞻凤。

同理憨攒,官方也為我們提供了一個小例子,簡單走馬觀花看一下:

public class MyActivity extends Activity {
  /**
  * 使用 C/C++ 語言實現(xiàn)的原生方法
  */
  public native void computeFoo();
}

native方法阀参,當年看到這個東西感覺好高大上肝集,沒想到而今我也能玩玩,哈哈蛛壳,GGG~

官方對于NDK是這樣說的:

NDK 不適用于大多數(shù)初學的 Android 編程者杏瞻,對許多類型的 Android 應用沒什么價值所刀。 因為它不可避免地會增加開發(fā)過程的復雜性,所以通常不值得使用捞挥。 但如果您需要執(zhí)行以下操作浮创,它可能很有用:

  • 從設備獲取卓越性能以用于計算密集型應用,例如游戲或物理模擬砌函;

  • 重復使用您自己或其他開發(fā)者的 C 或 C++ 庫蒸矛。

丫的,爺兒們好奇瞅瞅不行靶刈臁雏掠?

行~!

哈哈~

簡單有個印象后劣像,我們開始配置相關內容乡话,為什么要說這個配置呢,主要有以下幾個原因:

  • 雖說配置是傻瓜式無腦操作耳奕,但是對于LZ小白這樣的人來說绑青,依然覺得是一件很高大上的事兒,何況屋群,丫的闸婴,連配置都不會,還開發(fā)個卵子芍躏?

  • 凡事兒親歷親為邪乍,不經(jīng)歷,怎能有成長对竣?

配置之前庇楞,我們還需要了解我們需要配置or下載哪兒些工具,以及這些東西都是干嘛的否纬,不然稀里糊涂的吕晌,糟心。

同理临燃,我們也需要去簡單了解下使用NDK好處:

1睛驳、代碼的保護。由于apk的java層代碼很容易被反編譯膜廊,而C/C++庫反匯難度較大乏沸;
2、可以方便地使用現(xiàn)存的開源庫溃论。大部分現(xiàn)存的開源庫都是用C/C++代碼編寫的屎蜓;
3痘昌、提高程序的執(zhí)行效率钥勋。將要求高性能的應用邏輯使用C開發(fā)炬转,從而提高應用程序的執(zhí)行效率;
4算灸、便于移植扼劈。用C/C++寫得庫可以方便在其他的嵌入式平臺上再次使用。

NDK以及所需構建工具簡介

  • NDK:這個還需要再說嘛菲驴?

  • CMake:外部構建工具荐吵;

CMake是一個開源的跨平臺系列工具,旨在構建赊瞬,測試和打包軟件先煎。

CMake用于使用簡單的平臺和編譯器獨立的配置文件來控制軟件編譯過程,并生成可以在選擇的編譯環(huán)境中使用的本地makefile和工作空間巧涧。

CMack工具套件由Kitware創(chuàng)建薯蝎,以響應對開源項目(如ITK和VTK)的強大的跨平臺構建環(huán)境的需求。

官方地址:https://cmake.org/ 有興趣可以簡單了解下~

  • LLDB:Android Studio 上面調試本地代碼的工具

LLDB是下一代高性能調試器谤绳。它被構建為一組可重用的組件占锯,可以高度利用較大的LLVM項目中的現(xiàn)有庫,例如Clang表達式解析器和LLVM反匯編程序缩筛。

在Mac OS X中消略,LLDB是Xcode中的默認調試器,支持在桌面和iOS設備和模擬器上調試C瞎抛,Objective-C和C ++艺演。

LLDB項目中的所有代碼都可以使用標準的 LLVM許可證(一種開放源代碼“BSD風格”)許可證。

LLDB目前將調試信息轉換成clang類型桐臊,以便它可以利用clang編譯器基礎架構钞艇。這允許LLDB在表達式中支持最新的C,C++豪硅,Objective C和Objective C ++語言特性和運行時間哩照,而無需重新實現(xiàn)任何此功能。在編寫表達式的函數(shù)懒浮,拆卸指令和提取指令詳細信息等時飘弧,還可以利用編譯器來處理所有ABI細節(jié)。

主要優(yōu)點包括:

  1. C砚著,C ++次伶,Objective C的最新語言支持 ;
  2. 可以聲明局部變量和類型的多行表達式稽穆;
  3. 支持時使用JIT表達式冠王;
  4. 當JIT不能使用時,評估表達式中間表示(IR)

官方地址:http://lldb.llvm.org/

以上簡單了解下就好了舌镶,至于為啥要這么搞柱彻,就是為了方便以后有需要直接翻出來看看~

NDK配置(包含構建工具豪娜,調試工具)

<font color=#FF0000>下載安裝NDK,有倆種方式哟楷,其實都一樣瘤载,只是一個需要手動下載,解壓卖擅,配置目錄鸣奔,一個Android Studio自動完成以上操作。

配置NDK倆種方式

手動下載NDK

NDK下載地址如下:

https://developer.android.google.cn/ndk/downloads/index.html

大家可自行選擇相應版本進行下載惩阶。

下載完成后挎狸,解壓本地目錄,在Android Studio中配置路徑即可断楷,如下圖所示:

<center>
這里寫圖片描述
這里寫圖片描述

強大的Android Studio走起~

1.點擊Project Structure伟叛,選擇 Download Android NDK;

<center>
這里寫圖片描述
這里寫圖片描述

2.耐心等待吧脐嫂,LZ下載比較快统刮,解壓比較慢~

<center>
這里寫圖片描述
這里寫圖片描述

3.下載解壓完成,自動錄入地址账千,省事兒哈~

<center>
這里寫圖片描述
這里寫圖片描述

到此侥蒙,關于NDK下載安裝倆種方式圖解完畢~

我們看一下ndk目錄各個作用,簡單了解下匀奏。

  • docs: 幫助文檔
  •       build/tools:linux的批處理文件
    
  •       platforms:編譯c代碼需要使用的頭文件和類庫
    
  •       prebuilt:預編譯使用的二進制可執(zhí)行文件
    
  •      sample:jni的使用例子
    
  •      source:ndk的源碼
    
  •      toolchains:工具鏈
    
  •     ndk-build.cmd:編譯打包c代碼的一個指令鞭衩,需要配置系統(tǒng)環(huán)境變量
    

配置構建工具以及調試工具

1.如下圖所示,點擊SDK Manager娃善,選擇下載安裝CMake以及LLDB论衍;

<center>
這里寫圖片描述
這里寫圖片描述

簡單看一下版本信息,果斷OK~

<center>
這里寫圖片描述
這里寫圖片描述

沒啥可說的聚磺,等待坯台,不過分分鐘搞定~

<center>
這里寫圖片描述
這里寫圖片描述

到此,基本配置已完成瘫寝,但是如何查驗NDK是否成功安裝了呢蜒蕾?

配置下環(huán)境變量瞅瞅唄~

配置環(huán)境變量

復制NDK地址,按如下圖示進行操作即可焕阿。

<center>
這里寫圖片描述
這里寫圖片描述

<center>
這里寫圖片描述
這里寫圖片描述

cmd直接輸入ndk-build回車

<center>
這里寫圖片描述
這里寫圖片描述

在這里吐槽下LZ之前遇到的坑咪啡。

LZ目錄習慣命名為HLQWorkSofe(Android) or HLQWorkSofe(Java),在之前從來沒有出現(xiàn)過問題暮屡,但是在NDK時候撤摸,卻怎么也不行,最后無奈下只能把()去掉。

問題截圖如下:

<center>
這里寫圖片描述
這里寫圖片描述

<center>
這里寫圖片描述
這里寫圖片描述

<font color=#FF0000>搞得LZ都快放棄了准夷,最后一試钥飞,好了,給我郁悶的冕象,大家注意啊~

創(chuàng)建個項目玩一玩

創(chuàng)建項目時代承,記得勾選下面的Include C++ support哦~

導入C++支持庫汁蝶,不然沒法玩哈~
<center>

這里寫圖片描述
這里寫圖片描述

一路next下之后渐扮,關于最后一步選擇時,在此作特殊說明下掖棉。

<center>
這里寫圖片描述
這里寫圖片描述
  • C++ Standard:使用下拉列表選擇您希望使用哪種 C++ 標準墓律。選擇 Toolchain Default 會使用默認的 CMake 設置;

  • Exceptions Support:如果您希望啟用對 C++ 異常處理的支持幔亥,請選中此復選框耻讽。如果啟用此復選框,Android Studio 會將 -fexceptions 標志添加到模塊級 build.gradle 文件的 cppFlags 中帕棉,Gradle 會將其傳遞到 CMake针肥;

  • Runtime Type Information Support:如果您希望支持 RTTI,請選中此復選框香伴。如果啟用此復選框慰枕,Android Studio 會將 -frtti 標志添加到模塊級 build.gradle 文件的 cppFlags 中,Gradle 會將其傳遞到 CMake即纲。

點擊Finish之后具帮,我們稍等片刻~

查看默認生成例子

<center>
這里寫圖片描述
這里寫圖片描述

下面我們一起來探究下官方提供的例子,看看從例子中我們能得知什么對我們有用的信息低斋。

從上圖可看到蜂厅,和以前唯一不同的就是多出了cpp目錄以及External Build Files倆個目錄,那么這倆個都有什么用呢膊畴?一起來看看掘猿。

  • cpp 目錄存放所有 native code 的地方,包括源碼唇跨,頭文件术奖,預編譯項目等。對于新項目轻绞,Android Studio 創(chuàng)建了一個 C++ 模板文件:native-lib.cpp采记,并且將該文件放到了你的 app 模塊的 src/main/cpp/ 目錄下。這份模板代碼提供了一個簡答的 C++ 函數(shù):stringFromJNI()政勃,該函數(shù)返回一個字符串:”Hello from C++”

  • External Build Files 目錄是存放 CMake 或 ndk-build 構建腳本的地方唧龄。有點類似于 build.gradle 文件告訴 Gradle 如何編譯你的 APP 一樣,CMake 和 ndk-build 也需要一個腳本來告知如何編譯你的 native library奸远。對于一個新的項目既棺,Android Studio 創(chuàng)建了一個 CMake 腳本:CMakeLists.txt讽挟,并且將其放到了你的 module 的根目錄下

首先還是來看看代碼吧,比較直觀也比較好理解丸冕。

1.查看activity代碼

package cn.hlq.hlqjnipro;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();
}

首先static靜態(tài)塊去加載so庫耽梅,本地編寫native方法,調用方法輸出內容胖烛。

2.查看native-lib.cpp代碼

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_cn_hlq_hlqjnipro_MainActivity_stringFromJNI(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

簡單可以看到眼姐,首先定義hello變量,之后return佩番。

3.查看CMakeLists.txt

簡單的翻譯了下众旗,如有不正之處歡迎指出`

# 使用Android Studio使用CMake的更多信息,閱讀文檔:https://d.android.com/studio/projects/add-native-code.html

# 設置CMake的最低版本構建本機所需庫
cmake_minimum_required(VERSION 3.4.1)

# 創(chuàng)建和名稱庫,使它是靜態(tài)的或共享,并提供了相對路徑的源代碼
# 可以定義多個圖書館,CMake將為你構建這些內容
# Gradle自動與你的APK包共享庫

add_library( # 設置庫名稱
             native-lib

             # 集庫作為一個共享庫
             SHARED

             # 提供了一個相對路徑你的源文件
             src/main/cpp/native-lib.cpp )

# 搜索指定預先構建的庫和存儲路徑變量。因為CMake包括系統(tǒng)庫搜索路徑中默認情況下,只需要指定想添加公共NDK庫的名稱趟畏,在CMake驗證庫之前存在完成構建

find_library( # 設置path變量的名稱
              log-lib

              # 在CMake定位前指定的NDK庫名稱
              log )

# 指定庫CMake應該鏈接到目標庫中贡歧,可以鏈接多個庫,比如定義庫赋秀,構建腳本利朵,預先構建的第三方庫或者系統(tǒng)庫

target_link_libraries( # 指定目標庫
                       native-lib

                       # 目標庫到日志庫的鏈接 包含在NDK
                       ${log-lib} )

一開始還覺的差不多點呢,結果看到這里越來越蒙圈猎莲,還是先運行一下绍弟,看看結果吧。

按照剛才的簡單分析益眉,這個demo輸出的結果應該為:Hello from C++ 晌柬。一起來驗證一下唄~

<center>
這里寫圖片描述
這里寫圖片描述

嗯,確實郭脂,輸出了年碘,有些似懂非懂的,繼續(xù)研究~

經(jīng)過查詢展鸡,發(fā)現(xiàn)一個之前從未關注的內容屿衅,那就是從編譯到運行示例 APP 的流程到底是怎樣呢,如下:

  1. Gradle 調用外部構建腳本莹弊,也就是 CMakeLists.txt涤久;
  2. CMake 會根據(jù)構建腳本的指令去編譯一個 C++ 源文件,也就是 native-lib.cpp忍弛,并將編譯后的產(chǎn)物扔進共享對象庫中响迂,并將其命名為 libnative-lib.so,然后 Gradle 將其打包到 APK 中细疚;
  3. 在運行期間蔗彤,APP 的 MainActivity 會調用 System.loadLibrary() 方法,加載 native library。而這個庫的原生函數(shù)然遏,stringFromJNI()贫途,就可以為 APP 所用了;
  4. MainActivity.onCreate() 方法會調用 stringFromJNI()待侵,然后返回 “Hello from C++”丢早,并更新 TextView 的顯示;

注意:Instant Run 并不兼容使用了 native code 的項目秧倾。Android Studio 會自動禁止 Instant Run 功能怨酝。

如果你想驗證一下 Gradle 是否將 native library 打包進了 APK,你可以使用 APK Analyzer:

  • 選擇 Build > Analyze APK中狂。

  • 從 app/build/outputs/apk/ 路徑中選擇 APK凫碌,并點擊 OK扑毡。

  • 如下圖胃榕,在 APK Analyzer 窗口中,選擇 lib/<ABI>/瞄摊,你就可以看見 libnative-lib.so

<center>
這里寫圖片描述
這里寫圖片描述

轉自:http://blog.csdn.net/wl9739/article/details/52607010

仿造demo來一下勋又,首先布局中新增一個TextView,activity中編寫一個native方法换帜,調用native方法并輸出結果楔壤,如下:

        TextView tv1 = (TextView) findViewById(R.id.sample_text_1);
        tv1.setText(hlqFromJNI());
    public native String hlqFromJNI();

在cpp中這么玩下:

#include <jni.h>
#include <string>

extern "C" {
JNIEXPORT jstring JNICALL
Java_cn_hlq_hlqjnipro_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

JNIEXPORT jstring JNICALL
Java_cn_hlq_hlqjnipro_MainActivity_hlqFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "真惡心啊 Fuck";
    return env->NewStringUTF(hello.c_str());
}

}

大家有沒有注意到Java_cn_hlq_hlqjnipro_MainActivity_hlqFromJNI這個名稱,方法名必須為Java_包名全路徑_方法名

運行結果如下:

<center>
這里寫圖片描述
這里寫圖片描述

一般情況下惯驼,Gradle 會將你的本地庫構建成 .so 文件蹲嚣,然后將其打包到你的 APK 中。如果你想 Gradle 構建并打包某個特定的 ABI 祟牲。你可以在你的 module 層級的 build.gradle 文件中使用 ndk.abiFilters 標簽來指定他們:

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your APK.
      abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                   'arm64-v8a'
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

提供給別人使用

ReBuild Project之后隙畜,將生成好的so庫提供有需要的人即可,不過要記得調用的時候包名要一致说贝,不然會報一個找不到so的問題议惰。

LZ簡單寫了一個測試demo,如下圖:

<center>
這里寫圖片描述
這里寫圖片描述

運行結果如下:

<center>
這里寫圖片描述
這里寫圖片描述

比較惡心的就是包名這塊乡恕,等以后再看看有沒有好的解決辦法吧言询。

拓展APP構建流程

查看官方文檔中,突然發(fā)現(xiàn)有關構建流程內容傲宜,一起了解下运杭,如下:

構建流程涉及許多將您的項目轉換成 Android 應用軟件包 (APK)的工具和流程。構建流程非常靈活函卒,因此了解它的一些底層工作原理會很有幫助辆憔。

典型 Android 應用模塊的構建流程圖如下:

<center>
這里寫圖片描述
這里寫圖片描述

典型 Android 應用模塊的構建流程通常依循下列步驟:

1.編譯器將您的源代碼轉換成 DEX(Dalvik Executable) 文件(其中包括運行在 Android 設備上的字節(jié)碼),將所有其他內容轉換成已編譯資源;

2.APK 打包器將 DEX 文件和已編譯資源合并成單個 APK躁愿。不過叛本,必須先簽署 APK,才能將應用安裝并部署到 Android 設備上彤钟;

3.APK 打包器使用調試或發(fā)布密鑰庫簽署您的 APK:

a. 如果您構建的是調試版本的應用(即專用于測試和分析的應用)来候,打包器會使用調試密鑰庫簽署您的應用。Android Studio 自動使用調試密鑰庫配置新項目逸雹;

b. 如果您構建的是打算向外發(fā)布的發(fā)布版本應用营搅,打包器會使用發(fā)布密鑰庫簽署您的應用

4.在生成最終 APK 之前,打包器會使用 zipalign 工具對應用進行優(yōu)化梆砸,減少其在設備上運行時的內存占用

構建流程結束時转质,您將獲得可用來進行部署、測試的調試 APK帖世,或者可用來發(fā)布給外部用戶的發(fā)布 APK休蟹。

參考文獻

  1. http://baike.baidu.com/link?url=QrA-HKewzfPKP5UejCXH8JhE4yQs5MhwG6EBYI8imO9k8zYIlM0h2DYffNSqdK8dG6LZLfT0dK5ocK2NEsOUJq
  2. http://blog.csdn.net/tongseng/article/details/53005123日矫;
  3. http://www.cnblogs.com/bastard/archive/2012/05/19/2508913.html赂弓;
  4. http://blog.csdn.net/baidu_26352053/article/details/53931045
  5. https://developer.android.google.cn/ndk/guides/concepts.html哪轿;
  6. https://developer.android.google.cn/studio/build/index.html;
  7. http://blog.csdn.net/wl9739/article/details/52607010

結束語

這篇文章寫的夠揪心盈魁,個人感覺亂糟糟的,實際學習的時候也是亂糟糟的窃诉,幾乎都是靠著各種搜索杨耙,況且還有一些不靠譜的博文誤導或者說是版本有些老。

望觀看者海涵`有問題及時溝通飘痛。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末珊膜,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子敦冬,更是在濱河造成了極大的恐慌辅搬,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件脖旱,死亡現(xiàn)場離奇詭異堪遂,居然都是意外死亡,警方通過查閱死者的電腦和手機萌庆,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門溶褪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人践险,你說我怎么就攤上這事猿妈〈盗猓” “怎么了?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵彭则,是天一觀的道長鳍刷。 經(jīng)常有香客問我,道長俯抖,這世上最難降的妖魔是什么输瓜? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮芬萍,結果婚禮上尤揣,老公的妹妹穿的比我還像新娘。我一直安慰自己柬祠,他們只是感情好北戏,可當我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著漫蛔,像睡著了一般嗜愈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上惩猫,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天芝硬,我揣著相機與錄音蚜点,去河邊找鬼轧房。 笑死,一個胖子當著我的面吹牛绍绘,可吹牛的內容都是我干的奶镶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼陪拘,長吁一口氣:“原來是場噩夢啊……” “哼厂镇!你這毒婦竟也來了?” 一聲冷哼從身側響起左刽,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤捺信,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后欠痴,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體迄靠,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年喇辽,在試婚紗的時候發(fā)現(xiàn)自己被綠了掌挚。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡菩咨,死狀恐怖吠式,靈堂內的尸體忽然破棺而出陡厘,到底是詐尸還是另有隱情,我是刑警寧澤特占,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布糙置,位于F島的核電站,受9級特大地震影響是目,放射性物質發(fā)生泄漏罢低。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一胖笛、第九天 我趴在偏房一處隱蔽的房頂上張望网持。 院中可真熱鬧,春花似錦长踊、人聲如沸功舀。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽辟汰。三九已至,卻和暖如春阱佛,著一層夾襖步出監(jiān)牢的瞬間帖汞,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工凑术, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留翩蘸,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓淮逊,卻偏偏與公主長得像催首,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子泄鹏,可洞房花燭夜當晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內容