Android 硬件通讯之 蓝牙,USB,WIFI(一.蓝牙)

蓝牙

 

蓝牙通讯分为:经典蓝牙与低功耗蓝牙

现在所说的蓝牙设备,大部分都是在说4.0设备,ble也特指4.0设备。 在4.0之前重要的版本有2.1版本-基本速率/增强数据率(BR/EDR)和3.0 高速蓝牙版本,这些统称为经典蓝牙。

 

1.1 经典蓝牙

 

核心API:

BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

总结:

通过Android 系统提供API,进行蓝牙连接的前期工作准备(蓝牙开启,权限添加),外界设备扫描,设备连接(获取通讯BluetoothSocket),数据收发(IO流),资源释放 等等,完成Android系统与硬件设备通过蓝牙模式的数据收发功能。

 

1.1.1 权限检测:想要使用蓝牙必须给予应用相应的蓝牙权限

    //需要此权限来执行任何蓝牙通信,如请求一个连接、接受一个连接和传输数据。
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    //如果你想让你的应用启动设备发现或操纵蓝牙设置,必须申报bluetooth_admin许可
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

 

1.1.2 检测蓝牙是否开启:若没有开启,则跳转系统蓝牙功能相关选择开启蓝牙
 

        // If BT is not on, request that it be enabled.
        // setupChat() will then be called during onActivityResult
        if (!mBluetoothAdapter.isEnabled()) {
            Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
            // Otherwise, setup the chat session
        } else if (mChatService == null) {
            setupChat();
        }

1.1.3 设备扫描

 

   /**
     * Start device discover with the BluetoothAdapter
     */
    private void doDiscovery() {
        // If we're already discovering, stop it
        if (mBtAdapter.isDiscovering()) {
            mBtAdapter.cancelDiscovery();
        }

        // Request discover from BluetoothAdapter
        mBtAdapter.startDiscovery();
    }

蓝牙设备搜索的结果,Android系统会有对应的广播,我们可以在广播中对它进行接收并且进行相应的处理:

        // Register for broadcasts when a device is discovered
        IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
        this.registerReceiver(mReceiver, filter);

        // Register for broadcasts when discovery has finished
        filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        this.registerReceiver(mReceiver, filter);


/**
 * Create by dgs
 * Description  处理蓝牙状态
 **/
public class BluetoothStatuHandler implements IStatuHandler {

    public static final String ACTION_BT_CONNECTED = "BT_CONNECTED";
    public static final String ACTION_BT_DISCONNECTED = "BT_DISCONNECTED";




    @Override
    public void registAction(IntentFilter intentFilter) {
        //=======================bluetooth========================= start
        intentFilter.addAction(ACTION_BT_DISCONNECTED);
        intentFilter.addAction(ACTION_BT_CONNECTED);

        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        //=======================bluetooth========================= end
    }

    @Override
    public boolean onStatuChanged(String action, Context context, Intent intent) {
        if (ACTION_BT_CONNECTED.equals(action)) {
            Log.d("mBleCallback","蓝牙连接");
            onBluetoothConnected(intent);
        } else if (ACTION_BT_DISCONNECTED.equals(action)) {
            Log.d("mBleCallback","蓝牙断开了BT");
            onBluetoothDisconnected(intent);
        } else if (BluetoothDevice.ACTION_FOUND.equals(action)) {
            Log.d("mBleCallback","蓝牙查找");
            onBluetoothFound(intent);
        } else if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
            Log.d("mBleCallback","蓝牙断开了-------");
            onACLBluetoothDisconnected(intent);
        } else if (BluetoothAdapter.ACTION_STATE_CHANGED.equals(action)){
            if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF) {
                Log.d("mBleCallback","蓝牙断开了*******");
                onACLBluetoothDisconnected(intent);
            }
        } else {
            return false;
        }

        return true;
    }

    /**
     * 蓝牙连接上
     * @param intent
     */
    private void onBluetoothConnected(Intent intent) {
        ConnectedBluetoothEvent event = new ConnectedBluetoothEvent();
        event.setConnected(true);
        EventBusManager.postEvent(event);
        EventBus.getDefault().post(CollectionDevice.BLUETOOTH_CONNECTED);
    }

    /**
     * 蓝牙断开链接(来自自定义广播)
     * @param intent
     */
    private void onBluetoothDisconnected(Intent intent) {
        ConnectedBluetoothEvent event = new ConnectedBluetoothEvent();
        event.setConnected(false);
        EventBusManager.postEvent(event);

//        String msg = "蓝牙连接已断开,请退出目前的诊断系统,再重新进入需要诊断的电控系统,否则可能导致测试数据不准确或无法测试... ";

        EventBus.getDefault().post(CollectionDevice.BLUETOOTH_DISCONNECTED);
    }

    /**
     * 发现新蓝牙
     * @param intent
     */
    private void onBluetoothFound(Intent intent) {
        BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
        FoundBluetoothEvent foundBluetoothEvent = new FoundBluetoothEvent();
        Loger.printLog("MTFConnManager ", "  发现蓝牙设备  onBluetoothFound " + device.getAddress());
        foundBluetoothEvent.setBluetoothDevice(device);
        EventBusManager.postEvent(foundBluetoothEvent);
//
//        // 蓝牙已连上,不需再执行连接操作
//        if (ConnectManagement.IsBluetooth) {
//            return;
//        }
//
                Message msg = new Message();
                msg.what = 1;
                msg.obj = device;
                ConnectManagement.mBTHandler.handleMessage(msg);
//
//        L.e("蓝牙已匹配搜索:"+device.toString()+",我的:"+ConnectManagement.bluetoothAddress);
                ConnectManagement.bluetoothAddress="00:06:66:E5:3A:11";
//        if (device.toString().equalsIgnoreCase(ConnectManagement.bluetoothAddress)) {
//            L.e("蓝牙已匹配");
//            if (ConnectManagement.CheckDriver == false) {
//                new Thread(new Runnable() {
//                    @Override
//                    public void run() {
//                        ConnectManagement.myConnect(device);
//                    }
//                }).start();
//                L.i("广播处理函数:", "成功查找到设备!");
//            }
//        }
    }

    /**
     * 蓝牙断开链接(来自系统广播)
     * @param intent
     */
    private void onACLBluetoothDisconnected(Intent intent) {
        ConnectedBluetoothEvent event = new ConnectedBluetoothEvent();
        EventBusManager.postEvent(event);
        EventBus.getDefault().post( CollectionDevice.BLUETOOTH_DISCONNECTED);

//
//        // 可能出现在退出app立马重启,蓝牙自动连接时
//        if (ConnectManagement.isDiscovering(ConnectManagement.EnvEnum.BLUETOOTH_CLASSICAL)) {
//            return;
//        }
//
//        String msg = "蓝牙连接已断开 ";
//        disconnect(msg);
//        EventBus.getDefault().post(Constants.BLUETOOTH_DISCONNECTED);
    }
}

 

1.1.4 设备连接

根据广播中接受蓝牙设备对信息,并设置UUID后,执行连接方法

    private void connectToDevice(BluetoothDevice device) {
        UUID uuid = deviceInfo.getUuid()/*UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")*/;
        try {
            btSocket = device.createRfcommSocketToServiceRecord(uuid);
            if (isConnecting()) {
                scoketConnected();
            }
            return;
        } catch (Exception e) {
            e.printStackTrace();
            closeSocketConnect();
            try {
                btSocket = (BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(device, 1);
                if (isConnecting()) {
                    scoketConnected();
                }
            } catch (Exception e1) {
                closeSocketConnect();
            }
        }
    }

连接成功之后会获取到Socket对象,进而生成数据收发的数据流对象

    private void scoketConnected() throws Exception {
        btSocket.connect();
        mInputStream = btSocket.getInputStream();
        mOutputStream = btSocket.getOutputStream();
        connected();
    }

1.1.5 数据收发

发送数据

    @Override
    public boolean sendData(byte[] data) {
        boolean statu = false;
        if (mOutputStream != null) {
            try {
                mOutputStream.write(data);
                mOutputStream.flush();
                statu = true;
                onDataSended(data);
            } catch (Exception ex) {
                onSendDataError(ErrorCode.BLUETOOTH_WRITE_EXCEPTION, "数据写入时异常");
            }
        } else {
            onSendDataError(ErrorCode.BLUETOOTH_WRITE_CLOSED, "数据写入时数据流已经关闭,建议从新链接");
        }
        return statu;
    }

接收数据

数据接收通常启动一个无限循环执行的线程中,当连接断开时,才停止接收线程

    /**
     * 收取数据线程
     */
    private class RecivedDataThread extends Thread {

        @Override
        public void run() {
            while (isConnected()) {
                try {
                    byte data[] = readData();
                    if (data != null) {
                        onRecivedData(data);
                    }
                    Thread.sleep(1);
                } catch (Exception e) {
                    e.printStackTrace();
                    deviceConnected=false;
                    closeUsbPort();
                }

            }
            recivedDataThread = null;
        }
    }
    @Override
    protected byte[] readData() throws IOException, InterruptedException {
        if (mInputStream == null) {
            return null;
        }
        int length = mInputStream.available();
        if (length > 1) {
            byte[] temp = new byte[length];
            int result = mInputStream.read(temp);
            if (result > 0) {
                return temp;
            }
        }

        if (delayTime > 0) {
            Thread.sleep(delayTime);        
        }
        return null;

    }

 

1.1.6 设备断开

设备断开的时刻,意味着资源的释放,重置为未连接的状态,为了下一次连接做准备

    private void closeSocketConnect() {
        mOutputStream = null;
        try {
            if (null != btSocket) {
                if (btSocket.isConnected()) {
                    btSocket.close();
                    btSocket = null;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

 

1.2 低功耗蓝牙(蓝牙4.0/BLE 蓝牙)

在Android4.3系统之后,Android支持了蓝牙4.0。它最主要的特点是低功耗,普及率高。主要针对智能穿戴设备。

BLE蓝牙与经典蓝牙的区别是连接方式与数据收发的方式

核心API:

    private BluetoothManager mBluetoothManager = null;
    private BluetoothAdapter mAdapter = null;

    private BluetoothGattService mBTService = null;
    protected BluetoothGatt mBluetoothGatt = null;
    protected BluetoothGattCharacteristic mBTValueCharacteristic = null;

    @Override
    public void init(Context context) {
        mContext = context;
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
        }
        if (mAdapter == null) {
            mAdapter = mBluetoothManager.getAdapter();
        }
        if (!mAdapter.isEnabled()) {
            mAdapter.enable();
        }
        setScanDuring(Build.VERSION.SDK_INT >= 24 ? 6000 : 4000);
    }

1.2.1 设备连接方式

    @Override
    protected void scanDevice() {
        mAdapter.startLeScan(mDeviceFoundCallback);
    }


    private BluetoothAdapter.LeScanCallback mDeviceFoundCallback = new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
            Log.d("mDeviceFoundCallback","device:"+device.getAddress());

            if (deviceInfo != null && ("" + device.getAddress()).equals(deviceInfo.getMac())) {
                pauseDiscovery();
                connecting();
                _closeConn();
                Log.d("mDeviceFoundCallback", "停止扫描开始连接");

                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    mBluetoothGatt = device.connectGatt(mContext, true, mBleCallback, BluetoothDevice.TRANSPORT_LE);
                } else {
                    mBluetoothGatt = device.connectGatt(mContext, true, mBleCallback);
                }

                if (mBluetoothGatt == null) {
                    connectionError(-9, "蓝牙连接异常");
                    Log.d("mDeviceFoundCallback", "蓝牙连接异常");
                }

            }
        }
    };

1.2.2 设备连接方式

    private final BluetoothGattCallback mBleCallback = new BluetoothGattCallback() {

        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

            if ((!isConnected() && !isConnecting())
                    || deviceInfo == null
                    || gatt.getDevice() == null
                    || !(deviceInfo.getMac()+"").equals(gatt.getDevice().getAddress())) {
                return;
            }
            Log.d("mDeviceFoundCallback","newState:"+newState);
            if (newState == BluetoothProfile.STATE_CONNECTED && isConnecting()) {
                Log.d("mDeviceFoundCallback","蓝牙连上了");

                gatt.discoverServices();
            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Log.d("mDeviceFoundCallback","蓝牙断开了STATE_DISCONNECTED");
                if (isConnected()) {
                    _closeConn();
                    disconnected();
                }

            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS && gatt.getDevice().getAddress().equals(deviceInfo.getMac())) {
                initService();
            }
        }

        /**
         * 接收到数据
         * @param gatt
         * @param characteristic
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {

            byte[] data = characteristic.getValue();
//            Log.w("ble_data_h", ByteUtil.bytesToHexString(data));
            if (isConnected() && data != null && data.length > 0) {
                recivedBLEData(data);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            byte[] data = characteristic.getValue();
            if (isConnected() && data != null) {
                Log.w("ble_data_h----", ByteUtil.bytesToHexString(data));
                recivedBLEData(data);
            }
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {//写入成功
                onDataSended(characteristic.getValue());
            } else if (status == BluetoothGatt.GATT_FAILURE) {
                onSendDataError(status, "发送数据失败");
            } else if (status == BluetoothGatt.GATT_WRITE_NOT_PERMITTED) {
                onSendDataError(status, "没权限");
            }
        };

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        }
    };

 

下一章:Android 硬件通讯之 蓝牙,USB,WIFI(二.WIFI)

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值