1. 程式人生 > >android藍芽ble4.0開發

android藍芽ble4.0開發

1、許可權配置

AndroidManifest.xml裡配置,android:required="true"表示apk只有在具有bluetooth_le屬性的系統裡執行。

    <uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
    <uses-permission android:name="android.permission.BLUETOOTH"/>
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

2、判斷是否支援藍芽

	     if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
                   Toast.makeText(this, R.string.ble_not_supported, Toast.LENGTH_SHORT).show();
                    finish();
             }

3、開啟和關閉藍芽

先獲取藍芽介面卡:

        final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluetoothManager.getAdapter();

        // Checks if Bluetooth is supported on the device.
        if (mBluetoothAdapter == null) {
            Toast.makeText(this, R.string.error_bluetooth_not_supported, Toast.LENGTH_SHORT).show();
            finish();
            return;
        }

如果藍芽關閉,則開啟藍芽:

        if (!mBluetoothAdapter.isEnabled()) {
            if (!mBluetoothAdapter.isEnabled()) {
                Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }
public void onActivityResult(int requestCode, int resultCode, Intent data){  
       if(requestCode == REQUEST_ENABLE_BT){  
              if(requestCode == RESULT_OK){  
                   //藍芽已經開啟   
              }  
       }  
}

// 也可以用enable()方法來開啟,無需詢問使用者(無聲息的開啟藍芽裝置),這時就需要用到android.permission.BLUETOOTH_ADMIN許可權。  
        // mBluetoothAdapter.enable();  //開啟藍芽 
        // mBluetoothAdapter.disable();//關閉藍芽 

注意,如果用靜默的方式開啟藍芽,不能馬上開始掃描,這樣會失敗,因為開啟藍芽要一兩秒時間。

4、搜尋藍芽

            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;
                    mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    invalidateOptionsMenu();
                }
            }, SCAN_PERIOD);
            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
在4.3之前的api是通過註冊廣播來處理搜尋時發生的一些事件,使用startDiscovery()這個函式搜尋,而支援ble的新的api中,是通過回撥的方式來處理的,mLeScanCallback就是一個介面物件。
    private BluetoothAdapter.LeScanCallback mLeScanCallback =
            new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {     
                        mLeDeviceListAdapter.addDevice(device);
                        mLeDeviceListAdapter.notifyDataSetChanged();
                }
            });
        }
    };

device代表藍芽裝置,rssi是訊號強度,scanRecord是廣播資料,一些專案要求廣播匹配藍芽裝置才能被發現,就是根據把產品ID寫到廣播裡來判別。如下:

4.3以下的通過廣播方式來搜尋,如下:

// 設定廣播資訊過濾    
IntentFilter intentFilter = new IntentFilter();   
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);   
intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);   
intentFilter.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);   
intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);   
// 註冊廣播接收器,接收並處理搜尋結果    
context.registerReceiver(receiver, intentFilter);   
// 尋找藍芽裝置,android會將查詢到的裝置以廣播形式發出去    
adapter.startDiscovery();  
private BroadcastReceiver receiver = new BroadcastReceiver() {   
   @Override   
  public void onReceive(Context context, Intent intent) {   
       String action = intent.getAction();   
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {   
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);   
            System.out.println(device.getName());   
       }   
   }   
}

另外,還可以配置本機藍芽是否可見,被對方搜尋到:

//使本機藍芽在300秒內可被搜尋  
private void ensureDiscoverable() {  
        if (mBluetoothAdapter.getScanMode() !=   BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {  
            Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);  
            discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);  
            startActivity(discoverableIntent);  
        }  
} 
還有查詢以前配對過的裝置:
		Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
		if (pairedDevices.size() > 0) {
			for (BluetoothDevice device : pairedDevices) {
				//device.getName() +" "+ device.getAddress());
			}
		} else {
			mPairedDevicesArrayAdapter.add("沒有找到已匹對的裝置");
		}

5、藍芽連線 兩個裝置通過BLE通訊,首先需要建立GATT連線。這裡我們講的是Android裝置作為client端,連線GATT Server。 連線GATT Server,你需要呼叫BluetoothDevice的connectGatt()方法。此函式帶三個引數:Context、autoConnect(boolean)和BluetoothGattCallback物件。呼叫示例: mBluetoothGatt = device.connectGatt(this, false, mGattCallback); 函式成功,返回BluetoothGatt物件,它是GATT profile的封裝。通過這個物件,我們就能進行GATT Client端的相關操作。BluetoothGattCallback用於傳遞一些連線狀態及結果。 BluetoothGatt常規用到的幾個操作示例: connect() :連線遠端裝置。 discoverServices() : 搜尋連線裝置所支援的service。 disconnect():斷開與遠端裝置的GATT連線。 close():關閉GATT Client端。 readCharacteristic(characteristic) :讀取指定的characteristic。 setCharacteristicNotification(characteristic, enabled) :設定當指定characteristic值變化時,發出通知。 getServices() :獲取遠端裝置所支援的services。

google的demo裡,連線藍芽,首先繫結一個服務:

		Intent gattServiceIntent = new Intent(this, BluetoothLeService.class);
		bindService(gattServiceIntent, mServiceConnection, BIND_AUTO_CREATE);
// Code to manage Service lifecycle.
	private final ServiceConnection mServiceConnection = new ServiceConnection() {

		@Override
		public void onServiceConnected(ComponentName componentName,
				IBinder service) {
			mBluetoothLeService = ((BluetoothLeService.LocalBinder) service)
					.getService();
			if (!mBluetoothLeService.initialize()) {
				Log.e(TAG, "Unable to initialize Bluetooth");
				finish();
			}
			// Automatically connects to the device upon successful start-up
			// initialization.
			mBluetoothLeService.connect(mDeviceAddress);
		}

		@Override
		public void onServiceDisconnected(ComponentName componentName) {
			mBluetoothLeService = null;
		}
	};

initialize()初始化函式裡,主要是獲得mBluetoothManager和mBluetoothAdapter:
 /**
     * Initializes a reference to the local Bluetooth adapter.
     *
     * @return Return true if the initialization is successful.
     */
    public boolean initialize() {
        // For API level 18 and above, get a reference to BluetoothAdapter through
        // BluetoothManager.
        if (mBluetoothManager == null) {
            mBluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
            if (mBluetoothManager == null) {
                Log.e(TAG, "Unable to initialize BluetoothManager.");
                return false;
            }
        }

        mBluetoothAdapter = mBluetoothManager.getAdapter();
        if (mBluetoothAdapter == null) {
            Log.e(TAG, "Unable to obtain a BluetoothAdapter.");
            return false;
        }

        return true;
    }
     連線函式mBluetoothLeService.connect裡,先用getRemoteDevice獲取BluetoothDevice,然後呼叫connectGatt函式連線,連線成功返回BluetoothGatt。
 /* Connects to the GATT server hosted on the Bluetooth LE device.
     *
     * @param address The device address of the destination device.
     *
     * @return Return true if the connection is initiated successfully. The connection result
     *         is reported asynchronously through the
     *         {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)}
     *         callback.
     */
    public boolean connect(final String address) {
        if (mBluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        // Previously connected device.  Try to reconnect.
        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                && mBluetoothGatt != null) {
            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
            if (mBluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
        Log.d(TAG, "Trying to create a new connection.");
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        System.out.println("device.getBondState=="+device.getBondState());
        return true;
    }
這裡的mGattCallback是藍芽連線和通訊讀寫和收到通知時的回撥函式。
 //藍芽資料返回
    // Implements callback methods for GATT events that the app cares about.  For example,
    // connection change and services discovered.
    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                broadcastUpdate(ACTION_GATT_SERVICES_DISCOVERED);
            } else {
                Log.w(TAG, "onServicesDiscovered received: " + status);
                System.out.println("onServicesDiscovered received: " + status);
            }
        } 
        
        public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic,int status) {
        	 Log.e(TAG, "onCharacteristicRead");
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.e(TAG,"onCharRead "+gatt.getDevice().getName()
                        +" read "
                        +characteristic.getUuid().toString()
                        +" -> "
                        +UMDataProcessUtil.bytesToHexString(characteristic.getValue()));
                broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
                
            }
        }
        /**
         * 返回資料。
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt,
                                            BluetoothGattCharacteristic characteristic) {
            broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic);
            //資料
            Log.i("onCharacteristicChanged", "返回讀出的值");
            Log.e("notify data:", UMDataProcessUtil.bytesToHexString(characteristic.getValue()));

        }
        
    };


6、藍芽通訊
BLE分為三部分Service、Characteristic、Descriptor,這三部分都由UUID作為唯一標示符。一個藍芽4.0的終端可以包含多個Service,一個Service可以包含多個Characteristic,一個Characteristic包含一個Value和多個Descriptor,一個Descriptor包含一個Value
我們一般需要操作的是Characteristic,需要先獲取Service,然後可以進行讀、寫和開啟通知操作。     public static final UUID SERVIE_UUID = UUID.fromString("0000FE95-0000-1000-8000-00805f9b34fb");
     BluetoothGattService linkLossService = mBluetoothGatt.getService(SERVIE_UUID);
1)、Characteristic讀操作
    public static final UUID LIGHT_UUID = UUID.fromString("00001006-0000-1000-8000-00805F9B34FB");
public void readLlsAlertLevel(){
		BluetoothGattService linkLossService = mBluetoothGatt.getService(SERVIE_UUID);
		if (linkLossService == null) {
			showMessage("readLlsAlertLevel, link loss Alert service not found!");
			return;
		}
		BluetoothGattCharacteristic alertLevel = linkLossService.getCharacteristic(STATE_UUID);
		if(mBluetoothGatt.readCharacteristic(alertLevel)) {
			 Log.e("test","ble read success");
		} else {
			 Log.e("test","ble read fail");
		}
		
    }
藍芽讀操作對應上面mGattCallback的函式是onCharacteristicRead,執行完讀之後可以在onCharacteristicRead裡收到讀的資料。 2)Characteristic寫操作
    public void writeLlsAlertLevel(int iAlertLevel, byte[] bb) {

		BluetoothGattService linkLossService = mBluetoothGatt.getService(SERVIE_UUID);
		if (linkLossService == null) {
			showMessage("writeLlsAlertLevel,link loss Alert service not found!");
			return;
		}
		
		BluetoothGattCharacteristic alertLevel = null;
		alertLevel = linkLossService.getCharacteristic(KEY_UUID);
		if (alertLevel == null) {
			showMessage("writeLlsAlertLevel,link loss Alert Level charateristic not found!");
			return;
		}

		int storedLevel = alertLevel.getWriteType();
		Log.d(TAG, "storedLevel() - storedLevel=" + storedLevel);

		alertLevel.setValue(bb);
		Log.e("傳送的指令", "bb" + bb[0]);

		alertLevel.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
		boolean status = mBluetoothGatt.writeCharacteristic(alertLevel);
		Log.d(TAG, "writeLlsAlertLevel() - status=" + status);
	}
藍芽寫操作對應上面mGattCallback的函式是onCharacteristicWrite,但是我們一般沒有必要監視這個,直接從返回的status判斷是否寫成功就行了。 3)Characteristic開啟\關閉notify 如果我們要長期監視藍芽裝置的狀態變化,一般需要用到notify功能。
    public boolean enableStateNotification(boolean enable){
    	
		BluetoothGattService linkLossService = mBluetoothGatt.getService(SERVIE_UUID);
		if (linkLossService == null) {
			showMessage("enableStateNotification, link loss Alert service not found!");
			return false;
		}
		BluetoothGattCharacteristic characteristic = linkLossService.getCharacteristic(STATE_UUID);
	    int charaProp = characteristic.getProperties();
    	if ((charaProp | BluetoothGattCharacteristic.PROPERTY_NOTIFY) <= 0)
    	{
    		showMessage("getProperties wrong!Not PROPERTY_NOTIFY !");
    		return false;
    	}
    	return setCharacteristicNotification(characteristic,enable);
    }


 public static String CLIENT_CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb";
 /**
     * Enables or disables notification on a give characteristic.
     * @param characteristic Characteristic to act on.
     * @param enabled If true, enable notification.  False otherwise.
     */
    public boolean setCharacteristicNotification(BluetoothGattCharacteristic characteristic,
                                              boolean enabled) {
        if (mBluetoothAdapter == null || mBluetoothGatt == null) {
            Log.w(TAG, "BluetoothAdapter not initialized");
            return false;
        }
        boolean result =mBluetoothGatt.setCharacteristicNotification(characteristic, enabled);
        if(!result){
         <span style="white-space:pre">	</span>Log.e(TAG, "setCharacteristicNotification fail!!!!!!!!!!!");
        <span style="white-space:pre">	</span>return false;
        }


        BluetoothGattDescriptor descriptor = characteristic.getDescriptor(
                UUID.fromString(UMGattAttributes.CLIENT_CHARACTERISTIC_CONFIG));
        descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
        return  mBluetoothGatt.writeDescriptor(descriptor);
       
    }

藍芽notify操作對應上面mGattCallback的函式是onCharacteristicChanged,開啟之後,可以在這個函式裡監視notify的資料變化。

相關推薦

androidble4.0開發

1、許可權配置 AndroidManifest.xml裡配置,“android:required="true"表示apk只有在具有bluetooth_le屬性的系統裡執行。 <uses-feature android:name="android.hardwa

AndroidBLE4.0踩過的坑

一直都負責專案的藍芽模組,期間踩過很多坑,說出來跟大家分享一下。 1. 從簡單的開始,首先是許可權的問題,在Android6.0以上,部分機型需要開啟定位許可權,部分機型需要同時開啟GPS。所以使用藍芽之前,你可以動態申請定位許可權,或者直接將targetSdkVersio

ANDROID4.0開發_開發例項原始碼下載

一個整合目前主流藍芽的demo、android藍芽4.0開發、專案中使用到了搜尋BLE終端和讀寫BLE終端、另外還有在程式裡面開房藍芽、在Demo裡面還處理了收到BLE終端資料互動的事件、程式碼裡都有中文註釋、要讀性應該非常好的、應該會對開發有一定幫助、有興趣的哥們可以下

Android開發之低功耗(4.0)開發全記錄

主要內容概況 前面我記錄了開發藍芽2.0的過程,今天準備介紹現在的主流藍芽技術,藍芽4.0的開發,該藍芽技術是在Android4.3(API級別18)版本引入的API。 官方文件 具體的區別主要以下幾點: 1.新的藍芽技術提供了連線服務的方法,以前是沒有提供連線藍芽的方法

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

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

Unity實現Android源生平臺BLE4.0資料傳輸(三)

上篇我說到如何開啟系統藍芽 掃描裝置 連線 具體連線我們在這裡說 AndroidJavaObject wfzBluetoothGattCallback = new AndroidJavaObject("com.wfz.bletounity.WFZBluetoothGat

Android 4.0(ble)開發的解決方案

   最近,隨著智慧穿戴式裝置、智慧醫療以及智慧家居的普及,藍芽開發在移動開中顯得非常的重要。由於公司需要,研究了一下,藍芽4.0在Android中的應用。以下是我的一些總結。           1.先介紹一下關於藍芽4.0中的一些名詞吧:               

android 4.0(BLE)開發

最近剛好專案需要手機與藍芽模組通訊,基於藍芽4.0,網上資料較少也有些小坑,故作一下總結。 關鍵術語和概念 藍芽有傳統藍芽(3.0以下)和低功耗藍芽(BLE,又稱藍芽4.0)之分,而藍芽4.0開發需要android4.3版本(API 18)及以上才支援

Android4.0 關閉重開無法根據地址連線問題

在藍芽專案的末尾,在個別手機上出來,手動關閉手機藍芽,和再次啟動,開啟app發現無法連線上,經過檢視log最後確定錯誤是: onClientConnectionState()- status=133 clientIf=5 device=地址 133的一個錯誤,前面試過很

Android 4.0實現,自動匹配裝置

        今天開始寫部落格來記錄我的工作學習成長,作為一個初學者,近期的一個工作是通過Android藍芽4.0來實現與藍芽裝置的資料交換,下面就通過程式碼和文字來解釋一下整個過程。         首先我要說明的是,我再專案中使用了一個開源庫,我覺得不錯,所有程式碼都

android 4.0 ble 低功耗

一:概述 這段時間做了藍芽4.0的專案,就是一個藍芽裝置控制手機進行拍照。並且有很多按鍵,不同的按鍵對應到手機上有不同的功能,並且組合起來也有不同的功能。 低功耗藍芽有中央裝置後周邊裝置的概念手機就是一箇中央裝置,像我這次試用的一個控制器, 我試過小

android 4.0 分包傳輸資料 問題

最近一直被這個藍芽4.0資料傳輸問題的困擾,安卓版本這麼多,發現一樣的資料傳輸程式碼在不同手機上效果截然不同。 目前發現在5.1的系統上,藍芽4.0每次傳送256byte資料可行,但是在4.4的系統上每次傳輸資料最多為20byte。 下次傳輸時還未到BLE的

Android開發(二) BLE4.0低功耗

一、BLE4.0低功耗藍芽 Bluetooth Low Energy,藍芽低功耗,是從藍芽4.0開始支援的技術。相較傳統藍芽,傳輸速度更快、覆蓋範圍廣、安全性高、延時短、耗電低等特點。 二、關鍵術語 1.GATT(通用屬性配置):通用屬性配置檔案,用於ble鏈路上傳送和接

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

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

Android 開發常用UUID表

        // Sample Services.          attributes.put("0000180d-0

Android BLE開發詳解

轉載請註明出處。    https://blog.csdn.net/kong_gu_you_lan/article/details/81009800 1.介紹 藍芽是一種短距離的無線通訊技術,可以實現固定裝置、移動裝置之間的資料交換。一般將藍芽分為兩大類,藍芽3.0規範之前的

Android 通訊開發(一) 搜尋裝置

藍芽通訊是我們日常生活中比較方便的一種通訊技術,Android從2.0版本的SDK就開始支援藍芽。對開發人員來說,應用程式中藍芽還是一種用來建立點對點連線通訊的簡單而高效的方式。 藍芽通訊功能的實現的基本流程大致分為藍芽裝置搜尋、藍芽裝置連線和藍芽通訊

1 android開發---與模組進行通訊

原文地址 http://www.cnblogs.com/wenjiang/p/3200138.html 近半個月來一直在搞android藍芽這方面,主要是專案需要與藍芽模組進行通訊。開頭的進展很順利,但因為藍芽模組不在我這裡,所以只能用手機測試。一開頭就發現手機的藍芽

android4.0BLE及2.0 2.1 apk 串列埠助手帶16個自定義按鍵和自定義指令 字元接收 十六進位制或字元傳送

android藍芽4.0BLE apk 帶16個自定義按鍵和自定義指令 字元接收 https://pan.baidu.com/s/1eRSfprO android藍芽2.0 2.1 apk 帶16個自定義按鍵和自定義指令 字元接收  帶自動連線 https://pan.b

Android 開發 —— BLE

藍芽——BLE 介紹 1.BLE 是 Bluetooth Low Energy 的縮寫,意思為低功耗藍芽。由藍芽技術聯盟(Bluetooth SIG)設計的無線通訊技術,主要用於醫療,健身,安全和家庭娛樂行業。 與傳統藍芽相比,藍芽低功耗旨在大幅降低功耗