編輯:Android開發教程
一、藍牙BLE(Bluetooth Low Energy)介紹概要
藍牙低能耗(BLE)技術是低成本、短距離、可互操作的魯棒性無線技術,工作在免許可的2.4GHz ISM射頻頻段。它從一開始就設計為超低功耗(ULP)無線技術。
藍牙低能耗技術的三大特性成就了ULP性能,這三大特性分別是最大化的待機時間、快速連接和低峰值的發送/接收功耗。
無線“開啟”的時間只要不是很短就會令電池壽命急劇降低,因此任何必需的發送或接收任務需要很快完成。被藍牙低能耗技術用來最小化無線開啟時間的第一個技巧是僅用3個“廣告”信道搜索其它設備,或向尋求建立連接的設備宣告自身存在。相比之下,標准藍牙技術使用了32個信道。
藍牙低能耗技術“完成”一次連接(即掃描其它設備、建立鏈路、發送數據、認證和適當地結束)只需3ms。而標准藍牙技術完成相同的連接周期需要數百毫秒。再次提醒,無線開啟時間越長,消耗的電池能量就越多。
二、關鍵概念:
(1)Generic Attribute Profile (GATT)
通過BLE連接,讀寫屬性類小數據的Profile通用規范。現在所有的BLE應用Profile都是基於GATT的。
(2)Attribute Protocol (ATT)
GATT是基於ATT Protocol的。ATT針對BLE設備做了專門的優化,具體就是在傳輸過程中使用盡量少的數據。每個屬性都有一個唯一的UUID,屬性將以characteristics and services的形式傳輸。
(3)Characteristic
Characteristic可以理解為一個數據類型,它包括一個value和0至多個對次value的描述(Descriptor)。
(4)Descriptor
對Characteristic的描述,例如范圍、計量單位等。
(5)Service
Characteristic的集合。例如一個service叫做“Heart Rate Monitor”,它可能包含多個Characteristics,其中可能包含一個叫做“heart rate measurement"的Characteristic。
三、相關權限
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 允許程序進行發現和配對新的藍牙設備 -->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
public class BluetoothBleDemo extends Activity { private static final int REQUEST_CODE_BLUETOOTH_ENABLE = 1; private static final int SCAN_PERIOD = 10000; private BluetoothAdapter bluetoothAdapter; //import android.bluetooth.le.ScanCallback; private ScanCallback scanCallback = new ScanCallback() { @Override public void onBatchScanResults(List<ScanResult> results) { //Batch 一批 } @Override public void onScanResult(int callbackType, ScanResult result) { switch(callbackType) { case ScanSettings.CALLBACK_TYPE_ALL_MATCHES: break; case ScanSettings.CALLBACK_TYPE_FIRST_MATCH: break; case ScanSettings.CALLBACK_TYPE_MATCH_LOST: break; } BluetoothDevice device = result.getDevice(); String deviceName = device.getName(); String deviceAddress = device.getAddress(); int deviceType = device.getType(); ParcelUuid[] deviceUuids = device.getUuids(); int deviceBondState = device.getBondState(); ScanRecord scanRecord = result.getScanRecord(); int advertiseFlags = scanRecord.getAdvertiseFlags(); //txPowerLevel 發射功率等級 //URL:http://www.bianceng.cn/OS/extra/201608/50410.htm int txPowerLevel = scanRecord.getTxPowerLevel(); String recordDeviceName = scanRecord.getDeviceName(); List<ParcelUuid> serviceUuids = scanRecord.getServiceUuids(); Map<ParcelUuid, byte[]> serviceData = scanRecord.getServiceData(); //RSSI 信號強度,可以用來測算距離 int rssi = result.getRssi(); long timestampNanos = result.getTimestampNanos(); } @Override public void onScanFailed(int errorCode) { } }; private BluetoothGattCallback gattCallback = new BluetoothGattCallback() { @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { super.onServicesDiscovered(gatt, status); } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { super.onCharacteristicChanged(gatt, characteristic); } @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); } @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { super.onConnectionStateChange(gatt, status, newState); } @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); } @Override public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) { super.onMtuChanged(gatt, mtu, status); } @Override public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) { super.onReadRemoteRssi(gatt, rssi, status); } @Override public void onReliableWriteCompleted(BluetoothGatt gatt, int status) { super.onReliableWriteCompleted(gatt, status); } }; private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); //判斷是否支持BLE特性 if(getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { initBluetoothBle(); } else { showToast("this device can not support Bluetooth BLE"); } } private void initBluetoothBle() { //BluetoothAdapter是Android系統中所有藍牙操作都需要的,它對應本地Android設備的藍牙模塊,在整個系統中BluetoothAdapter是單例的。當你獲取到它的示例之後,就能進行相關的藍牙操作了。 //BluetoothManager在Android4.3以上支持(API level 18) BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE); bluetoothAdapter = bluetoothManager.getAdapter(); } /** * 開啟藍牙 * 打開和關閉藍牙模塊, 都可以通過ACTION_STATE_CHANGED廣播來監聽 */ private void requestEnable() { //第一種方法打開藍牙, 沒有任何提示, 直接就打開了 //boolean result = bluetoothAdapter.enable(); //第二種方法發送廣播, 會彈出一個對話框, 選擇是否打開藍牙, 選擇是藍牙才打開; if(bluetoothAdapter != null && !bluetoothAdapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(intent, REQUEST_CODE_BLUETOOTH_ENABLE); } } /** * 掃描BLE設備.注意該方法無法掃描標准藍牙,只能掃描BLE設備 */ private void scanBleDevice(final boolean enabled) { if(bluetoothAdapter == null) { return; } /* 為什麼不能再使用單例的BluetoothAdapter? 原因如下: bluetoothAdapter.startLeScan() //deprecated http://stackoverflow.com/questions/30223071/startlescan-replacement-to-current-api Remember that the method: public BluetoothLeScanner getBluetoothLeScanner () isn't static. If you do: BluetoothAdapter.getBluetoothLeScanner() you will get an error, since getDefaultAdapter() is a static method, but getBluetoothLeScanner() isn't. You need an instance of a BluetoothAdapter. */ final BluetoothLeScanner scanner = bluetoothAdapter.getBluetoothLeScanner(); if(enabled) { //scan分為2類,而在android L之前,搜索條件只有uuid //(1)直接搜索全部周圍peripheral(外圍的)設備,搜索結果將通過這個callback返回 scanner.startScan(scanCallback); //(2)根據過濾條件搜索設備 final List<ScanFilter> scanFilters = new ArrayList<ScanFilter>(); //uuid格式8-4-4-4-12(32位,128bit) //address格式(12位,48bit) scanFilters.add(new ScanFilter.Builder().setServiceUuid(ParcelUuid.fromString("00000000-0000-0000-0000-000000000000")).setDeviceAddress("00:00:00:00:00:00").build()); ScanSettings scanSettings = new ScanSettings.Builder() //require API 23 //.setCallbackType(0).setMatchMode(0).setNumOfMatches(0) .setReportDelay(0).setScanMode(BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE).build(); scanner.startScan(scanFilters, scanSettings, scanCallback); handler.postDelayed(new Runnable() { @Override public void run() { scanner.stopScan(scanCallback); } }, SCAN_PERIOD); } else { scanner.stopScan(scanCallback); } } /** * 兩個設備通過BLE通信,首先需要建立GATT連接。這裡我們講的是Android設備作為client端,連接GATT Server。數據發送方向總是從server推送到client */ private void connectToGATTServer(BluetoothDevice device) { //函數成功,返回BluetoothGatt對象,它是GATT profile的封裝。通過這個對象,我們就能進行GATT Client端的相關操作。BluetoothGattCallback用於傳遞一些連接狀態及結果。 BluetoothGatt bluetoothGatt = device.connectGatt(this, false, gattCallback); //連接遠程設備 boolean connectResult = bluetoothGatt.connect(); //搜索連接設備所支持的service boolean discoverResult = bluetoothGatt.discoverServices(); //斷開與遠程設備的GATT連接 bluetoothGatt.disconnect(); //關閉GATT Client端 bluetoothGatt.close(); //讀取指定的characteristic。 //boolean readResult = bluetoothGatt.readCharacteristic(characteristic); //設置當指定characteristic值變化時,發出通知 //boolean setResult = bluetoothGatt.setCharacteristicNotification(characteristic, enabled); //獲取遠程設備所支持的services List<BluetoothGattService> gattServices = bluetoothGatt.getServices(); } private void showToast(String msg) { Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); } }
1.介紹在制作android應用的時候,常常用到很多string,就是一些文字,這裡介紹一種方法,將所有string封裝在一個string.xml文件中,通過styles
今天心血來潮,又把ADT升級了一下,升級到了ADT 22,悲催的發現項目用不了了(能編譯通過,運行出錯)。錯誤一:(警告)Unable to resolve superc
在上一節,我們已經知道了在按MENU鍵的時候,如何顯示選項菜單。但是,除了選項菜單,你也可以顯示 一個上下文菜單。上下文菜單通常是和activity中的組件相關聯的。當用
當要進行耗時的操作的時候,往往會看見“請稍候”字樣的對話框。例如,用戶正在登入服務器,此時並 不允許用戶使用這個軟件,或者應用程序把結果返回給用戶