2024-03-25

車載BlueTooth通話機(jī)制原理及開發(fā)

1, 藍(lán)牙框架

主要代碼路徑:

路徑1: frameworks\base\core\java\android\bluetooth\??

藍(lán)牙相關(guān)接口,藍(lán)牙各種功能的發(fā)起點(diǎn)翩蘸。

路徑2:packages\apps\Bluetooth\src\com\android\bluetooth\??

獨(dú)立的Bluetooth.apk,里面包含藍(lán)牙相關(guān)的各種服務(wù),是java層和C/C++層的橋梁人乓。

路徑3: packages\apps\Bluetooth\jni\

? 調(diào)用底層C/C++實(shí)現(xiàn)各種藍(lán)牙功能,并且反饋給java層盅惜。

在路徑2里面還有各種相互獨(dú)立的java代碼包,每一個(gè)包都包含一個(gè)協(xié)議,實(shí)現(xiàn)一個(gè)具體的功能:

btservice: 統(tǒng)一管理,控制其他服務(wù)坪仇。

a2dp: 和藍(lán)牙耳機(jī),音頻有關(guān),比如聽歌等拉背。

avrcp: 音頻/視頻通過連接的藍(lán)牙控制,比如放歌時(shí)控制暫停等芍碧。

gatt:低功耗BLE有關(guān),比如藍(lán)牙按鍵飞醉。

hdp: 藍(lán)牙醫(yī)療有關(guān)

hfp和hfpclient?: 藍(lán)牙通話有關(guān),比如藍(lán)牙通話的相關(guān)操作

hid: 藍(lán)牙鍵盤鍵盤/鼠標(biāo)

map: 同步藍(lán)牙短信相關(guān)

opp: 藍(lán)牙傳輸,比如傳輸文件等

pan: 個(gè)人局域網(wǎng)

pbap: 同步電話本,比如聯(lián)系人/通話記錄等

sap : 藍(lán)牙通話,主要和SIM卡相關(guān)

sdp: 藍(lán)牙服務(wù)發(fā)現(xiàn)/獲取相關(guān)


這12個(gè)包分別實(shí)現(xiàn)了12中藍(lán)牙功能,大多數(shù)以服務(wù)的形式存在,運(yùn)行在Bluetooth.apk中芍躏。不僅如此,還具有以下特點(diǎn):

1,每一個(gè)服務(wù)相互獨(dú)立,互相毫無任何影響, 繼承自 ProfileService,由

AdapterService服務(wù)統(tǒng)一管理。

2,每一個(gè)服務(wù)在路徑1中都存在對(duì)應(yīng)的客戶端類,通過Binder進(jìn)行跨進(jìn)程通信宪巨。

3,每一個(gè)服務(wù)在路徑3中都存在對(duì)應(yīng)的C/C++類,通過JNI機(jī)制互相調(diào)用磷杏。

4,每一個(gè)服務(wù)的啟動(dòng),對(duì)應(yīng)的Binder以及JNI機(jī)制的調(diào)用原理,方法,流程幾乎都是一樣的。

下面以藍(lán)牙通話功能為例來解析相關(guān)接口以及代碼實(shí)現(xiàn)框架圖捏卓。



2 藍(lán)牙通話框架

2.1 相關(guān)類的說明

藍(lán)牙通話上層代碼主要分為3個(gè)部分:

1,藍(lán)牙api相關(guān)代碼, 路徑4: frameworks\base\core\java\android\bluetooth\

主要有2個(gè)類


BluetoothHeadsetClient.java主要負(fù)責(zé)藍(lán)牙通話的相關(guān)動(dòng)作,比如接聽等等

BluetoothHeadsetClientCall.java主要負(fù)責(zé)藍(lán)牙通話的狀態(tài),比如是來電還是去電等等极祸。


2,藍(lán)牙服務(wù)端的相關(guān)代碼,路徑5:

packages\apps\Bluetooth\src\com\android\bluetooth\hfpclient\

有3個(gè)類


HeadsetClientHalConstants.java類里面只是定義了一些int/boolean 類型的值。

HeadsetClientService.java從名字就知道它是一個(gè)服務(wù),它的設(shè)計(jì)很有意思,里面還有一個(gè)BluetoothHeadsetClientBinder內(nèi)部類,該內(nèi)部類主要負(fù)責(zé)和

BluetoothHeadsetClient進(jìn)行跨進(jìn)程通信。另外,HeadsetClientService也是

BluetoothHeadsetClientBinder和HeadsetClientStateMachine之間的橋梁遥金。

HeadsetClientStateMachine是一個(gè)狀態(tài)機(jī),即管理連接的狀態(tài)也是通話時(shí)java和C/C++之間的橋梁,通過JNI機(jī)制和com_android_bluetooth_hfpclient 里面的方法互相調(diào)用浴捆。


3,JNI相關(guān)代碼,路徑6: packages\apps\Bluetooth\jni\

有1個(gè)文件:?


com_android_bluetooth_hfpclient? 藍(lán)牙通話動(dòng)作,撥號(hào)/接聽/掛斷/拒接 實(shí)際的執(zhí)行者。


DialerBTHfpService服務(wù)是開機(jī)之后啟動(dòng)的稿械。




2.2類圖


圖一?類圖


BluetoothHeadsetClient是一個(gè)api,由第三方apk直接調(diào)用,可以進(jìn)行撥號(hào)/接聽/拒接/掛斷操作,對(duì)應(yīng)的方法依次為dial()/acceptCall()/rejectCall()/terminateCall().


HeadsetClientService是一個(gè)服務(wù), BluetoothHeadsetClientBinder是它的內(nèi)部類, BluetoothHeadsetClientBinder是BluetoothHeadsetClient在HeadsetClientService中的代理,通過aidl進(jìn)行方法的調(diào)用选泻。


Connected(已連接狀態(tài))是HeadsetClientStateMachine 的其中一種狀態(tài),通話的相關(guān)操作都建立在已連接狀態(tài)之上,其它三種狀態(tài)為Disconnected, Connecting,

AudioOn狀態(tài)。HeadsetClientService 根據(jù)不同的方法給狀態(tài)機(jī)發(fā)送不同的消息,最后通過HeadsetClientStateMachine根據(jù)JNI機(jī)制調(diào)用

com_android_bluetooth_hfpclient.cpp對(duì)應(yīng)的方法,最后調(diào)用底層C/C++ 來真正的實(shí)現(xiàn)撥號(hào)/接聽/拒接/掛斷操作溜哮。


撥號(hào)/接聽/拒接/掛斷方法調(diào)用的流程完全是一模一樣的,下小節(jié)給出接聽方法具體調(diào)用的完整流程圖滔金。




2.3流程圖


圖二?接聽電話流程圖

除了dial 方法最后調(diào)用從C/C++ dialNative之外,其它的3個(gè)方法最后都是調(diào)用handleCallActionNative,只是參數(shù)不同而已。

撥號(hào)/接聽/拒接/掛斷都是主動(dòng)完成的,那么如果有來電,對(duì)方接通電話或者對(duì)方掛斷電話,我們?cè)趺粗滥孛ぃ窟@些都是com_android_bluetooth_hfpclient.cpp通過JNI機(jī)制調(diào)用通話狀態(tài)機(jī)的方法sendCallChangedIntent,將電話的狀態(tài)(包含在

BluetoothHeadsetClientCall.java中)通過廣播發(fā)送出來,第三方apk監(jiān)聽狀態(tài)就可以進(jìn)行相應(yīng)的操作了餐茵。具體的來電流程圖如下:


?圖三 來電流程圖

3 藍(lán)牙通話apk說明

在自己的apk中,只需要做2件事情就可以完成藍(lán)牙通話的幾乎所有動(dòng)作,

1,根據(jù)上一小節(jié)的論述,注冊(cè)BluetoothHeadsetClientCall相關(guān)廣播,監(jiān)聽來電/接通/對(duì)方掛斷的狀態(tài),獲取藍(lán)牙電話的相關(guān)信息,比如號(hào)碼,設(shè)備信息等等。

比如,如果收到來電廣播,就可以根據(jù)BluetoothHeadsetClientCall獲取來電的號(hào)碼等信息,然后顯示來電界面述吸。

2,通過BluetoothAdapter 獲取并且初始化BluetoothHeadsetClient對(duì)象,然后就可以直接調(diào)用dial()/acceptCall()/rejectCall()/terminateCall() 方法進(jìn)行撥號(hào)/接聽/拒接/掛斷的操作了忿族。


4, 小節(jié)

利用api實(shí)現(xiàn)藍(lán)牙通話不是很難,但是如果弄清楚具體的藍(lán)牙通話機(jī)制以及細(xì)節(jié)甚至藍(lán)牙相關(guān)功能,這就得下功夫了,關(guān)于藍(lán)牙,還可以進(jìn)一步研究的android知識(shí)點(diǎn)以及藍(lán)牙涉及的上層java要點(diǎn)如下:

1,基本藍(lán)牙功能:打開/關(guān)閉/掃描/配對(duì)/連接

2,藍(lán)牙功能:通過藍(lán)牙傳輸文件/藍(lán)牙鍵盤/藍(lán)牙醫(yī)療服務(wù)/藍(lán)牙同步聯(lián)系人等等

3,android知識(shí):跨進(jìn)程通信機(jī)制/JNI機(jī)制/反射機(jī)制/狀態(tài)機(jī)機(jī)制等等。


實(shí)際開發(fā)過程

公司用的是android8.1的源碼蝌矛,系統(tǒng)api有改動(dòng)道批,改動(dòng)的地方會(huì)稍微標(biāo)明一下。我是在系統(tǒng)源碼上開發(fā)的入撒,所以有些類或者api@hide了 在開發(fā)工具上會(huì)報(bào)錯(cuò)隆豹,但是可以編譯通過。如果是純應(yīng)用上層需要利用反射茅逮,有一部分功能需要移植代碼璃赡。

車載藍(lán)牙主要是實(shí)現(xiàn)藍(lán)牙電話,藍(lán)牙音樂献雅,同步通訊錄碉考。這些功能都是用到藍(lán)牙的配置文件協(xié)議。下面簡單介紹一下這幾個(gè)協(xié)議挺身。

1.HFP(Hands-free Profile)侯谁,讓藍(lán)牙設(shè)備可以控制電話,如接聽章钾、掛斷墙贱、拒接、語音撥號(hào)等贱傀,拒接惨撇、語音撥號(hào)要視藍(lán)牙耳機(jī)及電話是否支持。

2.A2DP(Advanced Audio Distribution Profile)是藍(lán)牙的音頻傳輸協(xié)議窍箍,典型應(yīng)用為藍(lán)牙耳機(jī)。A2DP協(xié)議的音頻數(shù)據(jù)在ACL Link上傳輸。

3.AVRCP(Audio/Video Remote Control Profile)作用是支持CT控制TG椰棘,具體來說如果手機(jī)和一個(gè)藍(lán)牙音箱設(shè)備連接上了纺棺,那么音箱可以控制手機(jī)播放/暫停/切歌以及獲得手機(jī)上播放歌曲的信息,如專輯邪狞,歌名祷蝌,歌手,時(shí)長等信息帆卓。

4.PBAP(Phone Book Access Profile)訪問下載通訊錄以及通話記錄巨朦。

以上是簡單介紹這些協(xié)議的用途,想具體了解可以分別取查資料剑令,這方面資料很多糊啡。

一.打開藍(lán)牙,查找藍(lán)牙設(shè)備吁津,連接藍(lán)牙協(xié)議棚蓄。

要使用藍(lán)牙必須先在文件清單加權(quán)限

<uses-permission android:name="android.permission.BLUETOOTH"/>

? ? <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

檢測(cè)設(shè)備藍(lán)牙是否打開,沒有可以自動(dòng)打開碍脏,也可以請(qǐng)求梭依,給用戶提示,讓用戶自己打開典尾。


查找藍(lán)牙之前可以先查看是否有以前綁定過的藍(lán)牙設(shè)備

Set<BluetoothDevice>devices=mBluetoothAdapter.getBondedDevices();

if(devices !=null&&devices.size()>0) {

for(Iterator<BluetoothDevice>it=devices.iterator(); it.hasNext();) {

BluetoothDevice device=it.next();

if(device !=null) {

? ? ? ? addBluetoothDevice(device);

? ? }

}

? ? }


mBluetoothManager=(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

mBluetoothAdapter=mBluetoothManager.getAdapter();

if(!mBluetoothAdapter.isEnabled()) {

? mBluetoothAdapter.enable();

}


查找藍(lán)牙可以先查找低功耗藍(lán)牙役拴,一般查找時(shí)間為8-10秒,然后再查找經(jīng)典藍(lán)牙钾埂。兩種查找用的api不同河闰,先說一下查找低功耗藍(lán)牙設(shè)備。

拿到BluetoothLeScanner:mBluetoothLeScanner = mBluetoothAdapter.getBluetoothLeScanner();

調(diào)用startScan勃教,參數(shù)為ScanCallback對(duì)象淤击,它里面有各種回調(diào),根據(jù)自己的需求實(shí)現(xiàn)故源。

privatefinalScanCallbackscanCallback=newScanCallback() {

@Override

publicvoidonScanResult(intcallbackType, ScanResult result){

super.onScanResult(callbackType, result);

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

BluetoothDevicedevice=result.getDevice();

Log.i(TAG,"scan succeed device ==? "+device);

? ? ? ? ? ? ? ? addBluetoothDevice(device);

? ? ? ? ? ? }

? ? ? ? }

@Override

publicvoidonBatchScanResults(List<ScanResult> results){

super.onBatchScanResults(results);

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){

for(ScanResult result: results){

Log.i(TAG,"scan succeed device ==? "+result.getDevice());

? ? ? ? ? ? ? ? ? ? addBluetoothDevice(result.getDevice());

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

@Override

publicvoidonScanFailed(interrorCode){

super.onScanFailed(errorCode);

Log.i(TAG,"scan fail");

? ? ? ? }

? ? };

查看經(jīng)典藍(lán)牙直接使用BluetoothAdapter的startDiscovery方法污抬,注冊(cè)BluetoothDevice.ACTION_FOUND廣播接收搜索到的藍(lán)牙設(shè)備。使用intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE)可以得到BluetoothDevice绳军。

接著連接設(shè)備印机,連接設(shè)備之前需要綁定設(shè)備,就是確認(rèn)雙方設(shè)備的存在通過相同秘鑰门驾,如果需要訪問通訊錄射赛,需要勾選權(quán)限。

可以先判斷BluetoothDevice的狀態(tài)奶是,如果狀態(tài)為BluetoothDevice.BOND_NONE楣责,調(diào)用bluetoothDevice.createBond()進(jìn)行綁定竣灌。

講連接之前說一下自己踩過的坑,也不能說是坑秆麸,自己能力不足所以花了不少時(shí)間初嘹。開始我以為連接藍(lán)牙需要socket通訊,查google文檔說要? ?兩臺(tái)設(shè)備一臺(tái)充當(dāng)客戶端一臺(tái)充當(dāng)服務(wù)端沮趣,然后用io流傳輸數(shù)據(jù)屯烦。我一直在糾結(jié),我只能操作車載應(yīng)用房铭,用戶手機(jī)安裝不了我開發(fā)的應(yīng)用驻龟,那這怎么連接呢。后來看到系統(tǒng)setting有連接藍(lán)牙的效果就果斷去setting的Bluetooth模塊查看連接藍(lán)牙的代碼缸匪,終于找到了翁狐。在frameworks\base\packages\SettingsLib\src\com\android\settingslib\bluetooth中專門有個(gè)類存儲(chǔ)管理藍(lán)牙設(shè)備CachedBluetoothDevice.java,他連接遠(yuǎn)程藍(lán)牙設(shè)備就是

synchronizedvoid connectInt(LocalBluetoothProfile profile) {

if(!ensurePaired()) {

return;

? ? ? ? }

if(profile.connect(mDevice)) {

if(Utils.D) {

Log.d(TAG,"Command sent successfully:CONNECT "+describe(profile));

? ? ? ? ? ? }

return;

? ? ? ? }

Log.i(TAG,"Failed to connect "+profile.toString()+" to "+mName);

? ? }

LocalBluetoothProfile是一個(gè)接口豪嗽,各種協(xié)議的封裝者實(shí)現(xiàn)了該接口谴蔑,例如HfpClientProfile它里面封裝的是BluetoothHeadsetClient,就是HFP協(xié)議龟梦。主要看它的connect方法

@Override

publicbooleanconnect(BluetoothDevice device) {

if(mService==null)returnfalse;

List<BluetoothDevice>srcs=getConnectedDevices();

if(srcs !=null) {

for(BluetoothDevice src : srcs) {

if(src.equals(device)) {

//Connecttosamedevice, Ignore it

Log.d(TAG,"Ignoring Connect");

returntrue;

? ? ? ? ? ? ? ? }

? ? ? ? ? ? }

? ? ? ? }

returnmService.connect(device);

? ? }

先獲取已連接的藍(lán)牙設(shè)備隐锭,如果藍(lán)牙設(shè)備已連接返回true,不在列表中則調(diào)用BluetoothHeadsetClient的connect方法。接著看下這個(gè)BluetoothHeadsetClient怎么實(shí)例化计贰。

mLocalAdapter.getProfileProxy(context,newHfpClientServiceListener(),

? ? ? ? ? ? ? ? BluetoothProfile.HEADSET_CLIENT);

通過BluetoothAdapter的getProfileProxy方法去請(qǐng)求這個(gè)協(xié)議對(duì)象钦睡。

privatefinalclassHfpClientServiceListener

implementsBluetoothProfile.ServiceListener {

@Override

publicvoidonServiceConnected(intprofile, BluetoothProfile proxy){

if(V) Log.d(TAG,"Bluetooth service connected");

? ? ? ? ? ? mService = (BluetoothHeadsetClient) proxy;

// We just bound to the service, so refresh the UI for any connected HFP devices.

? ? ? ? ? ? List<BluetoothDevice> deviceList = mService.getConnectedDevices();

while(!deviceList.isEmpty()) {

BluetoothDevicenextDevice=deviceList.remove(0);

CachedBluetoothDevicedevice=mDeviceManager.findDevice(nextDevice);

// we may add a new device here, but generally this should not happen

if(device ==null) {

Log.w(TAG,"HfpClient profile found new device: "+ nextDevice);

? ? ? ? ? ? ? ? ? ? device = mDeviceManager.addDevice(mLocalAdapter, mProfileManager, nextDevice);

? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? device.onProfileStateChanged(

HfpClientProfile.this, BluetoothProfile.STATE_CONNECTED);

? ? ? ? ? ? ? ? device.refresh();

? ? ? ? ? ? }

mIsProfileReady=true;

? ? ? ? }

@Override

publicvoidonServiceDisconnected(intprofile){

if(V) Log.d(TAG,"Bluetooth service disconnected");

mIsProfileReady=false;

? ? ? ? }

? ? }

need-to-insert-img

監(jiān)聽返回狀態(tài),賦值躁倒。其實(shí)不僅僅是BluetoothHeadsetClient荞怒,BluetoothA2dpSink等等請(qǐng)求方式一模一樣,參數(shù)不同秧秉『肿溃看到這個(gè)之后恍然大悟,車載藍(lán)牙實(shí)現(xiàn)的功能不需要進(jìn)行socket通信象迎,只需要連接這些協(xié)議荧嵌。

好了,整理一下連接過程砾淌,先拿到BluetoothAdapter啦撮,調(diào)用getProfileProxy方法請(qǐng)求協(xié)議,第三個(gè)參數(shù)為協(xié)議的種類汪厨,都定義在BluetoothProfile中赃春,例如BluetoothProfile.AVRCP_CONTROLLER(藍(lán)牙控制協(xié)議),BluetoothProfile.A2DP_SINK(音頻協(xié)議)劫乱。實(shí)現(xiàn)BluetoothProfile.ServiceListener接口织中,監(jiān)聽返回狀態(tài)锥涕。如果返回成功得到對(duì)象,就可以調(diào)用connect(BluetoothDevice device)連接狭吼。

mAdapter=BluetoothAdapter.getDefaultAdapter();

mAdapter.getProfileProxy(mContext, new ProxyServiceListener(), BluetoothProfile.AVRCP_CONTROLLER);

mAdapter.getProfileProxy(mContext, new ProxyServiceListener(), BluetoothProfile.A2DP_SINK);

privatefinalclassProxyServiceListener implements BluetoothProfile.ServiceListener {

@Override

public void onServiceConnected(int profile, BluetoothProfile proxy) {

Log.d(TAG,"Bluetooth service connected profile == "+profile);

if(profile==BluetoothProfile.AVRCP_CONTROLLER) {

isAvrcpProfileReady=true;

mAvrcpCt=(BluetoothAvrcpController)proxy;

Log.d(TAG,"AvrcpController Profile Proxy Connected");

}

if(profile==BluetoothProfile.A2DP_SINK) {

isA2dpProfileReady=true;

mA2dpSink=(BluetoothA2dpSink)proxy;

Log.d(TAG,"BluetoothA2dpSink Profile Proxy Connected");

}

}

@Override

public void onServiceDisconnected(int profile) {

if(profile==BluetoothProfile.AVRCP_CONTROLLER) {

isAvrcpProfileReady=false;

mAvrcpCt=null;

Log.d(TAG,"AvrcpController Profile Proxy Disconnected");

}

if(profile==BluetoothProfile.A2DP_SINK) {

isA2dpProfileReady=false;

mA2dpSink=null;

Log.d(TAG,"BluetoothA2dpSink Profile Proxy Disconnected");

}

}

}

publicbooleanconnect(BluetoothDevice device) {

if(null!=mA2dpSink) {

returnmA2dpSink.connect(device);

}

Log.i(TAG,"mA2dpSink == null");

returnfalse;

}


來源于?https://blog.csdn.net/dl6655/article/details/82798431

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末站楚,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子搏嗡,更是在濱河造成了極大的恐慌,老刑警劉巖拉一,帶你破解...
    沈念sama閱讀 206,482評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件采盒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡蔚润,警方通過查閱死者的電腦和手機(jī)磅氨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,377評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來嫡纠,“玉大人烦租,你說我怎么就攤上這事〕担” “怎么了叉橱?”我有些...
    開封第一講書人閱讀 152,762評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長者蠕。 經(jīng)常有香客問我窃祝,道長,這世上最難降的妖魔是什么踱侣? 我笑而不...
    開封第一講書人閱讀 55,273評(píng)論 1 279
  • 正文 為了忘掉前任粪小,我火速辦了婚禮,結(jié)果婚禮上抡句,老公的妹妹穿的比我還像新娘探膊。我一直安慰自己,他們只是感情好待榔,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,289評(píng)論 5 373
  • 文/花漫 我一把揭開白布逞壁。 她就那樣靜靜地躺著,像睡著了一般究抓。 火紅的嫁衣襯著肌膚如雪猾担。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,046評(píng)論 1 285
  • 那天刺下,我揣著相機(jī)與錄音绑嘹,去河邊找鬼。 笑死橘茉,一個(gè)胖子當(dāng)著我的面吹牛工腋,可吹牛的內(nèi)容都是我干的姨丈。 我是一名探鬼主播,決...
    沈念sama閱讀 38,351評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼擅腰,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼蟋恬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起趁冈,我...
    開封第一講書人閱讀 36,988評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤歼争,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后渗勘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沐绒,經(jīng)...
    沈念sama閱讀 43,476評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,948評(píng)論 2 324
  • 正文 我和宋清朗相戀三年旺坠,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了乔遮。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,064評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡取刃,死狀恐怖蹋肮,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情璧疗,我是刑警寧澤坯辩,帶...
    沈念sama閱讀 33,712評(píng)論 4 323
  • 正文 年R本政府宣布,位于F島的核電站崩侠,受9級(jí)特大地震影響濒翻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜啦膜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,261評(píng)論 3 307
  • 文/蒙蒙 一有送、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧僧家,春花似錦雀摘、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,264評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至肌稻,卻和暖如春清蚀,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爹谭。 一陣腳步聲響...
    開封第一講書人閱讀 31,486評(píng)論 1 262
  • 我被黑心中介騙來泰國打工枷邪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人诺凡。 一個(gè)月前我還...
    沈念sama閱讀 45,511評(píng)論 2 354
  • 正文 我出身青樓东揣,卻偏偏與公主長得像践惑,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嘶卧,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,802評(píng)論 2 345

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