1. 程式人生 > >Anroid BLE藍芽(手機分別作為中心裝置和外圍裝置)

Anroid BLE藍芽(手機分別作為中心裝置和外圍裝置)

        藍芽是一種短距的無線通訊技術,可實現固定裝置、移動裝置之間的資料交換。一般將藍芽3.0之前的BR/EDR藍芽稱為傳統藍芽,而將藍芽4.0規範下的LE藍芽稱為低功耗藍芽。

BLE藍芽模組主要應用領域

    1、移動擴充套件裝置

    2、汽車電子裝置

    3、健康醫療用品:心跳帶、血壓計等

    4、定位應用:室內定位、井下定位等

    5、近距離資料採集:無線抄表、無線遙測等

    6、資料傳輸:智慧家居室內控制、藍芽調光、印表機等

   手機作為中心裝置連線外圍裝置 藍芽的操作流程

        1.宣告藍芽許可權               

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

在 Android 6.0 及以上,還需要開啟位置許可權。如果應用沒有位置許可權,藍芽掃描功能不能使用

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

    2.判斷裝置是否支援BLE藍芽

public boolean isSupportBle() {
    return mContext.getApplicationContext()
            .getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE);
}

   3.初始化藍芽

public BleBluetooth(Context context) {
    this
.context = context = context.getApplicationContext(); bluetoothManager = (BluetoothManager) context .getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); }

4.是否開啟藍芽

public boolean isBlueEnable() {
    return bluetoothAdapter.isEnabled();
}

5.開啟藍芽

public void enableBluetooth() {
    bluetoothAdapter.enable();
}

6.掃描藍芽

    6.0以上要動態設定許可權

public void scanDevice(BluetoothAdapter.LeScanCallback callback, Activity activity) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // Android M Permission check
if (activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) !=
                PackageManager.PERMISSION_GRANTED) {
            //TODO 許可權適配 終止
activity.requestPermissions(new String[]{Manifest.permission
                    .ACCESS_COARSE_LOCATION}, PERMISSION_REQUEST_COARSE_LOCATION);
} else {
            
    mbluetoothAdapter.startLeScan(callBack);
} } else {
    mbluetoothAdapter.startLeScan(callBack);
}}@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); switch (requestCode) { case PERMISSION_REQUEST_COARSE_LOCATION: if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
        mbluetoothAdapter.startLeScan(callBack);
} break;}}
mbluetoothAdapter.startLeScan(callBack);
BluetoothAdapter.LeScanCallback callBack = new BluetoothAdapter.LeScanCallback() {
    @Override
public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
    //TODO 處理掃描到的結果
Device = device;
}
}; 

6.連線藍芽

7.尋找服務,並開啟

Device.connectGatt(this,false,coreGattCallback);
BluetoothGattCallback connectCallback = new BluetoothGattCallback() {
    @Override
public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
        super.onConnectionStateChange(gatt, status, newState);
//TODO 藍芽連線狀態的回撥,在這裡根據newState判斷藍芽是否連線成功
if (newState == BluetoothGatt.STATE_CONNECTED) {
            mbluetoothGatt = gatt;
} else if (newState == BluetoothGatt.STATE_DISCONNECTED) {

        } else if (newState == BluetoothGatt.STATE_CONNECTING) {

        }
    }

    @Override
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
        super.onServicesDiscovered(gatt, status);
//TODO 在發方法中找服務並找到可通知的特徵值
BluetoothGattService bleService = gatt.getService(UUID.fromString("0000fee7-0000-1000-8000-00805f9b34fb"));
List<BluetoothGattCharacteristic> characteristics = bleService
                .getCharacteristics();
        for (BluetoothGattCharacteristic characteristic :characteristics) {
            int charaProp = characteristic.getProperties();
//找到可通知的特徵
UUID_NOFITY = characteristic.getUuid();
            if ((charaProp & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0) {
                //使所有的描述可通知
for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
gatt.writeDescriptor(descripter);
}
            }else if((charaProp & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0){
                //使所有的描述可通知
UUID_INDICATE = characteristic.getUuid();
                for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
gatt.writeDescriptor(descripter);
}
            }
        }


        //根據notify還是indicate來設定可寫的描述
for (BluetoothGattCharacteristic characteristic :characteristics) {
            int charaProp = characteristic.getProperties();
            if((charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE) > 0
|| (charaProp & BluetoothGattCharacteristic.PROPERTY_WRITE) > 0){
                UUID_WRITE = characteristic.getUuid();
//使所有的描述可通知
for (BluetoothGattDescriptor descripter : characteristic.getDescriptors()){
                    if(UUID_NOFITY != null && UUID_INDICATE == null){
                        descripter.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
}else if(UUID_INDICATE != null && UUID_NOFITY == null){
                        descripter.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE);
}
                    gatt.writeDescriptor(descripter);
}
            }
        }

    }

    @Override
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicRead(gatt, characteristic, status);
}

    @Override
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
        super.onCharacteristicWrite(gatt, characteristic, status);
//TODO 在這裡判斷想裝置是否寫資料成功
}

    @Override
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicChanged(gatt, characteristic);
//TODO 接受裝置上發是資料
}

    @Override
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorRead(gatt, descriptor, status);
}

    @Override
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        super.onDescriptorWrite(gatt, descriptor, status);
} @Overridepublic void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status);} @Overridepublic void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status);} @Overridepublic void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status);}};

8.斷開藍芽

mbluetoothGatt.close();

手機作為外圍裝置,傳送廣播供中心裝置連線

1.獲取BluetoothLeAdvertiser例項

private void initialize(){
    if(mBluetoothLeAdvertiser==null){
       mBluetoothManager=(BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        if(mBluetoothManager!=null){
            BluetoothAdapter bluetoothAdapter=mBluetoothManager.getAdapter();
            if(bluetoothAdapter!=null){
                mBluetoothLeAdvertiser=bluetoothAdapter.getBluetoothLeAdvertiser();
}else{
                Toast.makeText(this,"裝置不支援藍芽廣播",Toast.LENGTH_SHORT).show();
}
        }else{
            Toast.makeText(this,"不支援藍芽",Toast.LENGTH_SHORT).show();
}
    }
}

2.設定引數

private AdvertiseSettings buildAdvertiseSettings(){
    AdvertiseSettings.Builder settingsBuilder=new AdvertiseSettings.Builder();
settingsBuilder.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_LOW_POWER);
settingsBuilder.setTimeout(0);
    return settingsBuilder.build();
}
private AdvertiseData buildAdvertiseData(){
    AdvertiseData.Builder dataBuilder=new AdvertiseData.Builder();
dataBuilder.setIncludeDeviceName(true);
    return dataBuilder.build();
}
3.開始廣播
private void startAdvertising(){
    
    Log.d(TAG,"服務開始廣播");
    if(mAdertiseCallback==null){
        AdvertiseSettings settings=buildAdvertiseSettings();
AdvertiseData data=buildAdvertiseData();
mAdertiseCallback=new SampleAdvertiseCallback();
        if(mBluetoothLeAdvertiser!=null){
            mBluetoothLeAdvertiser.startAdvertising(settings,data,mAdertiseCallback);
}
    }
}
4.廣播回撥
private class SampleAdvertiseCallback extends AdvertiseCallback{
    @Override
public void onStartFailure(int errorCode){
        super.onStartFailure(errorCode);
Log.d(TAG,"廣播失敗");
sendFailureIntent(errorCode);
stopSelf();
}

    @Override
public void onStartSuccess(AdvertiseSettings settingsInEffect){
        super.onStartSuccess(settingsInEffect);
Log.d(TAG,"服務端的廣播成功開啟");
initServices(getContext());//該方法是新增一個服務,在此處呼叫即將服務廣播出去
}
}
5.為裝置新增服務
 private void initServices(Context context){
//        獲取BluetoothGattServer的例項
mBluetoothGattServer=mBluetoothManager.openGattServer(context,bluetoothGattServerCallback);
BluetoothGattService service=new BluetoothGattService(UUID_SERVER,BluetoothGattService.SERVICE_TYPE_PRIMARY);
characteristicRead=new BluetoothGattCharacteristic(UUID_CHARREAD,BluetoothGattCharacteristic.PROPERTY_READ,BluetoothGattCharacteristic.PERMISSION_READ);
service.addCharacteristic(characteristicRead);
characteristicWrite=new BluetoothGattCharacteristic(UUID_CHARWRITE,
BluetoothGattCharacteristic.PROPERTY_WRITE ,
BluetoothGattCharacteristic.PERMISSION_WRITE);
service.addCharacteristic(characteristicWrite);
characteristicIndicate = new BluetoothGattCharacteristic(UUID_INDICATE,
BluetoothGattCharacteristic.PROPERTY_INDICATE,
BluetoothGattCharacteristic.PERMISSION_WRITE);
BluetoothGattDescriptor descriptor=new BluetoothGattDescriptor(UUID_DESCRIPTOR,BluetoothGattCharacteristic.PERMISSION_WRITE);
characteristicIndicate.addDescriptor(descriptor);
service.addCharacteristic(characteristicIndicate);
mBluetoothGattServer.addService(service);
}
6.服務回撥
//服務事件的回撥
private BluetoothGattServerCallback bluetoothGattServerCallback=new BluetoothGattServerCallback() {
    //1、首先是連線狀態的回撥
@Override
public void onConnectionStateChange(BluetoothDevice device, int status, int newState) {
        super.onConnectionStateChange(device, status, newState);
Log.e(TAG,"連線狀態發生改變,安卓系統回撥onConnectionStateChange:device name="+device.getName()+"address="+device.getAddress()+"status="+status+"newstate="+newState);
}

    @Override
public void onCharacteristicReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattCharacteristic characteristic) {
        super.onCharacteristicReadRequest(device, requestId, offset, characteristic);
Log.e(TAG,"客戶端有讀的請求,安卓系統回撥該onCharacteristicReadRequest()方法");
mBluetoothGattServer.sendResponse(device,requestId, BluetoothGatt.GATT_SUCCESS,offset,characteristic.getValue());
}

    //接受具體位元組,當有特徵被寫入時,回撥該方法,寫入的資料為引數中的value
@Override
public void onCharacteristicWriteRequest(BluetoothDevice device, int requestId, BluetoothGattCharacteristic characteristic, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onCharacteristicWriteRequest(device, requestId, characteristic, preparedWrite, responseNeeded, offset, value);
Log.e(TAG,"客戶端有寫的請求,安卓系統回撥該onCharacteristicWriteRequest()方法");
//特徵被讀取,在該回調方法中回覆客戶端響應成功
mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);
//處理響應內容
        //value:客戶端傳送過來的資料
onResponseToClient(value,device,requestId,characteristic);
}

    //特徵被讀取。當回覆相應成功後,客戶端胡讀取然後觸發本方法
@Override
public void onDescriptorReadRequest(BluetoothDevice device, int requestId, int offset, BluetoothGattDescriptor descriptor) {
        super.onDescriptorReadRequest(device, requestId, offset, descriptor);
mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,null);
}

    //2、其次,當有描述請求被寫入時,回撥該方法,
@Override
public void onDescriptorWriteRequest(BluetoothDevice device, int requestId, BluetoothGattDescriptor descriptor, boolean preparedWrite, boolean responseNeeded, int offset, byte[] value) {
        super.onDescriptorWriteRequest(device, requestId, descriptor, preparedWrite, responseNeeded, offset, value);
mBluetoothGattServer.sendResponse(device,requestId,BluetoothGatt.GATT_SUCCESS,offset,value);
// onResponseToClient(value,device,requestId,descriptor.getCharacteristic());
}

    @Override
public void onServiceAdded(int status,BluetoothGattService service){
        super.onServiceAdded(status,service);
Log.e(TAG,"新增服務成功,安卓系統回撥該onServiceAdded()方法");
}
};

參考連線

BLE原始碼

4、BLE學習

相關推薦

Anroid BLE手機分別作為中心裝置外圍裝置

        藍芽是一種短距的無線通訊技術,可實現固定裝置、移動裝置之間的資料交換。一般將藍芽3.0之前的BR/EDR藍芽稱為傳統藍芽,而將藍芽4.0規範下的LE藍芽稱為低功耗藍芽。BLE藍芽模組主要應用領域    1、移動擴充套件裝置    2、汽車電子裝置    3、健

Android BLE 低功耗教程,中央BluetoothGatt周邊BluetoothGattServer的實現

Android4.3 規範了BLE的API,但是直到目前的4.4,還有些功能不完善。 在BLE協議中,有兩個角色,周邊(Periphery)和中央(Central);周邊是資料提供者,中央是資料使用/處理者;在iOS SDK裡面,可以把一個iOS裝置作為一個周邊,也可以作為

Android BLE 學習總結手機作為周邊BluetoothGattServer的實現

低功耗藍芽的基本概念: 在BLE協議中,有兩個角色,周邊(Periphery)和中央(Central)。周邊是資料的提供者,中央是資料的使用和處理者。在Android SDK裡面,Android4.3以後手機可以作為中央使用;Android5.0以後手機才可以

一分鐘讀懂低功耗BLE)連線資料包

一分鐘讀懂低功耗藍芽(BLE)連線資料包1.概述   BLE 連線過程中有三個重要的資料包:SCAN_REQ, SCAN_RSP 和 CONNECT_REQ。   SCAN_REQ: 掃描請求,由主裝置(MASTER DEVICE)向從裝置(SLAVE DEV

一分鐘讀懂低功耗BLE)廣播資料包

一分鐘讀懂低功耗藍芽(BLE)廣播資料包 低功耗藍芽 =》 BLE (Bluetooth Low Energy) 1. 怎樣抓取BLE廣播資料包    * 硬體:一個BLE裝置(具有廣播功能);          一臺H

TI低功耗BLE介紹

轉載自:http://www.cnblogs.com/cainiaoaixuexi/archive/2013/11/08/3414433.html 本文件翻譯和修改自參考資料:CC2540Bluetooth Low Energy Software Developer’s Guide (Rev.

IOS--swift BLE通訊管理裝置

之前一直做的是Android,公司IOS端突然要同時進行多個專案,IOS同學表示壓力山大,所以臨危受命由我來完成專案中關於BLE通訊的功能模組,由於之前做過Android版本的,並且執行狀況良好,一直都比較穩定,因此分享出來,也希望大家能提出好的建議。 總共有4個swift檔案。 如圖

低功耗BLEZigBee在物聯網應用中的區別

 隨著低功耗、廣域網(LPWAN)市場的擴大,物聯網(IoT)應用的低功耗協議有了更多的選擇。在本文中,我們將藍芽和藍芽低能耗(BLE)與ZigBee進行比較,這樣您就可以更好地瞭解在連線裝置上使用哪種無線協議。  簡單來說,藍芽是近場通訊,ZigBee是區域網,更深入的區別繼續看下文。

Android BLE4.0開發—Android手機BLE終端通訊

轉載自: https://blog.csdn.net/fu908323236/article/details/76208997 這篇部落格主要講解AndroidBLE藍芽4.0的基本概念,以及基礎用法。  BLE 即 Bluetooth Low Energy,藍芽低功耗技術,是藍芽

低功耗 BLE開發各種坑

這段時間在做低功耗藍芽 (BLE) 應用的開發(並不涉及藍芽協議棧)。總體感覺 Android BLE 還是不太穩定,開發起來也是各種痛苦。這裡記錄一些雜項和開發中遇到的問題及其解決方法,避免大家踩坑。本文說的問題有些沒有得到官方文件的驗證,不過也有一些論壇帖子的支援,也可以

android ble開發總結附帶自己專案中提取整理的demo地址

一些基本的知識我就不寫了,很多其他部落格都可以查到。我主要寫幾點我在其他部落格沒有看到的東西以及我在實際開發中遇到的問題。最後我會貼上程式碼的地址。 1.需要設定2個或3個uuid。通常連線裝置後會得

BLE協議 — BLE連線建立過程梳理

主裝置和從裝置建立連線之後,所有的資料通訊都是在連線事件(Connection Events)中進行的。尖刺的波就是連線事件(Connection events),剩下的Sleeping是睡眠時間,裝置在建立連線之後的大多數時間都是處於Sleeping,這種情況下耗電量比較低,而在連線事件(Connectio

BLE中的安全連線Secure Connections

BLE關於安全的發展歷史 藍芽Core 5.0已經發布,目前來看安全相關的內容沒有太多改變 BLE作為一個新發展出來的分支,作為一個新興的事務,關於安全的修改並不是特別多,僅僅在Core 4.2中有所增補 4.0提出BLE,並且採用配對認證的方式(密碼輸入、數字比較、直接工

Android BLE學習:編寫自己的 BLE讀寫工具功能仿照nrf master control panel

背景 由於nordic官方的nrf master control panel只提供了apk,很多同學學習起來都得自己摸索藍芽的讀寫,專案中整理了BLE模組的基本讀寫方法以及一些常用的UUID,並且抽取了一些藍芽操作的流程,方便Android app程式碼開發,

TI低功耗BLEGATT介紹

TI低功耗藍芽(BLE)介紹 本文件翻譯和修改自參考資料:CC2540Bluetooth Low Energy Software Developer’s Guide (Rev. B),部分圖片直接引用自該文件,不一一說明。初稿,待修改。 一、概述 1、BLE藍芽協議棧結

android BLE詳細講解

本文主要講解Android低功耗藍芽的api使用以及藍芽掃描、連線、傳送資料、接收資料等一系列操作,本篇結尾有本人封裝的BleLib藍芽庫,非常適合藍芽初學者使用,只需要一行程式碼注入就OK了,而且用法也極其簡單,我會在第二篇中專門講解一下BleLib庫的使用。

Android通過Bluetooth傳送手機照片檔案到Windows PC:Java實現

Android通過Bluetooth藍芽傳送手機照片檔案到Windows PC:Java實現 本文在《Android通過藍芽傳送資料到Windows PC電腦:Java實現(連結地址:https://blog.csdn.net/zhangphil/article/details/831467

Android學習——Bluetooth

藍芽(Bluetooth) 藍芽(Bluetooth)是一種短距離的無線通訊技術標準。 藍芽協議 藍芽協議分為4層,即核心替代層、電纜替代協議層、電話控制協議層和採納的其他的協議層。這4種最重要的是核心協議層。藍芽協議包括基帶、鏈路管理、邏輯鏈路控制和適應協議四部分。其中鏈路

Android BLE 快速開發框架。

FastBle 專案地址:Jasonchenlijian/FastBle  簡介:Android BLE 藍芽快速開發框架。 更多:作者   提 Bug    標籤: 藍芽- Thanks to th

Android開發之經典2.0開發全記錄

前言部分 最近因為需要開始藍芽相關開發,所以在網上搜索了很多內容,並且結合自己的開發過程做了一個總結,先儲備上,也許可能幫到正在做藍芽開發的同學。 藍芽很早就是android裝置上基本通訊功能了,只是以前的沒有那麼多藍芽裝置,現在藍芽裝置種類繁多,所以經常會有人遇到藍芽相關的開發