zoukankan      html  css  js  c++  java
  • Android 4.4.2上与BLE 蓝牙锁设备的通讯

    Android从4.3(Api level 18)开始支持BLE的开发,本文记录了Android 4.4.2设备与BLE设备通讯的流程。

    权限需求:
    <uses-permission android:name="android.permission.BLUETOOTH" />
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

    步骤:
    1.获取蓝牙服务
    BluetoothManager btManager= (BluetoothManager) this.getSystemService(Context.BLUETOOTH_SERVICE);
    2.获取蓝牙设备管理器(适配器)
    BluetoothAdapter mBluetoothAdapter = btManager.getAdapter();
    3.判断设备是否支持BLE蓝牙通讯,支持则判断蓝牙是否已开启,未开启蓝牙的设置开启。
    if (mBluetoothAdapter != null && (!mBluetoothAdapter.isEnabled())){
    mBluetoothAdapter.enable();//打开蓝牙
    }
    4.扫描当前附近的蓝牙BLE设备(这个操作比较耗电,要适时地停止)
    5.停止设备扫描
    6.与指定BLE设备建立Gatt连接
    7.在连接成功后,设置扫描BLE设备支持的service和characteristic,并设置。这里需要注意,需要开启通知的,需要设置相应描述符。
    8.读写操作
    9.断开Gatt连接
    10.关闭Gatt连接

    在开发过程中,遇到的主要问题是onCharacteristicWrite失败回调,这个可能跟低功耗蓝牙外设有关,需要断开并关闭Gatt连接重新建立

     下面是主要参考代码

    package com.rollup.bluetoothlock;
    
    import java.lang.ref.WeakReference;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Timer;
    import java.util.TimerTask;
    import java.util.UUID;
    
    import com.android.peephole.MyApplication;
    import com.rollup.bluetoothlock.MyLog;
    import com.rollup.bluetoothlock.Utils;
    import com.rollup.bluetoothlock.Value;
    
    
    
    import android.R.integer;
    import android.bluetooth.BluetoothAdapter;
    import android.bluetooth.BluetoothAdapter.LeScanCallback;
    import android.bluetooth.BluetoothDevice;
    import android.bluetooth.BluetoothGatt;
    import android.bluetooth.BluetoothGattCallback;
    import android.bluetooth.BluetoothGattCharacteristic;
    import android.bluetooth.BluetoothGattDescriptor;
    import android.bluetooth.BluetoothGattService;
    import android.bluetooth.BluetoothManager;
    import android.bluetooth.BluetoothProfile;
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.os.Handler;
    import android.os.Message;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class BleManager {
        private static final String TAG = "BleManager";
        public static final int ERROR_NO_ERROR = 0;//成功
        public static final int ERROR_BTDEVICE_EXC_FAIL = 1;// 蓝牙锁端执行错误
        public static final int ERROR_PSD_ERROR = 2; // 钥匙错误
        public static final int ERROR_CONNECT_FAIL = 3;
        public static final int ERROR_DEFAULT = 4;
        public static final int ERROR_NOT_FOUND_DEVICE = 5;// 未扫描到指定编码的锁
        public static final int ERROR_HAVE_CONNECTED = 6;//上次连接未执行完毕
        public static final int ERROR_NO_DEVICE = 7;//设备没有初始化
        public static final int ERROR_CREATE_FAIL = 8;
    
        private static final int STOP_LESCAN = 1;
        private final int OVER_TIMER = 60 * 1000;// 扫描超时时间
    
        private Context mContext = null;
        private BluetoothAdapter mBluetoothAdapter = null;
        private BluetoothManager mBluetoothManager = null;
        public BluetoothDevice mBluetoothDevice = null;
        private BluetoothGatt mBluetoothGatt;
        private static boolean isScanning = false;
        private BluetoothGattCharacteristic writeCharacteristic = null;
        private static boolean isConnectToDevice = false;
        private String btName = null;
        private String psd = null;
        private boolean hasExcuteOpenDoor = false;// 开门命令已执行
        private byte[] devceKey;
    
        private static boolean haveRetry = false;
        private static BleManager instance = null;
        private MyHandler mHandler = null;
    
        public static long lastOpendoorTime = 0;
    
        private OnBleScanOpenDoorCallback openDoorCallback = null;
    
        public interface OnBleScanOpenDoorCallback {
            public void openDoorSuc();
            public void openDoorFail(int error);
        }
    
        private BleManager(Context context, String btName, String psd) {
            this.mContext = context;
            initBluetooth();
            if (mBluetoothManager == null) {
                MyLog.e(TAG, "Unable to initialize BluetoothManager.");
                return;
            }
            this.btName = btName;
            this.psd = psd;
            devceKey = new byte[16];
        }
    
        public static BleManager getInstance(String btName, String psd) {
            if (instance == null) {
                instance = new BleManager(MyApplication.getMyApplication(), btName,
                        psd);
            } else {
                instance.setBTinfo(btName, psd);
            }
            return instance;
        }
    
        private void setBTinfo(String name, String psd) {
            this.btName = name;
            this.psd = psd;
        }
    
        private void initBluetooth() {
            mHandler = new MyHandler(this);
            mBluetoothManager = (BluetoothManager) mContext
                    .getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager != null) {
                mBluetoothAdapter = mBluetoothManager.getAdapter();
                if (mBluetoothAdapter != null) {
                    if (!mBluetoothAdapter.isEnabled()) {
                        mBluetoothAdapter.enable(); // 打开蓝牙
                    }
                }
            }
        }
        
        /**
         * 是否空闲可用
         * @return
         */
        public static boolean isFree(){
            return (!isConnectToDevice)&&(!isScanning);
        }
    
        public void startLeScan(boolean autoConnect) {
            if (mBluetoothAdapter == null) {
                return;
            }
            if (btName == null || btName.length() == 0) {
                return;
            }
    
            if (isScanning) {
                return;
            }
            isScanning = true;
    
            if (autoConnect) {
                mBluetoothAdapter.startLeScan(mLeScanCallback2);
            } else {
                mBluetoothAdapter.startLeScan(mLeScanCallback); // 此mLeScanCallback为回调函数
            }
    
            mHandler.sendEmptyMessageDelayed(STOP_LESCAN, OVER_TIMER); // 这个搜索30秒,如果搜索不到则停止搜索
        }
    
        private void stopLeScan() {
            if (mHandler != null && mHandler.hasMessages(STOP_LESCAN)) {
                mHandler.removeMessages(STOP_LESCAN);
            }
            if (mBluetoothAdapter == null) {
                return;
            }
    
            if (!isScanning) {
                return;
            }
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
            mBluetoothAdapter.stopLeScan(mLeScanCallback2);
            isScanning = false;
        }
    
        private LeScanCallback mLeScanCallback = new LeScanCallback() {
            @Override
            public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
                MyLog.i(TAG, "onLeScan() DeviceName------>" + device.getName()); // 在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
                if (device.getAddress() != null) {
                    if (device.getName().toLowerCase().replace("_", "")
                            .contentEquals(btName.toLowerCase().replace(" ", ""))) {
                        mBluetoothDevice = device;
                        stopLeScan();
                    }
                }
            }
        };
    
        private LeScanCallback mLeScanCallback2 = new LeScanCallback() {
            @Override
            public void onLeScan(BluetoothDevice device, int arg1, byte[] arg2) {
                MyLog.i(TAG, "onLeScan() DeviceName------>" + device.getName()); // 在这里可通过device这个对象来获取到搜索到的ble设备名称和一些相关信息
                if (device.getAddress() != null) {
                    if (device.getName().toLowerCase().replace("_", "")
                            .contentEquals(btName.toLowerCase().replace(" ", ""))) {
                        mBluetoothDevice = device;
                        stopLeScan();
                        connect();
                    }
                }
            }
        };
    
        private static class MyHandler extends Handler {
            WeakReference<BleManager> wf = null;
    
            public MyHandler(BleManager manager) {
                // TODO Auto-generated constructor stub
                wf = new WeakReference<BleManager>(manager);
            }
    
            @Override
            public void handleMessage(Message msg) {
                // TODO Auto-generated method stub
                switch (msg.what) {
                case STOP_LESCAN:
                    MyLog.i(TAG,  "MyHandler handleMessage STOP_LESCAN");
                    if (wf.get()!=null){
                        wf.get().stopLeScan();
                    }
                    MyLog.i(TAG, "release(), Scan time is up");
                    break;
                }
            }
        }
    
        public int connect() {
            if (mBluetoothDevice == null) {
                MyLog.i(TAG, "BluetoothDevice is null.");
                return ERROR_NO_DEVICE;
            }
            
            if(isConnectToDevice){
                MyLog.i(TAG, "Have connected to device");
                return ERROR_HAVE_CONNECTED;
            }
            isConnectToDevice = true;
            hasExcuteOpenDoor = false;
    
            // 两个设备通过BLE通信,首先需要建立GATT连接。这里我们讲的是Android设备作为client端,连接GATT Server
    
            mBluetoothGatt = mBluetoothDevice.connectGatt(mContext, false,
                    mGattCallback); // mGattCallback为回调接口
    
            if (mBluetoothGatt != null) {
    
                if (mBluetoothGatt.connect()) {
                    MyLog.d(TAG, "Connect succeed.");
                    return ERROR_NO_ERROR;
                } else {
                    MyLog.d(TAG, "Connect fail.");
                    return ERROR_CONNECT_FAIL;
                }
            } else {
                MyLog.d(TAG, "BluetoothGatt null.");
                return ERROR_CREATE_FAIL;
            }
        }
    
        private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
            @Override
            public void onConnectionStateChange(BluetoothGatt gatt, int status,
                    int newState) {
                if (newState == BluetoothProfile.STATE_CONNECTED) {
                    isConnectToDevice = true;
                    gatt.discoverServices(); // 执行到这里其实蓝牙已经连接成功了
                    MyLog.i(TAG, "Connected to GATT server.");
                } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                    if (!hasExcuteOpenDoor) {
                        disconnect();
                        retryUnlock();
                        if (!haveRetry) {
                            //已失败重试过
                            if (openDoorCallback != null) {
                                openDoorCallback.openDoorFail(ERROR_CONNECT_FAIL);
                            }
                        } 
                    } else {
                        MyLog.i(TAG, "BluetoothProfile.STATE_DISCONNECTED  hasExcuteOpenDoor=TRUE");
                        haveRetry = false;
                        disconnect();
                    }
                    MyLog.i(TAG, "BluetoothProfile.STATE_DISCONNECTED --release()");
                }
            }
    
            public void onServicesDiscovered(BluetoothGatt gatt, int status) {
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    MyLog.i(TAG, "onServicesDiscovered");
                    List<BluetoothGattService> services = gatt.getServices();
                    for (int i = 0; i < services.size(); i++) {
                        MyLog.i(TAG, "[Service " + i + "] uuid:"
                                + services.get(i).getUuid());
                        if (services.get(i).getUuid().equals(Value.uuid)) {
                            List<BluetoothGattCharacteristic> characteristics = services
                                    .get(i).getCharacteristics();
                            for (int j = 0; j < characteristics.size(); j++) {
                                MyLog.i(TAG, "[Characteristic]"
                                        + characteristics.get(j).getUuid());
                                if (characteristics.get(j).getUuid()
                                        .equals(Value.CHARACTERISTIC_READ)) {
                                    boolean res = mBluetoothGatt
                                            .setCharacteristicNotification(
                                                    characteristics.get(j), true);
                                    // 打开通知描述
                                    for (BluetoothGattDescriptor descriptor : characteristics
                                            .get(j).getDescriptors()) {
                                        descriptor
                                                .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                                        gatt.writeDescriptor(descriptor);
                                        MyLog.i(TAG,
                                                "Characteristic set notification is Success!");
                                    }
                                    MyLog.i(TAG,
                                            "onServicesDiscovered setCharacteristicNotification result="
                                                    + res);
                                    break;
                                }
                            }
                            characteristics = null;
                        }
                    }
    
                    for (int i = 0; i < services.size(); i++) {
                        MyLog.i(TAG, "[Service " + i + "] uuid:"
                                + services.get(i).getUuid());
                        if (services.get(i).getUuid().equals(Value.uuid)) {
                            List<BluetoothGattCharacteristic> characteristics = services
                                    .get(i).getCharacteristics();
                            for (int j = 0; j < characteristics.size(); j++) {
                                MyLog.i(TAG, "[Characteristic]"
                                        + characteristics.get(j).getUuid());
                                if (characteristics.get(j).getUuid()
                                        .equals(Value.CHARACTERISTIC_WRITE)) {
                                    writeCharacteristic = characteristics.get(j);
                                    final int charaProp = characteristics.get(j)
                                            .getProperties();
                                    // 如果该char可写
                                    if ((charaProp | BluetoothGattCharacteristic.PROPERTY_READ) > 0) {
                                        byte[] value = new byte[] { 0x01, 0x00,
                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                                0x00, 0x00, 0x00 };
                                        characteristics.get(j).setValue(value);
                                        writeCharacteristic
                                                .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                                        mBluetoothGatt
                                                .writeCharacteristic(characteristics
                                                        .get(j));
                                        value = null;
                                    }
                                    break;
                                }
                            }
                            characteristics = null;
                        }
                    }
                    services = null;
                } else {
                    MyLog.i(TAG, "onServicesDiscovered status------>" + status);
                }
            }
    
            @Override
            public void onCharacteristicRead(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic, int status) {
                MyLog.i(TAG,
                        "onCharacteristicRead------>"
                                + Utils.bytesToHexString(characteristic.getValue()));
    
            }
    
            
    
            @Override
            public void onCharacteristicChanged(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic) {
                MyLog.i(TAG,
                        "onCharacteristicChanged------>"
                                + Utils.bytesToHexString(characteristic.getValue()));
                MyLog.i(TAG, "UUID------>" + characteristic.getUuid().toString());
    
                if (Value.CHARACTERISTIC_READ.equals(characteristic.getUuid())) {
                    byte[] value = characteristic.getValue();
                    if ((value[0] & 0xFF) == 0x81) {
                        for (int i = 0; i < 16; i++) {
                            devceKey[i] = value[i + 1];
                        }
                        // MyLog.i(TAG, "加密秘钥为:"+Utils.bytesToHexString(devceKey));
                        if (writeCharacteristic != null) {
                            byte[] cmd = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                    0x00, 0x00, 0x00 };
                            if (psd.length() == 8) {
                                int j = 0;
                                for (int i = 0; i < 4; i++) {
                                    cmd[5 + i] = (byte) (((((Integer.valueOf(psd
                                            .charAt(j)) - 48) << 4) & (0xF0)) + ((Integer
                                            .valueOf(psd.charAt(j + 1)) - 48) & 0x0F)) & 0xFF);
                                    MyLog.i(TAG, "cmd" + (9 + i) + "=" + cmd[9 + i]);
                                    j = j + 2;
                                }
                            }
                            byte[] cmd_encrypt = Utils.enCode(devceKey, cmd);
                            if (cmd_encrypt != null) {
                                byte[] request = new byte[17];
                                request[0] = 0x03;
                                for (int i = 1; i < (cmd_encrypt.length < request.length ? cmd_encrypt.length
                                        : request.length); i++) {
                                    request[i] = cmd_encrypt[i - 1];
                                }
                                writeCharacteristic.setValue(request);
                                writeCharacteristic
                                        .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
                                // MyLog.i(TAG,
                                // "发送开锁命令:"+Utils.bytesToHexString(request));
                                mBluetoothGatt
                                        .writeCharacteristic(writeCharacteristic);
                                request = null;
                            }
                            cmd_encrypt  = null;
                            cmd = null;
                        }
    
                    } else if ((value[0] & 0xFF) == 0x83) {
                        byte[] res = new byte[16];
                        for (int i = 0; i < 16; i++) {
                            res[i] = value[i + 1];
                        }
                        // MyLog.i(TAG, "解密秘钥为:"+Utils.bytesToHexString(devceKey));
                        // MyLog.i(TAG, "待解密数据为:"+Utils.bytesToHexString(res));
                        byte[] decode_res = Utils.deCode(devceKey, res);
                        hasExcuteOpenDoor = true;
                        if (decode_res != null) {
                            MyLog.i(TAG,
                                    "获取到蓝牙开锁返回数据:"
                                            + Utils.bytesToHexString(decode_res));
                            if ((decode_res[0] & 0xFF) == 0x01) {
                                if ((decode_res[1] & 0xFF) == 0x00) {
                                    MyLog.i(TAG, "开锁成功");
    
                                    if (openDoorCallback != null) {
                                        openDoorCallback.openDoorSuc();
                                    }
                                    lastOpendoorTime = System.currentTimeMillis();
                                } else if ((decode_res[1] & 0xFF) == 0x01) {
                                    MyLog.i(TAG, "开锁失败:命令执行失败");
                                    if (openDoorCallback != null) {
                                        openDoorCallback
                                                .openDoorFail(ERROR_BTDEVICE_EXC_FAIL);
                                    }
                                } else if ((decode_res[1] & 0xFF) == 0x02) {
                                    MyLog.i(TAG, "开锁失败:密钥解密失败,无效用户密钥");
                                    if (openDoorCallback != null) {
                                        openDoorCallback
                                                .openDoorFail(ERROR_PSD_ERROR);
                                    }
                                } else {
                                    MyLog.e(TAG, "开锁返回异常");
                                    if (openDoorCallback != null) {
                                        openDoorCallback
                                                .openDoorFail(ERROR_DEFAULT);
                                    }
                                }
    
                                new Timer().schedule(new TimerTask() {
    
                                    @Override
                                    public void run() {
                                        // TODO Auto-generated method stub
                                        sendEndCmd();
                                    }
                                }, 500);
    
                            } else {
                                MyLog.e(TAG, "开锁返回动作标志位异常,此时锁还会再次返回其他数据");
                                if (openDoorCallback != null) {
                                    openDoorCallback.openDoorFail(ERROR_DEFAULT);
                                }
                            }
    
                        } else {
                            MyLog.e(TAG, "蓝牙开锁数据获取失败");
                            if (openDoorCallback != null) {
                                openDoorCallback.openDoorFail(ERROR_DEFAULT);
                            }
    //                        disconnect(true);
                        }
                        decode_res = null;
                        res = null;
                    } else {
                        MyLog.e(TAG, " value[0] =  " + value[0]
                                + " ===release()    11111111");
    //                    disconnect(true);
                    }
                    value = null;
                }
            }
    
            // 接受Characteristic被写的通知,收到蓝牙模块的数据后会触发onCharacteristicWrite
            @Override
            public void onCharacteristicWrite(BluetoothGatt gatt,
                    BluetoothGattCharacteristic characteristic, int status) {
                MyLog.i(TAG,
                        "onCharacteristicWrite status = " + status
                                + ",onCharacteristicWrite------>"
                                + Utils.bytesToHexString(characteristic.getValue()));
                if (status != 0) {
    //                disconnect(true);
                }
            }
        };
        
        private void sendEndCmd() {
            if (writeCharacteristic != null) {
                byte[] cmd = new byte[] { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                        0x00 };
                byte[] cmd_encrypt = Utils.enCode(devceKey, cmd);
                if (cmd_encrypt != null) {
                    byte[] request = new byte[17];
                    request[0] = 0x08;
                    for (int i = 1; i < (cmd_encrypt.length < request.length ? cmd_encrypt.length
                            : request.length); i++) {
                        request[i] = cmd_encrypt[i - 1];
                    }
                    writeCharacteristic.setValue(request);
                    writeCharacteristic
                            .setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
                    mBluetoothGatt.writeCharacteristic(writeCharacteristic);
                    request = null;
                }
                cmd = null;
                cmd_encrypt = null;
            }
            // release();
        }
    
        private void retryUnlock() {
            if (!haveRetry) {
                haveRetry = true;
                connect();
            } else {
                haveRetry = false;
                MyLog.i(TAG, "retryUnlock  haveRetry");
            }
        }
    
        public void setOpenDoorCallback(OnBleScanOpenDoorCallback callback) {
            openDoorCallback = callback;
        }
        
        public synchronized void disconnect() {
            MyLog.i(TAG, "disconnect");
            if (mBluetoothGatt != null) {
                mBluetoothGatt.disconnect();
                mBluetoothGatt.close();
                mBluetoothGatt = null;
            }
            isConnectToDevice = false;
        }
    }
    View Code
    package com.example.common;
    
    import java.security.SecureRandom;
    
    import javax.crypto.Cipher;
    import javax.crypto.KeyGenerator;
    import javax.crypto.SecretKey;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    
    public class Utils {
    
         /** Convert byte[] to hex string.这里我们可以将byte转换成int,然后利用Integer.toHexString(int)来转换成16进制字符串。  
         * @param src byte[] data  
         * @return hex string  
         */     
        public static String bytesToHexString(byte[] src){  
            StringBuilder stringBuilder = new StringBuilder("");  
            if (src == null || src.length <= 0) {  
                return null;  
            }  
            for (int i = 0; i < src.length; i++) {  
                int v = src[i] & 0xFF;  
                String hv = Integer.toHexString(v);  
                if (hv.length() < 2) {  
                    stringBuilder.append(0);  
                }  
                stringBuilder.append(hv);  
            }  
            return stringBuilder.toString();  
        }  
        /** 
         * Convert hex string to byte[] 
         * @param hexString the hex string 
         * @return byte[] 
         */  
        public static byte[] hexStringToBytes(String hexString) {  
            if (hexString == null || hexString.equals("")) {  
                return null;  
            }  
            hexString = hexString.toUpperCase();  
            int length = hexString.length() / 2;  
            char[] hexChars = hexString.toCharArray();  
            byte[] d = new byte[length];  
            for (int i = 0; i < length; i++) {  
                int pos = i * 2;  
                d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));  
            }  
            return d;  
        }  
        
        /** 
         * Convert char to byte 
         * @param c char 
         * @return byte 
         */  
         private static byte charToByte(char c) {  
            return (byte) "0123456789ABCDEF".indexOf(c);  
        }  
    
        //将指定byte数组以16进制的形式打印到控制台  
        public static void printHexString( byte[] b) {    
           for (int i = 0; i < b.length; i++) {   
             String hex = Integer.toHexString(b[i] & 0xFF);   
             if (hex.length() == 1) {   
               hex = '0' + hex;   
             }   
             System.out.print(hex.toUpperCase() );   
           }   
          
        }  
        
        /**
         * 真正的加密过程
         * 1.通过密钥得到一个密钥专用的对象SecretKeySpec
         * 2.Cipher 加密算法,加密模式和填充方式三部分或指定加密算 (可以只用写算法然后用默认的其他方式)Cipher.getInstance("AES");
         * @param key
         * @param src
         * @return
         * @throws Exception
         */
        public static byte[] enCode(byte[] key, byte[] src) {
            try {
                SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding"); 
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                byte[] encrypted = cipher.doFinal(src);
                return encrypted;
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                return null;
            }
            
        }
        
         /**
         * 解密
         * @param view
         */
        public static byte[] deCode(byte[] key, byte[] src){ 
            try {
                //获取AESkey
                SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
                Cipher cipher = Cipher.getInstance("AES/ECB/ZeroBytePadding"); //AES/ECB/ZeroBytePadding
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
                byte[] decrypted = cipher.doFinal(src);
                byte[] result;
                if (decrypted.length<16){
                    result = new byte[]{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
                    for (int i=0; i<decrypted.length; i++){
                        result[i]=decrypted[i];
                    }
                }else{
                    result = decrypted;
                }
                return result;
            } catch (Exception e) {
                // TODO: handle exception
                e.printStackTrace();
                return null;
            }
        }
    }
    View Code
    package com.example.common;
    
    import java.util.UUID;
    
    public class Value {
        public static final String BLE_LOCK_SP_NAME = "BleLockConfig";
        public static final String KEY_BLE_LOCK_ID = "kEY_BLE_LOCK_ID";
        public static final String KEY_BLE_LOCK_KEY = "KEY_BLE_LOCK_KEY";
        
        public final static UUID uuid = UUID.fromString("0000ff12-0000-1000-8000-00805f9b34fb");
        public final static UUID CHARACTERISTIC_WRITE = UUID.fromString("0000ff01-0000-1000-8000-00805f9b34fb");//主机BLE发送给BLE模块数据使用
        public final static UUID CHARACTERISTIC_READ = UUID.fromString("0000ff04-0000-1000-8000-00805f9b34fb");//BLE模块发送给主机BLE数据使用,NOTIFY功能发送,前提是双方连接上后,需要主机BLE主动打开BLE模块的UUID=0XFF04(NOTIFY)功能。
    }
    View Code
    package com.example.bluetoothdemo;
    
    import com.example.common.BleManager;
    import com.example.common.Utils;
    import com.example.common.BleManager.OnBleScanOpenDoorCallback;
    
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.content.Context;
    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    import android.os.Bundle;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.view.Window;
    import android.view.inputmethod.InputMethodManager;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.RelativeLayout;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener, OnBleScanOpenDoorCallback{
        
        private final String TAG = "MainActivity";
        private final String KEY_BLE_LOCK_ID = "kEY_BLE_LOCK_ID";
        private final String KEY_BLE_LOCK_KEY = "KEY_BLE_LOCK_KEY";
        
        private BleManager mBleManager = null;
        
        private RelativeLayout relativeLayout = null;
        private EditText idEditText = null;
        private EditText psdEditText = null;
        private Button scanButton = null;
        private Button connectButton = null;
        private ProgressDialog progressDialog = null;
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            getWindow().requestFeature(Window.FEATURE_NO_TITLE);
            setContentView(R.layout.activity_main);
            
            relativeLayout = (RelativeLayout) findViewById(R.id.relativelayout);
            scanButton = (Button) findViewById(R.id.button_scan);    
            connectButton = (Button) findViewById(R.id.button_connect);
            idEditText = (EditText) findViewById(R.id.edittext_lock_id);
            psdEditText = (EditText) findViewById(R.id.edittext_psd);
            progressDialog = new ProgressDialog(this);
            progressDialog.setMessage(getString(R.string.waiting));
            
            SharedPreferences sp = getPreferences(MODE_PRIVATE);
            String bleName = sp.getString(KEY_BLE_LOCK_ID, "ZY121711240013");
            String blePsd = sp.getString(KEY_BLE_LOCK_KEY, "12345678");
            idEditText.setText(bleName);
            psdEditText.setText(blePsd);
            
            relativeLayout.setOnClickListener(this);
            scanButton.setOnClickListener(this);        
            connectButton.setOnClickListener(this);
            
            mBleManager = BleManager.getInstance(bleName, blePsd);  //这个this是一个上下文,只要在上面的BleManager工具类定义一个有参数就好
            mBleManager.setOpenDoorCallback(this);
        }
        
        @Override
        protected void onResume() {
            // TODO Auto-generated method stub
            super.onResume();
        }
        
        @Override
        protected void onPause() {
            // TODO Auto-generated method stub
            super.onPause();
            SharedPreferences sp = getPreferences(MODE_PRIVATE);
            Editor editable = sp.edit();
            editable.putString(KEY_BLE_LOCK_ID, idEditText.getText().toString().trim());
            editable.putString(KEY_BLE_LOCK_KEY, psdEditText.getText().toString().trim());
            editable.commit();
        }
    
        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub
            switch (v.getId()) {
            case R.id.button_scan:
                break;
            case R.id.relativelayout:
                InputMethodManager m = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                m .hideSoftInputFromWindow(relativeLayout.getWindowToken(), 0);//比如EditView
                break;
            case R.id.button_connect:
                progressDialog.show();
                int res = mBleManager.connect();
                
                if (res == BleManager.ERROR_NO_ERROR){
                }else if (res == BleManager.ERROR_HAVE_CONNECTED){
                    //已经连接不能再次连
                    progressDialog.dismiss();
                }else{
                    mBleManager.startLeScan(true);
                }
    
                break;
            
            default:            
                break;
            }
        }
    
        @Override
        protected void onDestroy() {
            // TODO Auto-generated method stub
            
            if (mBleManager != null){
                mBleManager.setOpenDoorCallback(null);
                mBleManager.disconnect();
                mBleManager = null;
            }
            super.onDestroy();
        }
    
    
        @Override
        public void openDoorSuc() {
            // TODO Auto-generated method stub
            runOnUiThread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    if (progressDialog.isShowing()){
                        progressDialog.dismiss();
                    }
                    Toast.makeText(MainActivity.this, getString(R.string.open_door_suc), Toast.LENGTH_LONG).show();
                }
            });
            
        }
    
        @Override
        public void openDoorFail(final int error) {
            // TODO Auto-generated method stub
            runOnUiThread(new Runnable() {
                
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    if (progressDialog.isShowing()){
                        progressDialog.dismiss();
                    }
                    int resId  = R.string.error_default;
                    if (error==BleManager.ERROR_BTDEVICE_EXC_FAIL){
                        resId = R.string.error_btdevice_exc_fail;
                    }else if (error == BleManager.ERROR_CONNECT_FAIL){
                        resId = R.string.error_not_connect;
                    }else if (error == BleManager.ERROR_PSD_ERROR){
                        resId = R.string.error_psd_error;
                    }else if (error == BleManager.ERROR_NOT_FOUND_DEVICE){
                        resId = R.string.error_device_not_found;
                    }
                    Toast.makeText(MainActivity.this, resId, Toast.LENGTH_LONG).show();
                }
            });
            
        }
    }
    View Code
  • 相关阅读:
    Longest Subsequence CodeForces
    Alyona and towers CodeForces
    Electric Charges CodeForces
    Array GCD CodeForces
    笔记(模拟)
    城堡 (spfa+cheng)
    YOU ARE MY SUNSHINE
    AC日记——潜伏者 洛谷 P1071 (模拟)
    AC日记——神奇的幻方 洛谷 P2615(大模拟)
    AC日记——机器翻译 洛谷 P1540
  • 原文地址:https://www.cnblogs.com/suxiaoqi/p/8023588.html
Copyright © 2011-2022 走看看