安卓BLE藍牙開發入門

     最近做了有關安卓BLE藍牙開發的東西,所以在這裏記錄一下,是一些入門的知識。希望能幫到正需要學習安卓ble藍牙開發的同學。

 

  1.    介紹:安卓 4.3(API 18)爲 BLE 的核心功能提供平臺支持和 API,App 可以利用它來發現設 備、查詢服務和讀寫特性。相比傳統的藍牙,BLE 更顯著的特點是低功耗。這一優 點使 Android App 可以與具有低功耗要求的 BLE 設備通信,如近距離傳感器、心臟 速率監視器、健身設備等。

  2. 角色和責任 :
    以下是 Android 設備與 BLE 設備交互時的角色和責任: 
    中央 VS 外圍設備。 適用於 BLE 連接本身。中央設備掃描,尋找廣播;外 圍設備發出廣播。  GATT 服務端 VS GATT 客戶端。決定了兩個設備在建立連接後如何互相交 流。爲了方便理解,想象你有一個 Android 手機和一個用於活動跟蹤 BLE 設備,手機支 持中央角色,活動跟蹤器支持外圍(爲了建立 BLE 連接你需要注意兩件事,只支持 外圍設備的兩方或者只支持中央設備的兩方不能互相通信)。 當手機和運動追蹤器建立連接後,他們開始向另一方傳輸 GATT 數據。哪一方作爲 服務器取決於他們傳輸數據的種類。例如,如果運動追蹤器想向手機報告傳感器數 據,運動追蹤器是服務端。如果運動追蹤器更新來自手機的數據,手機會作爲服務 端。 

        代碼編寫:

  1.   權限部分:我開發過程中要了以下幾個權限,才能正常使用相應功能。有些運行時申請的權限請各位讀者自行申請權限。

                       

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

    2.   第一步:檢查設備是否支持BLE

private void check()//檢查設備是否支持BLE
    {
        if (this.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);        }

        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE))
        {
            Toast.makeText(this, "此設備不支持BLE功能", Toast.LENGTH_SHORT).show();
            finish();
        }
    }

 

   3.  第二步:開啓BLE藍牙

      mBluetoothAdapter 是藍牙設配器在整個藍牙開發中有重要功能,後續也會用到這個對象,所以這裏我們先初始化它。

 private void bleTurnOn()//開啓BLE藍牙
    {
        final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();
        // 確保藍牙在設備上可以開啓
        if (mBluetoothAdapter == null || !mBluetoothAdapter.isEnabled())
        {
            Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);

        }

    }

 

  4. 開啓/停止掃描藍牙設備:

     mBluetoothAdapter這裏充當了開啓/停止藍牙掃描的功能。

  private void scanLeDevice(final boolean enable)
    {
        if(enable){
            //時間超出預定掃描時間後,停止掃描。
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    if(mScanning) {
                        mScanning = false;
                        mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    }
                }
            },SCAN_PERIOD);
            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        }else{
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }

5.掃描的回調可以在這裏連接設備

  private BluetoothAdapter.LeScanCallback mLeScanCallback =new 
  BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord)
        {

            if(device.getName()!=null&&device.getName().equals(bleName)){
               connect(device);

            }
            Log.d("scanResult","掃描到了一個BLE設備"+device.getName());
            runOnUiThread(new Runnable() {
                @Override
                public void run(){
                   Toast.makeText(MainActivity.this,"掃描到"+device.getName(),Toast.LENGTH_SHORT).show();
                }
            });
        }
    };

6.我們在這裏看一下

mGattCallback

的代碼。這也是BLE藍牙開發的重要核心。

連接成功時,發現服務,寫入數據....,都會回調

mGattCallback

的相應方法。

private BluetoothGattCallback mGattCallback= new BluetoothGattCallback() {
    // 連接狀態改變的回調
    @Override
    public void onConnectionStateChange(BluetoothGatt gatt, int status,
        int newState) {
    
    };
 
    // 發現服務回調
    @Override
    public void onServicesDiscovered(BluetoothGatt gatt, int status) {

    };
 
    @Override
    public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
        // 由mBluetoothGatt.readRemoteRssi()調用得到,可不停刷新rssi信號強度
     
    }
 
    // 寫描述信息回調
    @Override
    public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor
        descriptor, int status) {
        
    };
 
    // 寫操作回調
    @Override
    public void onCharacteristicWrite(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
         
        }
    };
 
    // 讀操作回調
    @Override
    public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic, int status) {
        if (status == BluetoothGatt.GATT_SUCCESS) {
            
        }
    }
 
    // 數據改變回調(接收BLE設備發送的數據)
    @Override
    public void onCharacteristicChanged(BluetoothGatt gatt,BluetoothGattCharacteristic 
        characteristic) {
 
        };
    };
}

 7.連接設備

   這裏我們首先停止掃描藍牙,然後用device.connectGatt()連接藍牙設備。

 private void connect(BluetoothDevice device)
    {
        
        mBluetoothAdapter.stopLeScan(mLeScanCallback);
        mBluetoothGatt=device.connectGatt(MainActivity.this,false,mGattCallback);
        mScanning=false;


    }

8.掃描服務:我們可以在 

 public void onConnectionStateChange(BluetoothGatt gatt, int status,
        int newState) {
    
    };

裏先判斷連接是否成功然後使用 

 mBluetoothGatt.discoverServices();

掃描設備的服務。這裏給出一個例子代碼:

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

            if (newState == BluetoothProfile.STATE_CONNECTED) {//當前藍牙設備已經連接
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;//記錄連接狀態的
     
                runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        Toast.makeText(MainActivity.this,gatt.getDevice().getName()+"設備已經連接",Toast.LENGTH_SHORT).show();
                    }
                });
                mBluetoothGatt.discoverServices();
                Log.i("connected", "Connected to GATT server.");
                Log.i("serviceFinding", "Attempting to start service discovery:" + mBluetoothGatt.discoverServices());
            } 
            }
        }

 

掃描到服務回調onServicesDiscovered(...)方法。

這裏給出示例代碼:

 public void onServicesDiscovered(BluetoothGatt gatt, int status){
                if (status == BluetoothGatt.GATT_SUCCESS) {
                    List<BluetoothGattService> serviceList= gatt.getServices();//獲取服務列表
                 }
        }

 

9.針對一個服務我們可以獲取它的特徵列表。然後對相應特徵進行讀寫操作。

          List<BluetoothGattCharacteristic> mlist=service.getCharacteristics();

 10.讀取特徵數據

mBluetoothGatt.readCharacteristic(Characteristic a);
//使用mBluetoothGatt的readCharacteristic()進行讀取即可。

11.寫入特徵數據

    private  void writeData(byte hexData[], BluetoothGattCharacteristic characteristic){

        characteristic.setValue(hexData);//先設置值,再寫入。數據是比特數組。
        mBluetoothGatt.writeCharacteristic(characteristic);
 

    }

12.注意要想寫入之後收到BLE設備的通知應該設置接受通知。示例代碼如下:

 public void setCharacteristicNotification() {


        BluetoothGattDescriptor descriptor = readCharacteristic.getDescriptors().get(0);
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        mBluetoothGatt.writeDescriptor(descriptor);
        mBluetoothGatt.setCharacteristicNotification(readCharacteristic, true);



    }

13.備註:

所有關於FTPClient的操作都要異步執行,否則就會出現錯誤。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章