Android蓝牙开锁讲解

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/a214024475/article/details/87874927

目录

今日科技快讯

介绍

实战


 

今日科技快讯

2月21日凌晨,三星美国旧金山举行Galaxy Unpacked 2019新品发布会。正式发布年度旗舰Galaxy S10系列手机以及折叠手机Galaxy Fold,还推出了首款5G手机。

Galaxy Fold此前曾在2018年11月开发者大会上亮相,但当时并没宣布具体参数,今天这是它终于定妆出场。它的形态是两折的,仿佛一个钱包,外表是一块4.6英寸的狭长屏幕,打开后,内部是一块7.3英寸的屏幕。三星Galaxy S10系列一共包含三款机型,分别是S10、S10+、S10e。相比去年的S9系列,S10系列外观最大的变化在于采用Dynamic AMOLED屏幕设计,网友俗称“挖孔屏”,其中S10为6.1英寸2K分辨率双曲全视屏、S10+为6.4英寸2K分辨率双曲全视屏,S10e由于定位相比前两者更低,所以仍然使用1080P非双曲全视屏。(转郭霖大神的快讯)

介绍

蓝牙介绍:

     BLE蓝牙的兴起主要因为近年来可穿戴设备的流行。由于传统蓝牙功耗高不能满足可穿戴设备对于续航的要求。所以大部分可穿戴设备采用蓝牙4.0,即BLE蓝牙技术。BLE(Bluetooth Low Energy)低功耗蓝牙,主要特点是快速搜索,快速连接,超低功耗保持连接和数据传输。
缺点:BLE蓝牙数据传输速率低,特别是在安卓开发过程,BLE蓝牙一包数据最多为20字节,因此安卓系统下最好不要使用BLE蓝牙传输大量数据。

      之前我在创业公司工作的时候做过一款蓝牙开锁APP,当时刚拿到需求的时候各种懵逼,在网上百度了好几天都没有一点头目,因为都讲的牛头不对马嘴,换句话来说不是我想要的,根本满足不了我现在的需求,不知道从何入手,然后问身边各种蓝牙大牛以及技术大牛才稍微有一点头目,在这里给大家分享一下技术难点和各种坑,我直接上图:

流程大概是这样:我懒得画图了,用简单一句话来讲就是,房东分配钥匙-租客拿到权限-临时权限(各种权限....)-查看房子-下单

实战

在开始之前推荐几个蓝牙框架给大家学习:https://github.com/dingjikerbo/BluetoothKit,https://github.com/litesuits/android-lite-bluetoothLE

上面已经简单得介绍了一下项目的流程,现在直接上重点以第一个指令开始演示:

由于怕影响到公司业务,打上马赛克,你们可以根据自己的业务需求来实现功能

权限代码:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.nokelock.nokelockble">

    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
    <application
        android:name=".App"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service
            android:name="com.nokelock.service.BluetoothLeService"
            android:enabled="true" />

        <activity android:name=".LockManageActivity" android:screenOrientation="portrait"/>
    </application>

</manifest>

扫描部分:

private void startScanDevice() {
        if (isRefreshing) return;
        isRefreshing = true;
        BluetoothLeService bluetoothLeService = App.getInstance().getBluetoothLeService();
        if (bluetoothLeService != null) {
            final BluetoothAdapter bluetoothAdapter = bluetoothLeService.getmBluetoothAdapter();
            if (bluetoothAdapter == null) {
                isRefreshing = false;
                return;
            }
            tvRefresh.setText("正在扫描...");
            bluetoothDeviceList.clear();
            adapterList.clear();
            bleDeviceList.clear();
            bluetoothAdapter.startLeScan(new UUID[]{SampleGattAttributes.bltServerUUID}, leScanCallback);
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    tvRefresh.setText("扫描结束");
                    isRefreshing = false;
                    bluetoothAdapter.stopLeScan(leScanCallback);
                }
            }, 5000);

        } else {
            isRefreshing = false;
        }
    }

扫描回调:

这一块可以做处理比如我匹配到mac地址直接跳转到主页,你们可以做成那种扫描完以后放到adapter里面进行展示,这样更加直观明了。

private BluetoothAdapter.LeScanCallback leScanCallback = new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            if (!bluetoothDeviceList.contains(device)) {
                bluetoothDeviceList.add(device);
                bleDevice = new BleDevice(device, scanRecord, rssi);
                Log.e("TAG", "名字" + device.getName());
                Log.e("TAG", "MAC" + device.getAddress());
                //自动连接
                if ("F0:0F:26:5D:95:E3".equals(device.getAddress())) {
                    Log.e("TAG", "ok");

                    App.getInstance().getBluetoothLeService().connect("F0:0F:26:5D:95:E3");
                    Intent intent = new Intent(MainActivity.this, LockManageActivity.class);
                    intent.putExtra("name", device.getName());
                    intent.putExtra("address", device.getAddress());
                    startActivity(intent);

                }
                bleDeviceList.add(bleDevice);
            }
        }
    };
 private void initWidget() {
        comp = new SortComparator();
        ListView listView = (ListView) findViewById(R.id.recycler_view);
        tvRefresh = (TextView) findViewById(R.id.tv_refresh);
        Button btRefresh = (Button) findViewById(R.id.bt_refresh);
        adapter = new DeviceAdapter(this, adapterList);
        listView.setAdapter(adapter);
        new Thread(new DeviceThread()).start();
        listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                App.getInstance().getBluetoothLeService().getmBluetoothAdapter().stopLeScan(leScanCallback);
                isRefreshing = false;
                tvRefresh.setText("扫描结束");
                BleDevice bluetoothDevice = adapterList.get(position);
                String name = bluetoothDevice.getDevice().getName();
                if (TextUtils.isEmpty(name)) {
                    name = "null";
                }
                String address = bluetoothDevice.getDevice().getAddress();
                Intent intent = new Intent(MainActivity.this, LockManageActivity.class);
                intent.putExtra("name", name);
                intent.putExtra("address", address);
                startActivity(intent);

            }
        });
        btRefresh.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                refreshDevice();
            }
        });

    }

    private void refreshDevice() {
        requestPermission(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, 101);
    }

连接到蓝牙以后呢,就比较简单了,现在要做的是蓝牙锁的读和写:

/**
     * BLE通讯广播
     */
    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            switch (action) {
                case SampleGattAttributes.ACTION_GATT_CONNECTED:
                    //链接
                    deviceStatus.setText("连接状态:已连接");
                    progressDialog.dismiss();
                    break;
                case SampleGattAttributes.ACTION_GATT_DISCONNECTED:
                    //断开
                    progressDialog.dismiss();
                    deviceStatus.setText("连接状态:已断开");
                    count = 0;
                    openCount.setText("开锁次数:" + count);
                    break;
                case SampleGattAttributes.ACTION_GATT_SERVICES_DISCOVERED:
                    //发现服务

                    handler.sendEmptyMessageDelayed(0, 2000);
                    break;
                case SampleGattAttributes.ACTION_BLE_REAL_DATA:
                    parseData(intent.getStringExtra("data"));
                    break;
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    Log.e(LockManageActivity.class.getSimpleName(), "state_changed");
                    break;
            }
        }
    };
private void parseData(String value) {
        byte[] values = HexUtils.hexStringToBytes(value);
        byte[] x = new byte[16];
        System.arraycopy(values, 0, x, 0, 16);
        byte[] decrypt = BluetoothLeService.Decrypt(x, SampleGattAttributes.key);
        String decryptString = HexUtils.bytesToHexString(decrypt).toUpperCase();
        Log.e("TAG", "value:" + decryptString);
        if (decryptString.startsWith("0102")) {//token
            if (decrypt != null && decrypt.length == 16) {
                if (decrypt[0] == 0x01 && decrypt[1] == 0x02) {
                    token[0] = decrypt[3];
                    token[1] = decrypt[4];
                    token[2] = decrypt[5];
                    token[3] = decrypt[6];
                    CHIP_TYPE = decrypt[7];
                    DEV_TYPE = decrypt[10];
                    deviceVersion.setText("当前版本:" + Integer.parseInt(decryptString.substring(16, 18), 16) + "." + Integer.parseInt(decryptString.substring(18, 20), 16));
                    handler.sendEmptyMessageDelayed(1, 1000);
                }
            }
            handler.sendEmptyMessage(1);
        } else if (decryptString.startsWith("0402")) {//电量
            progressDialog.dismiss();
//            if (decryptString.startsWith("020201ff")) {
//                deviceCz.setText("获取电量失败");
//                Log.e("TAG", "获取电量失败");
//            } else {
            String battery = decryptString.substring(10, 12);
            deviceBattery.setText("当前电量:" + battery);
            Log.e("TAG", "电量字符串" + battery);
            Log.e("TAG", "当前电量" + Integer.parseInt(battery, 16));
//            }
        } else if (decryptString.startsWith("0202")) {//开锁
            if (decryptString.startsWith("02020101")) {
                deviceCz.setText("开锁失败");
            } else {
                count++;
                deviceCz.setText("开锁成功");
                openCount.setText("开锁次数:" + count);
            }
        }

基本一系列操作已经做完了,主要难点就是指令的读和写,然后在转成文档对应的编码就可以了,后面只需要按照文档里面的读和写操作就可以了,之前有过一篇蓝牙打印文章感兴趣请移步:https://blog.csdn.net/a214024475/article/details/52996047

 

练习

对照现有的蓝牙框架进行练习:https://github.com/dingjikerbo/BluetoothKit,https://github.com/litesuits/android-lite-bluetoothLE

猜你喜欢

转载自blog.csdn.net/a214024475/article/details/87874927
今日推荐