Android 低功耗(BLE)蓝牙(三)

本文章经典蓝牙开发目录:

1、权限申请
2、开启蓝牙
3、扫描蓝牙
4、连接蓝牙
5、通信(实现双向通信)(这个是公司的设备,我把步骤说清楚,没法演示~)
6、关闭各种通信

1、2两个步骤和经典蓝牙的步骤是一样的,在这里不在写了,可以看一下上一篇的经典蓝牙的1/2两部哦~~~
Android 蓝牙开发 经典蓝牙和低功耗蓝牙(一)
Android 经典蓝牙开发(二)

bug10.jpeg

开发之前先了解几个概念,大概知道啥意思就行:

BluetoothGatt
这个类提供了 Bluetooth GATT 的基本功能。例如重新连接蓝牙设备,发现蓝牙设备的 Service 等等。
BluetoothGattService
这一个类通过 BluetoothGatt#getService 获得,如果当前服务不可见那么将返回一个 null。这一个类对应上面说过的 Service。我们可以通过这个类的 getCharacteristic(UUID uuid) 进一步获取 Characteristic 实现蓝牙数据的双向传输。
BluetoothGattCharacteristic
这个类对应上面提到的 Characteristic。通过这个类定义需要往外围设备写入的数据和读取外围设备发送过来的数据。

第三步,扫描蓝牙

扫描蓝牙
低功耗蓝牙扫描有两种方式
api>=21 bluetoothAdapter.getBluetoothLeScanner().startScan(scanCallback)
api<21 bluetoothAdapter.startLeScan(leScanCallback)

      /**
         * 扫描
         */
        public void scanLeDevice(final BluetoothAdapter.LeScanCallback leScanCallback, final ScanCallback scanCallback) {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (bluetoothAdapter.isEnabled() && bluetoothLeScanner != null) {
                    bluetoothLeScanner.startScan(scanCallback);//开始搜索
                } else {
                    Log.e("mcy", "蓝牙不可用...");
                }
            } else {
                if (bluetoothAdapter.isEnabled()) {
                    bluetoothAdapter.startLeScan(leScanCallback); //开始搜索
                } else {
                    Log.e("mcy", "蓝牙不可用...");
                }
            }
            Log.e("mcy", "开始扫描...");
        }

停止扫描

       /**
         * 停止扫描
         */
        public void stopScan(BluetoothAdapter.LeScanCallback mLeScanCallback, ScanCallback scanCallback) {
            Log.e("mcy", "停止扫描...");
            if (bluetoothAdapter != null && mLeScanCallback != null) {
                bluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            if (bluetoothLeScanner != null && scanCallback != null) {
                bluetoothLeScanner.stopScan(scanCallback);
            }

        }

还有两个回调的方法,这是用来反馈扫描的结果的:

//api<21回调这个借口
        leScanCallback = new BluetoothAdapter.LeScanCallback() {
            @Override
            public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {

                if (!TextUtils.isEmpty(device.getName())) {
                    if (!devicesList.contains(device)) {
                        devicesList.add(device);
                        Log.e("mcy", "扫描到设备-->" + device.getName());
                        textView.setText(textView.getText() + "\n" + device.getName());
                    }
                    if (device.getName().equals("00doos009000012147")) {//连接制定的设备。!!!!!测试使用!!!!!!
                        Log.e("mcy", "扫描到设备-->" + device.getName());
                        bleBTBind.stopScan(leScanCallback, scanCallback);
                        bleBTBind.connectLeDevice(MainActivity.this, device);
                    }

                }


            }
        };
        //api>=21回调这个借口
        scanCallback = new ScanCallback() {
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                if (!TextUtils.isEmpty(result.getDevice().getName())) {
                    if (!devicesList.contains(result.getDevice())) {
                        devicesList.add(result.getDevice());
                        textView.setText(textView.getText() + "\n" + result.getDevice().getName());
                    }
                    if (result.getDevice().getName().equals("00doos009000012147")) {//连接制定的设备。!!!!!测试使用!!!!!!
                        Log.e("mcy", "扫描到设备-->" + result.getDevice().getName());
                        bleBTBind.stopScan(leScanCallback, scanCallback);
                        bleBTBind.connectLeDevice(MainActivity.this, result.getDevice());
                    }
                }
            }
        };
bug11.jpeg

第四步,连接蓝牙

低功耗蓝牙没有配对这么一说,直接连接,连接方式有两种,一种是根据蓝牙的地址获取远程设备连接,连接另一种是蓝牙设备直接连接,传入一个回调接口,反馈连接状态,发现服务状态,可以进行下一步的操作

/**
         * 连接方式二
         */

        public void connectLeDevice(Context context, BluetoothDevice device) {
            bluetoothGatt = device.connectGatt(context, false, mBluetoothGattCallback);
        }
        /**
         * 连接方式一
         */
        public void connection(Context context, String address) {
            if (BluetoothAdapter.checkBluetoothAddress(address)) {
                BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(address);
                if (remoteDevice == null) {
                    Log.e("mcy", "设备不可用");
                }
                connectLeDevice(context, remoteDevice);
            } else {
                Log.e("mcy", "设备不可用");
            }
        }

连接的时候,需要传递一个接口回调,这个是设备反馈回来的状态,具体的使用,代码注释说的很清楚了,不再赘述。

 mBluetoothGattCallback = new BluetoothGattCallback() {

            //当连接状态发生改变
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                super.onConnectionStateChange(gatt, status, newState);
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    Log.e("mcy", "连接成功..." + gatt.getDevice().getName());
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.e("mcy", "连接断开...");
                } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                    Log.e("mcy", "连接ing...");
                }
            }

            //发现新服务,即调用了mBluetoothGatt.discoverServices()后,返回的数据
            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                super.onServicesDiscovered(gatt, status);
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e("mcy", "发现服务成功...");
                    gattService = gatt.getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));
                    indexTpye = 1;
                    if (gattService == null) {
                        indexTpye = 2;
                        gattService = gatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));
                    }
                    if (gattService == null) {
                        Log.e("mcy", "获取bluetoothGattService失败...");
                    } else {
                        if (indexTpye == 1) {
                            gattCharacteristic = gattService.getCharacteristic(UUID.fromString("49535343-8841-43F4-A8D4-ECBE34729BB3"));
                        } else {
                            gattCharacteristic = gattService.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));
                        }
                        if (gattCharacteristic == null) {
                            Log.e("mcy", "获取Characteristic失败...");
                        } else {
                            bluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);//这一句是为了接受蓝牙数据,必须写!!!否则接受不到数据
                            bleResultCallBack.onDiscoverServicesSuccess();
                        }
                    }
                } else {
                    Log.e("mcy", "发现服务失败...");
                }

            }

            //读取从设备传递过来的数据值,在这里读数据
            @Override
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicRead(gatt, characteristic, status);
                Log.e("mcy", "onCharacteristicRead...");
            }

            //发送数据后的回调
            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicWrite(gatt, characteristic, status);
                Log.e("mcy", "onCharacteristicWrite...发送成功后走这个方法");

            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                super.onCharacteristicChanged(gatt, characteristic);
                Log.e("mcy", "---蓝牙回传数据onCharacteristicChanged---");
                byte[] value = characteristic.getValue();
                if (value != null && value.length > 0) {
                    Log.e("mcy", "接收数据" + Arrays.toString(value));
                    bleResultCallBack.onReturnResult(value);

                }
            }

        };
bug3.jpeg

第五步,通信

通信包括发送数据和读取数据,这里,我们只需要发送数据就行啦,读数据的话,在上面的接口中回调回来了,进行数据处理就行啦

我这里展示了两种发送数据的方式:均使用 handler 处理了一下,没有直接发送。因为Characteristic最长只能发送 20 个字节,如果要是超过 20 个字节,就得循环发送,当然了,接受数据的时候,也是这个样子,一次接收不完,循环接收。

我这里也有一个问题,就是直接发送数据,第二次会失败,一直没找到原因,但是我换handler 方式,就发送成功,若有大佬知道原因,求你联系我,给小女解惑。

 /**
         * 向蓝牙发送数据方式一
         */
        public void sendDataToBT() {
            bluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);//不写这一句,蓝牙消息会回传不回来
            if (gattCharacteristic != null && bluetoothGatt != null) {
                //设置读数据的UUID
                for (byte[] datum : data) {
                    Log.e("mcy_devidedPacket", "" + Arrays.toString(datum));
                    gattCharacteristic.setValue(datum);
                    Message message = new Message();
                    message.obj = datum;
                    handler1.sendMessage(message);

                }
            }

        }

        private void writeData() {
            try {
                boolean b = bluetoothGatt.writeCharacteristic(gattCharacteristic);
                if (b) {
                    Thread.sleep(200);
                } else {
                    for (int i = 0; i < 10; i++) {
                        if (bluetoothGatt.writeCharacteristic(gattCharacteristic)) {
                            return;
                        }
                    }
                    Log.e("mcy", "10次递归发送数据失败" + b);
                    cancleConnection();
                }
                Log.e("mcy", "发送数据是否成功:" + b);

            } catch (Exception e) {
                e.printStackTrace();
            }


        }

        //存储待发送的数据队列
        public Queue<byte[]> dataInfoQueue = new LinkedList<>();

        private Handler handler2 = new Handler();

        private Runnable runnable = new Runnable() {
            @Override
            public void run() {
                send();
            }
        };

        /**
         * 向蓝牙发送数据方式二
         */
        public void sendDataToBT2() {
            if (dataInfoQueue != null) {
                dataInfoQueue.clear();
                dataInfoQueue = Utils.splitPacketFor20Byte(data2);
                handler2.post(runnable);
            }

        }

        private void send() {
            if (dataInfoQueue != null && !dataInfoQueue.isEmpty()) {
                //检测到发送数据,直接发送
                if (dataInfoQueue.peek() != null) {
                    gattCharacteristic.setValue(dataInfoQueue.poll());//移除并返回队列头部的元素
                    boolean b = bluetoothGatt.writeCharacteristic(gattCharacteristic);
                    Log.e("mcy", "发送数据是否成功:" + b);
                }
                //检测还有数据,延时后继续发送,一般延时100毫秒左右
                if (dataInfoQueue.peek() != null) {
                    handler2.postDelayed(runnable, 100);
                }
            }
        }
bug.jpeg

第六步,关闭各种通信

        /**
         * 断开连接
         */
        public void cancleConnection() {
            if (bluetoothGatt != null) {
                bluetoothGatt.close();
                Log.e("mcy", "主动断开连接...");
            }
        }
bug6.jpeg

---------------------好啦,放大招-------------------

BleBlueToothService.java

public class BleBlueToothService extends Service {

    private BluetoothAdapter bluetoothAdapter;
    private BluetoothGatt bluetoothGatt;
    private BluetoothLeScanner bluetoothLeScanner;
    private BluetoothGattCallback mBluetoothGattCallback;
    private BleResultCallBack bleResultCallBack;
    private BluetoothGattService gattService;
    private BluetoothGattCharacteristic gattCharacteristic;

    private byte[][] data = new byte[][]{{2, 0, 19, 67, 79, 49, 50, 51, 52, 53, 54, 55, 56, 1, 73, -33, 77, -19, -61, -1},
            {41, -45, -26, 3}};
    private byte[] data2 = new byte[]{2, 0, 19, 67, 79, 49, 50, 51, 52, 53, 54, 55, 56, 1, 73, -33, 77, -19, -61, -1, 41, -45, -26, 3};

    private int indexTpye = 0;

    @Override
    public void onCreate() {
        super.onCreate();
        //获取蓝牙适配器
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        bluetoothLeScanner = bluetoothAdapter.getBluetoothLeScanner();
        mBluetoothGattCallback = new BluetoothGattCallback() {

            //当连接状态发生改变
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
                super.onConnectionStateChange(gatt, status, newState);
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    Log.e("mcy", "连接成功..." + gatt.getDevice().getName());
                    gatt.discoverServices();
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    Log.e("mcy", "连接断开...");
                } else if (newState == BluetoothProfile.STATE_DISCONNECTING) {
                    Log.e("mcy", "连接ing...");
                }
            }

            //发现新服务,即调用了mBluetoothGatt.discoverServices()后,返回的数据
            @Override
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                super.onServicesDiscovered(gatt, status);
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    Log.e("mcy", "发现服务成功...");
                    gattService = gatt.getService(UUID.fromString("49535343-fe7d-4ae5-8fa9-9fafd205e455"));
                    indexTpye = 1;
                    if (gattService == null) {
                        indexTpye = 2;
                        gattService = gatt.getService(UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb"));
                    }
                    if (gattService == null) {
                        Log.e("mcy", "获取bluetoothGattService失败...");
                    } else {
                        if (indexTpye == 1) {
                            gattCharacteristic = gattService.getCharacteristic(UUID.fromString("49535343-8841-43F4-A8D4-ECBE34729BB3"));
                        } else {
                            gattCharacteristic = gattService.getCharacteristic(UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"));
                        }
                        if (gattCharacteristic == null) {
                            Log.e("mcy", "获取Characteristic失败...");
                        } else {
                            bluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);//这一句是为了接受蓝牙数据,必须写!!!否则接受不到数据
                            bleResultCallBack.onDiscoverServicesSuccess();
                        }
                    }
                } else {
                    Log.e("mcy", "发现服务失败...");
                }

            }

            //读取从设备传递过来的数据值,在这里读数据
            @Override
            public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicRead(gatt, characteristic, status);
                Log.e("mcy", "onCharacteristicRead...");
            }

            //发送数据后的回调
            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
                super.onCharacteristicWrite(gatt, characteristic, status);
                Log.e("mcy", "onCharacteristicWrite...发送成功后走这个方法");

            }

            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
                super.onCharacteristicChanged(gatt, characteristic);
                Log.e("mcy", "---蓝牙回传数据onCharacteristicChanged---");
                byte[] value = characteristic.getValue();
                if (value != null && value.length > 0) {
                    Log.e("mcy", "接收数据" + Arrays.toString(value));
                    bleResultCallBack.onReturnResult(value);

                }
            }

        };
    }


    public class BleBlueToothBind extends Binder {

        public BluetoothAdapter getAdapter() {
            return bluetoothAdapter;
        }

        public void setBleResultCallBack(BleResultCallBack bleResultCallBack) {
            BleBlueToothService.this.bleResultCallBack = bleResultCallBack;
        }

        /**
         * 扫描
         */
        public void scanLeDevice(final BluetoothAdapter.LeScanCallback leScanCallback, final ScanCallback scanCallback) {

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                if (bluetoothAdapter.isEnabled() && bluetoothLeScanner != null) {
                    bluetoothLeScanner.startScan(scanCallback);//开始搜索
                } else {
                    Log.e("mcy", "蓝牙不可用...");
                }
            } else {
                if (bluetoothAdapter.isEnabled()) {
                    bluetoothAdapter.startLeScan(leScanCallback); //开始搜索
                } else {
                    Log.e("mcy", "蓝牙不可用...");
                }
            }
            Log.e("mcy", "开始扫描...");
        }

        /**
         * 停止扫描
         */
        public void stopScan(BluetoothAdapter.LeScanCallback mLeScanCallback, ScanCallback scanCallback) {
            Log.e("mcy", "停止扫描...");
            if (bluetoothAdapter != null && mLeScanCallback != null) {
                bluetoothAdapter.stopLeScan(mLeScanCallback);
            }
            if (bluetoothLeScanner != null && scanCallback != null) {
                bluetoothLeScanner.stopScan(scanCallback);
            }

        }


        /**
         * 连接方式二
         */

        public void connectLeDevice(Context context, BluetoothDevice device) {
            bluetoothGatt = device.connectGatt(context, false, mBluetoothGattCallback);
        }
        /**
         * 连接方式一
         */
        public void connection(Context context, String address) {
            if (BluetoothAdapter.checkBluetoothAddress(address)) {
                BluetoothDevice remoteDevice = bluetoothAdapter.getRemoteDevice(address);
                if (remoteDevice == null) {
                    Log.e("mcy", "设备不可用");
                }
                connectLeDevice(context, remoteDevice);
            } else {
                Log.e("mcy", "设备不可用");
            }
        }

        private Handler handler1 = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                writeData();

            }
        };

        /**
         * 向蓝牙发送数据方式一
         */
        public void sendDataToBT() {
            bluetoothGatt.setCharacteristicNotification(gattCharacteristic, true);//不写这一句,蓝牙消息会回传不回来
            if (gattCharacteristic != null && bluetoothGatt != null) {
                //设置读数据的UUID
                for (byte[] datum : data) {
                    Log.e("mcy_devidedPacket", "" + Arrays.toString(datum));
                    gattCharacteristic.setValue(datum);
                    Message message = new Message();
                    message.obj = datum;
                    handler1.sendMessage(message);

                }
            }

        }

        private void writeData() {
            try {
                boolean b = bluetoothGatt.writeCharacteristic(gattCharacteristic);
                if (b) {
                    Thread.sleep(200);
                } else {
                    for (int i = 0; i < 10; i++) {
                        if (bluetoothGatt.writeCharacteristic(gattCharacteristic)) {
                            return;
                        }
                    }
                    Log.e("mcy", "10次递归发送数据失败" + b);
                    cancleConnection();
                }
                Log.e("mcy", "发送数据是否成功:" + b);

            } catch (Exception e) {
                e.printStackTrace();
            }


        }

        //存储待发送的数据队列
        public Queue<byte[]> dataInfoQueue = new LinkedList<>();

        private Handler handler2 = new Handler();

        private Runnable runnable = new Runnable() {
            @Override
            public void run() {
                send();
            }
        };

        /**
         * 向蓝牙发送数据方式二
         */
        public void sendDataToBT2() {
            if (dataInfoQueue != null) {
                dataInfoQueue.clear();
                dataInfoQueue = Utils.splitPacketFor20Byte(data2);
                handler2.post(runnable);
            }

        }

        private void send() {
            if (dataInfoQueue != null && !dataInfoQueue.isEmpty()) {
                //检测到发送数据,直接发送
                if (dataInfoQueue.peek() != null) {
                    gattCharacteristic.setValue(dataInfoQueue.poll());//移除并返回队列头部的元素
                    boolean b = bluetoothGatt.writeCharacteristic(gattCharacteristic);
                    Log.e("mcy", "发送数据是否成功:" + b);
                }
                //检测还有数据,延时后继续发送,一般延时100毫秒左右
                if (dataInfoQueue.peek() != null) {
                    handler2.postDelayed(runnable, 100);
                }
            }
        }


        /**
         * 断开连接
         */
        public void cancleConnection() {
            if (bluetoothGatt != null) {
                bluetoothGatt.close();
                Log.e("mcy", "主动断开连接...");
            }
        }

    }


    @Override
    public IBinder onBind(Intent intent) {
        return new BleBlueToothBind();
    }
}

使用:

 bleConnection = new ServiceConnection() {
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                bleBTBind = ((BleBlueToothService.BleBlueToothBind) service);
                if (bleBTBind.getAdapter() != null) {
                    //判断蓝牙是否开启
                    if (!bleBTBind.getAdapter().isEnabled()) {
                        //打开蓝牙
                        openBlueSync(MainActivity.this, openBTCode);
                    } else {
                        //========================开始执行工作=============================
                        bleBTBind.scanLeDevice(leScanCallback, scanCallback);
                        final StringBuilder stringBuilder = new StringBuilder();
                        bleBTBind.setBleResultCallBack(new BleResultCallBack() {
                            //连接成功回调
                            @Override
                            public void onDiscoverServicesSuccess() {
                                bleBTBind.stopScan(leScanCallback, scanCallback);
                                bleBTBind.sendDataToBT();//方式一
//                                bleBTBind.sendDataToBT2();//方式二

                            }

                            //蓝牙返回数据回调
                            @Override
                            public void onReturnResult(byte[] data) {
                                bleBTBind.stopScan(leScanCallback, scanCallback);
                                for (byte byteChar : data) {
                                    stringBuilder.append(String.format("%02X ", byteChar));
                                }
                                String returnedPacket = stringBuilder.toString().replace(" ", "");
                                byte[] packetByte = Utils.hexStringToByteArray(returnedPacket);
                                if (packetByte.length - 5 == Utils.getLengthFromToken(packetByte)) {
                                    Log.e("mcy_returnedPacket", returnedPacket);
                                    bleBTBind.cancleConnection();//取消连接
                                }
                            }


                        });
                    }
                } else {
                    Log.e("mcy", "此设备不支持蓝牙");
                }


            }

            @Override
            public void onServiceDisconnected(ComponentName name) {
                bleBTBind = null;

            }
        };
        bindService(new Intent(this, BleBlueToothService.class), bleConnection, BIND_AUTO_CREATE);

github,地址 : https://github.com/Mchunyan/BlueToothTest

-----------------------The End-----------------

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容