編輯:關於Android編程
package com.rmt.bluetooth.audio.ble; import android.app.Service; import android.content.Intent; import android.os.Handler; import android.os.HandlerThread; import android.os.IBinder; /** * 00:01:e4:00:00:26 smart Key 678fea09-1021-0001-4429-00ab85ba498a (service) * 678fea09-dde9-0388-40a9-34ab85ba498a 01:0d:5b:00:15:11 Howic123 * 00006678-9082-11e1-9b23-00025b000011 (service) * 00006678-9082-11e1-9b23-00025b000012 00006678-9082-11e1-9b23-00025b000013 */ public class RMTBleService extends Service { private final long SCAN_PERIOD = 8000; // 2000毫秒(ms) = 2秒(s) private Handler mHandler; private HandlerThread handlerThread; private boolean mStop = false; @Override public IBinder onBind(Intent intent) { return null; } @Override public void onCreate() { super.onCreate(); mStop = false; handlerThread = new HandlerThread("xxxx"); handlerThread.start(); mHandler = new Handler(handlerThread.getLooper()); mHandler.post(mRunnable); } // @Override // public int onStartCommand(Intent intent, int flags, int startId) { // RMTBle.getInstance(RMTBleService.this).startSacnThread(); // return super.onStartCommand(intent, flags, startId); // } private Runnable mRunnable = new Runnable() { public void run() { if (mStop) return; scanBleDevice(true); mHandler.postDelayed(this, 8500); } }; private Runnable mStopLeScanRunable = new Runnable() { public void run() { if (mStop) return; RMTBle.getInstance(RMTBleService.this).stopLeScan(); } }; public void scanBleDevice(boolean enable) { if (enable) { mHandler.postDelayed(mStopLeScanRunable, SCAN_PERIOD); RMTBle.getInstance(RMTBleService.this).startLeScan(); } else { RMTBle.getInstance(RMTBleService.this).stopLeScan(); } } @Override public void onDestroy() { super.onDestroy(); mStop = true; mHandler.removeCallbacks(mRunnable); mHandler.removeCallbacks(mStopLeScanRunable); RMTBle.getInstance(this).destroy(); }; }
package com.rmt.bluetooth.audio.ble; import java.util.List; import java.util.UUID; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import org.apache.commons.lang3.ArrayUtils; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.os.Handler; import android.util.Log; import com.rmt.bluetooth.audio.dataparse.CommonMethods; import com.rmt.bluetooth.audio.dataparse.Constants; public class RMTBle { public static final String TAG = "Ble"; //2000毫秒(ms) = 2秒(s) private Context mContext; private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; public static final UUID keyUUID = UUID.fromString("xxxxx-1021-0001-4429-00xxxxxa498a"); public static final UUID earUUID = UUID.fromString("xxxxx-9082-11e1-9b23-000xxxx00011"); public static final UUID earWriteUUID = UUID.fromString("xxxxx-9082-11e1-9b23-0002xxxx0012"); private final int MAX_PACKET_SIZE = 16; private BleFunction bleFunction; private BluetoothGatt bGettKeyboard, bGettHearset; private String lastAddress; public int count; private boolean keyStatus, earStatus; private final int OP_READ = 0; private final int OP_WRITE = 1; private final int MAX_BUFFER_SIZE = 1024 * 100; private int mDataLen; private byte[] mDataBuffer = new byte[MAX_BUFFER_SIZE]; private IStatus iStatus; private static RMTBle sInstance; // private ScanThread scanThread; private RMTBle(Context context) { this.mContext = context; getAdapter(); // scanThread = new ScanThread(); bleFunction = new BleFunction(mContext); } public synchronized static RMTBle getInstance(Context context) { if (sInstance == null) { sInstance = new RMTBle(context); } return sInstance; } private void getAdapter() { if (mBluetoothManager == null) { mBluetoothManager = (BluetoothManager) mContext.getSystemService(Context.BLUETOOTH_SERVICE); } mBluetoothAdapter = mBluetoothManager.getAdapter(); } /* ************************************************************************** */ /* private class ScanThread extends Thread { @Override public void run() { super.run(); mHandler.postDelayed(new Runnable() { @Override public void run() { mHandler.sendEmptyMessage(0x02); } }, 10000); mHandler.sendEmptyMessage(0x01); } }; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { switch (msg.what) { case 0x01: //開始掃描 startLeScan(); Log.d(TAG, "-----------------startLeScan()------------>"); break; case 0x02: //停止掃描,停止線程 stopLeScan(); // scanThread.interrupt(); Log.d(TAG, "-----------------scanThread.interrupt();------------>"); break; } }; }; public void startSacnThread() { Runnable runnable = new Runnable() { public void run() { Log.d(TAG, "-----------------線程start()------------>"); scanThread.start(); } }; ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); service.scheduleAtFixedRate(runnable, 50, 2000, TimeUnit.MICROSECONDS); } */ /* ************************************************************************** */ //掃描的回調中截取UUID private UUID guuid_record(byte[] scanRecord) { final int serviceOffset = 5; try { byte[] service = ArrayUtils.subarray(scanRecord, serviceOffset, serviceOffset + 16); ArrayUtils.reverse(service); String discoveredServiceID = bytesToHex(service); String realId = discoveredServiceID.substring(0, 8) + "-" + discoveredServiceID.substring(8, 12) + "-" + discoveredServiceID.substring(12, 16) + "-" + discoveredServiceID.substring(16, 20) + "-"+ discoveredServiceID.substring(20); return UUID.fromString(realId); } catch (Exception e) { e.printStackTrace(); } return null; } //byte 轉 String private String bytesToHex(byte[] service) { String a = ""; for (int i = 0; i < service.length; i++) { String hex = Integer.toHexString(service[i] & 0xFF); if (hex.length() == 1) { hex = '0' + hex; } a = a + hex; } return a; } //掃描回調 private BluetoothAdapter.LeScanCallback mLeScanCallback = new BluetoothAdapter.LeScanCallback() { @Override public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) { String str = device.getAddress(); String name = device.getName(); Log.d(TAG, "---掃描的設備---->"+name+"---"+str); if (count < 2) { if (guuid_record(scanRecord).equals(keyUUID) || guuid_record(scanRecord).equals(earUUID)) { //連接指定的uuid if (!str.equalsIgnoreCase(lastAddress)) { // 連接上的同一地址不處理 if (connect(device, guuid_record(scanRecord))) { lastAddress = str; count++; } } } } else{ Log.d(TAG, "---count >= 2---->"+count); } } }; public void startLeScan() { if (mBluetoothAdapter != null) { mBluetoothAdapter.startLeScan(mLeScanCallback); } } public void stopLeScan() { if (mBluetoothAdapter != null) { Log.d(TAG, "---stopLeScan()---->"+count); mBluetoothAdapter.stopLeScan(mLeScanCallback); } } /** 向耳機寫入指令 */ public void write(byte[] bytes) { if(bGettHearset != null){ int i = 0; byte[] tmp_data = new byte[MAX_PACKET_SIZE]; if (bytes.length % MAX_PACKET_SIZE > 0) { System.arraycopy(bytes, i * MAX_PACKET_SIZE, tmp_data, 0, bytes.length % MAX_PACKET_SIZE); BluetoothGattService writeValue = bGettHearset.getService(earUUID); if (writeValue == null) return; BluetoothGattCharacteristic characteristic = writeValue.getCharacteristic(earWriteUUID); if (characteristic == null) return; characteristic.setValue(tmp_data); characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); bGettHearset.writeCharacteristic(characteristic); } } } //連接 public boolean connect(BluetoothDevice device, UUID uuid) { String connectAddress = device.getAddress(); //耳機斷開了重新連接 , 沒必要做重連, 在connectGatt() call connect(); // if (bGettHearset != null && connectName.startsWith("Howic") && connectAddress.equals(lastAddress)) { // earStatus = bGettHearset.connect(); // CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_EAR_STATUS, earStatus); // return earStatus; // } //遙控器斷開了重新連接 // if(bGettKeyboard != null && connectName.startsWith("smart") && connectAddress.equals(lastAddress)){ // keyStatus = bGettKeyboard.connect(); // CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_KEY_STATUS, keyStatus); // return keyStatus; // } final BluetoothDevice deviceTemp = mBluetoothAdapter.getRemoteDevice(connectAddress); //遙控器建立GATT連接 if(uuid.toString().startsWith("678fea09")){ bGettKeyboard = deviceTemp.connectGatt(mContext, false, gattKeyboard); if(bGettKeyboard != null){ lastAddress = connectAddress; keyStatus = true; CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_KEY_STATUS, keyStatus); return true; } } //耳機建立GATT連接 if(uuid.toString().startsWith("00006678")){ bGettHearset = deviceTemp.connectGatt(mContext, false, gettHearset); if(bGettHearset != null) { lastAddress = connectAddress; earStatus = true; CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_EAR_STATUS, earStatus); return true; } } return false; } /**耳機的GATT回調*/ private BluetoothGattCallback gettHearset = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { bGettHearset.discoverServices(); iStatus.statusInfo(newState, earUUID); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { lastAddress = ""; //斷開後將最後的地址置空, 不然重連不上,連接設備的個數也減 1 count--; bGettHearset.close(); bGettHearset = null; try { CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_EAR_STATUS, false); iStatus.statusInfo(newState, earUUID); String atCmd = "HFP=0\r\n"; byte[] new_data = atCmd.getBytes(); handle_buffer(OP_WRITE, new_data, new_data.length); Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { ListgettServiceList = bGettHearset.getServices(); for (BluetoothGattService gattService : gettServiceList) { if(gattService.getUuid().equals(earUUID)){ List gattCharacteristicsList = gattService.getCharacteristics(); for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristicsList) { if(gattCharacteristic.getUuid().equals(earWriteUUID)){ bGettHearset.setCharacteristicNotification(gattCharacteristic, true); break; } } } } } @Override public void onCharacteristicRead(BluetoothGatt gatt,BluetoothGattCharacteristic characteristic, int status) { } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] new_data = characteristic.getValue(); while (handle_buffer(OP_WRITE, new_data, new_data.length) != null) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } }; } }; /**遙控器的GATT回調*/ private BluetoothGattCallback gattKeyboard = new BluetoothGattCallback() { @Override public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) { if (newState == BluetoothProfile.STATE_CONNECTED) { bGettKeyboard.discoverServices(); iStatus.statusInfo(newState, keyUUID); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { lastAddress = ""; //斷開後將最後的地址置空, 不然重連不上,連接設備的個數也減 1 count--; bGettKeyboard.close(); bGettKeyboard = null; CommonMethods.saveBooleanSharedParameter(mContext, Constants.BLE_KEY_STATUS, false); iStatus.statusInfo(newState, keyUUID); } } @Override public void onServicesDiscovered(BluetoothGatt gatt, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { List gettServiceList = bGettKeyboard.getServices(); for (BluetoothGattService gattService : gettServiceList) { if(gattService.getUuid().equals(keyUUID)){ List gattCharacteristicsList = gattService.getCharacteristics(); for (int i = 0; i < gattCharacteristicsList.size(); i++) { bGettKeyboard.setCharacteristicNotification(gattCharacteristicsList.get(0), true); break; } } } } } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { byte[] data = characteristic.getValue(); final StringBuilder stringBuilder = new StringBuilder(data.length); for (byte byteChar : data) { //讀到的byte[]轉為十進制的int stringBuilder.append(String.format("%d", byteChar)); } Log.d(TAG, "---key---value---->"+Integer.parseInt(stringBuilder.toString())); bleFunction.keySingEven(Integer.parseInt(stringBuilder.toString())); } }; public void sendPortText(String str) { send(str.getBytes()); } public int send(byte[] data) { if(bGettHearset != null){ BluetoothGattService writeValue = bGettHearset.getService(earUUID); if (writeValue == null) return 0; BluetoothGattCharacteristic characteristic = writeValue.getCharacteristic(earWriteUUID); if (characteristic == null) return 0; int i = 0; int loop = data.length / MAX_PACKET_SIZE; byte[] tmp_data = new byte[MAX_PACKET_SIZE]; for (i = 0; i < loop; i++) { System.arraycopy(data, i * MAX_PACKET_SIZE, tmp_data, 0, MAX_PACKET_SIZE); characteristic.setValue(tmp_data); characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); bGettHearset.writeCharacteristic(characteristic); } if (data.length % MAX_PACKET_SIZE > 0) { System.arraycopy(data, i * MAX_PACKET_SIZE, tmp_data, 0, data.length % MAX_PACKET_SIZE); characteristic.setValue(tmp_data); characteristic.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); bGettHearset.writeCharacteristic(characteristic); } } return data.length; } public byte[] read() { return handle_buffer(OP_READ, null, 0); } public synchronized byte[] handle_buffer(int op_mode, byte[] buffer, int size) { if (op_mode == OP_READ) { if (mDataLen > 0) { byte[] copy_data = new byte[mDataLen]; System.arraycopy(mDataBuffer, 0, copy_data, 0, mDataLen); mDataLen = 0; return copy_data; } } else { if (mDataLen < MAX_BUFFER_SIZE) { System.arraycopy(buffer, 0, mDataBuffer, mDataLen, size); mDataLen += size; } else { String strDelay = "Delay"; return strDelay.getBytes(); } } return null; } public synchronized String receivePortText() { byte[] buffer = read(); if (buffer != null && buffer.length > 0) { int length = buffer.length; byte[] xiao = new byte[length]; for(int i=0;i
附參考 ;
/* * Copyright (C) 2013 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.bluetooth.smart.light.server; import java.util.List; import java.util.UUID; import android.app.Service; import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothGatt; import android.bluetooth.BluetoothGattCallback; import android.bluetooth.BluetoothGattCharacteristic; import android.bluetooth.BluetoothGattDescriptor; import android.bluetooth.BluetoothGattServer; import android.bluetooth.BluetoothGattService; import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; import android.content.Intent; import android.os.Binder; import android.os.Bundle; import android.os.Handler; import android.os.IBinder; import android.os.Message; import android.util.Log; /** * Service for managing connection and data communication with a GATT server * hosted on a given Bluetooth LE device. */ public class BluetoothLeService extends Service { private final static String TAG = BluetoothLeService.class.getSimpleName(); private BluetoothManager mBluetoothManager; private BluetoothAdapter mBluetoothAdapter; private String mBluetoothDeviceAddress; private String mBluetoothDeviceAddress1; private String mBluetoothDeviceAddress2; private String mBluetoothDeviceAddress3; private String mBluetoothDeviceAddress4; public static BluetoothGatt mBluetoothGatt; public static BluetoothGatt mBluetoothGatt2; public static BluetoothGatt mBluetoothGatt3; public static BluetoothGatt mBluetoothGatt4; public static BluetoothGatt mBluetoothGatt5; private int mConnectionState = STATE_DISCONNECTED; public BluetoothGattServer mBluetoothGattServer = null; private static final int STATE_DISCONNECTED = 0; private static final int STATE_CONNECTING = 1; private static final int STATE_CONNECTED = 2; public static final int PXP_CONNECT_MSG = 21; public static final int PXP_DISCONNECT_MSG = 22; public static final int PXP_READY_MSG = 23; public static final int PXP_VALUE_MSG = 24; public static final int GATT_DEVICE_FOUND_MSG = 25; public static final int GATT_CHARACTERISTIC_RSSI_MSG = 26; public static final int PROXIMITY_ALERT_LEVEL_CHANGED_MSG = 27; /** Source of device entries in the device list */ public static final int DEVICE_SOURCE_SCAN = 10; public static final int DEVICE_SOURCE_BONDED = 11; public static final int DEVICE_SOURCE_CONNECTED = 12; private Handler mActivityHandler = null; private Handler mDeviceListHandler = null; // public final static String ACTION_GATT_CONNECTED = "com.example.bluetooth.le.ACTION_GATT_CONNECTED"; public final static String ACTION_GATT_DISCONNECTED = "com.example.bluetooth.le.ACTION_GATT_DISCONNECTED"; public final static String ACTION_GATT_SERVICES_DISCOVERED = "com.example.bluetooth.le.ACTION_GATT_SERVICES_DISCOVERED"; public final static String ACTION_DATA_AVAILABLE = "com.example.bluetooth.le.ACTION_DATA_AVAILABLE"; public final static String EXTRA_DATA = "com.example.bluetooth.le.EXTRA_DATA"; // /** Intent extras */ public static final String EXTRA_DEVICE = "DEVICE"; public static final String EXTRA_RSSI = "RSSI"; public static final String EXTRA_SOURCE = "SOURCE"; public static final String EXTRA_ADDR = "ADDRESS"; public static final String EXTRA_CONNECTED = "CONNECTED"; public static final String EXTRA_STATUS = "STATUS"; public static final String EXTRA_UUID = "UUID"; public static final String EXTRA_VALUE = "VALUE"; public static final byte NO_ALERT = 0; public static final byte LOW_ALERT = 1; public static final byte HIGH_ALERT = 2; public final static UUID UUID_HEART_RATE_MEASUREMENT = UUID .fromString(SampleGattAttributes.HEART_RATE_MEASUREMENT); public static final UUID IMMEDIATE_ALERT_UUID = UUID .fromString("00001802-0000-1000-8000-00805f9b34fb"); public static final UUID LINK_LOSS_UUID = UUID .fromString("00001803-0000-1000-8000-00805f9b34fb"); public static final UUID TX_POWER_UUID = UUID .fromString("00001804-0000-1000-8000-00805f9b34fb"); public static final UUID ALERT_LEVEL_UUID = UUID .fromString("00002a06-0000-1000-8000-00805f9b34fb"); public static final UUID TX_POWER_LEVEL_UUID = UUID .fromString("00002a07-0000-1000-8000-00805f9b34fb"); public static final UUID CCC = UUID .fromString("00002902-0000-1000-8000-00805f9b34fb"); public static final UUID FIRMWARE_REVISON_UUID = UUID .fromString("00002a26-0000-1000-8000-00805f9b34fb"); public static final UUID DIS_UUID = UUID .fromString("0000180a-0000-1000-8000-00805f9b34fb"); public static final UUID SERVIE_UUID = UUID .fromString("0000ffe0-0000-1000-8000-00805f9b34fb"); public static final UUID RED_LIGHT_CONTROL_UUID = UUID .fromString("0000ffe1-0000-1000-8000-00805f9b34fb"); public static final UUID GREED_LIGHT_CONTROL_UUID = UUID .fromString("0000ffe2-0000-1000-8000-00805f9b34fb"); public static final UUID BLUE_LIGHT_CONTROL_UUID = UUID .fromString("0000ffe3-0000-1000-8000-00805f9b34fb"); public static final UUID WHITE_LIGHT_CONTROL_UUID = UUID .fromString("0000ffe4-0000-1000-8000-00805f9b34fb"); public static final UUID WRGB_LIGHT_CONTROL_UUID = UUID .fromString("0000ffe5-0000-1000-8000-00805f9b34fb"); public static final UUID SHADE_CONTROL_UUID = UUID .fromString("0000ffe6-0000-1000-8000-00805f9b34fb"); public static final UUID AUTO_SHOT_OFF_UUID = UUID .fromString("0000ffd1-0000-1000-8000-00805f9b34fb"); public static final UUID FADE_SHOT_ON_UUID = UUID .fromString("0000ffd2-0000-1000-8000-00805f9b34fb"); public static final UUID AUTO_SHOT_ON_UUID = UUID .fromString("0000ffd3-0000-1000-8000-00805f9b34fb"); // 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.+1"); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:"+ mBluetoothGatt.discoverServices()); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_CONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); mBluetoothGatt.discoverServices(); // mBluetoothGatt2.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothDeviceAddress = null; intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server.+1"); broadcastUpdate(intentAction); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_DISCONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE,gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); } } @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); } Message msg = Message.obtain(mActivityHandler, PXP_READY_MSG); // msg.sendToTarget(); // DummyReadForSecLevelCheck(device); // 分開發送到PXP Bundle mBundle = new Bundle(); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice().getAddress()); msg.setData(mBundle); msg.sendToTarget(); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (TX_POWER_LEVEL_UUID.equals(characteristic.getUuid())) { Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_VALUE_MSG); mBundle.putByteArray(EXTRA_VALUE, characteristic.getValue()); msg.setData(mBundle); msg.sendToTarget(); } } }; // Implements callback methods for GATT events that the app cares about. For example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback1 = 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.+2"); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt2.discoverServices()); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_CONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); // mBluetoothGatt.discoverServices(); mBluetoothGatt2.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothDeviceAddress1 = null; intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server.+2"); broadcastUpdate(intentAction); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_DISCONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); } } @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); } Message msg = Message.obtain(mActivityHandler, PXP_READY_MSG); // msg.sendToTarget(); // DummyReadForSecLevelCheck(device); // 分開發送到PXP Bundle mBundle = new Bundle(); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() .getAddress()); msg.setData(mBundle); msg.sendToTarget(); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (TX_POWER_LEVEL_UUID.equals(characteristic.getUuid())) { Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_VALUE_MSG); mBundle.putByteArray(EXTRA_VALUE, characteristic.getValue()); msg.setData(mBundle); msg.sendToTarget(); } } }; // Implements callback methods for GATT events that the app cares about. For // example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback2 = 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.+3"); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt3.discoverServices()); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_CONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); mBluetoothGatt3.discoverServices(); // mBluetoothGatt2.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothDeviceAddress2 = null; intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server.+3"); broadcastUpdate(intentAction); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_DISCONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); } } @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); } Message msg = Message.obtain(mActivityHandler, PXP_READY_MSG); // msg.sendToTarget(); // DummyReadForSecLevelCheck(device); // 分開發送到PXP Bundle mBundle = new Bundle(); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() .getAddress()); msg.setData(mBundle); msg.sendToTarget(); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (TX_POWER_LEVEL_UUID.equals(characteristic.getUuid())) { Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_VALUE_MSG); mBundle.putByteArray(EXTRA_VALUE, characteristic.getValue()); msg.setData(mBundle); msg.sendToTarget(); } } }; // Implements callback methods for GATT events that the app cares about. For // example, // connection change and services discovered. private final BluetoothGattCallback mGattCallback3 = 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.+4"); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt4.discoverServices()); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_CONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); mBluetoothGatt4.discoverServices(); // mBluetoothGatt2.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothDeviceAddress3 = null; intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server.+4"); broadcastUpdate(intentAction); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_DISCONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); } } @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); } Message msg = Message.obtain(mActivityHandler, PXP_READY_MSG); // msg.sendToTarget(); // DummyReadForSecLevelCheck(device); // 分開發送到PXP Bundle mBundle = new Bundle(); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() .getAddress()); msg.setData(mBundle); msg.sendToTarget(); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (TX_POWER_LEVEL_UUID.equals(characteristic.getUuid())) { Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_VALUE_MSG); mBundle.putByteArray(EXTRA_VALUE, characteristic.getValue()); msg.setData(mBundle); msg.sendToTarget(); } } }; private final BluetoothGattCallback mGattCallback4 = 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.+5"); // Attempts to discover services after successful connection. Log.i(TAG, "Attempting to start service discovery:" + mBluetoothGatt5.discoverServices()); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_CONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); mBluetoothGatt5.discoverServices(); // mBluetoothGatt2.discoverServices(); } else if (newState == BluetoothProfile.STATE_DISCONNECTED) { mBluetoothDeviceAddress4 = null; intentAction = ACTION_GATT_DISCONNECTED; mConnectionState = STATE_DISCONNECTED; Log.i(TAG, "Disconnected from GATT server.+5"); broadcastUpdate(intentAction); Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_DISCONNECT_MSG); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() + ""); msg.setData(mBundle); msg.sendToTarget(); } } @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); } Message msg = Message.obtain(mActivityHandler, PXP_READY_MSG); // msg.sendToTarget(); // DummyReadForSecLevelCheck(device); // 分開發送到PXP Bundle mBundle = new Bundle(); mBundle.putString(BluetoothDevice.EXTRA_DEVICE, gatt.getDevice() .getAddress()); msg.setData(mBundle); msg.sendToTarget(); } @Override public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) { if (status == BluetoothGatt.GATT_SUCCESS) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); } } @Override public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { broadcastUpdate(ACTION_DATA_AVAILABLE, characteristic); if (TX_POWER_LEVEL_UUID.equals(characteristic.getUuid())) { Bundle mBundle = new Bundle(); Message msg = Message.obtain(mActivityHandler, PXP_VALUE_MSG); mBundle.putByteArray(EXTRA_VALUE, characteristic.getValue()); msg.setData(mBundle); msg.sendToTarget(); } } }; private void broadcastUpdate(final String action) { final Intent intent = new Intent(action); sendBroadcast(intent); } private void broadcastUpdate(final String action, final BluetoothGattCharacteristic characteristic) { final Intent intent = new Intent(action); // This is special handling for the Heart Rate Measurement profile. Data // parsing is // carried out as per profile specifications: // http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.heart_rate_measurement.xml if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { int flag = characteristic.getProperties(); int format = -1; if ((flag & 0x01) != 0) { format = BluetoothGattCharacteristic.FORMAT_UINT16; Log.d(TAG, "Heart rate format UINT16."); } else { format = BluetoothGattCharacteristic.FORMAT_UINT8; Log.d(TAG, "Heart rate format UINT8."); } final int heartRate = characteristic.getIntValue(format, 1); Log.d(TAG, String.format("Received heart rate: %d", heartRate)); intent.putExtra(EXTRA_DATA, String.valueOf(heartRate)); } else { // For all other profiles, writes the data formatted in HEX. final byte[] data = characteristic.getValue(); if (data != null && data.length > 0) { final StringBuilder stringBuilder = new StringBuilder( data.length); for (byte byteChar : data) stringBuilder.append(String.format("%02X ", byteChar)); intent.putExtra(EXTRA_DATA, new String(data) + "\n" + stringBuilder.toString()); } } sendBroadcast(intent); } public class LocalBinder extends Binder { public BluetoothLeService getService() { return BluetoothLeService.this; } } @Override public IBinder onBind(Intent intent) { return mBinder; } @Override public boolean onUnbind(Intent intent) { // After using a given device, you should make sure that // BluetoothGatt.close() is called // such that resources are cleaned up properly. In this particular // example, close() is // invoked when the UI is disconnected from the Service.'= for (int i = 0; i < 5; i++) { close(i); } return super.onUnbind(intent); } private final IBinder mBinder = new LocalBinder(); /** * 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; } /** * 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, int sBluetoothGatt) { if (mBluetoothAdapter == null || address == null) { Log.w(TAG, "BluetoothAdapter not initialized or unspecified address."); return false; } // Previously connected device. Try to reconnect. Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection."); switch (sBluetoothGatt) { case 0: if (mBluetoothDeviceAddress != null&& address.equals(mBluetoothDeviceAddress)) { if (mBluetoothGatt.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } case 1: if (mBluetoothDeviceAddress1 != null && address.equals(mBluetoothDeviceAddress1)) { if (mBluetoothGatt2.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } case 2: if (mBluetoothDeviceAddress2 != null && address.equals(mBluetoothDeviceAddress2)) { if (mBluetoothGatt3.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } case 3: if (mBluetoothDeviceAddress3 != null && address.equals(mBluetoothDeviceAddress3)) { if (mBluetoothGatt4.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } case 4: if (mBluetoothDeviceAddress4 != null && address.equals(mBluetoothDeviceAddress4)) { if (mBluetoothGatt5.connect()) { mConnectionState = STATE_CONNECTING; return true; } else { return false; } } default: break; // } } 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. if (sBluetoothGatt == 1) { mBluetoothGatt = device.connectGatt(this, false, mGattCallback); mBluetoothDeviceAddress = address; } else if (sBluetoothGatt == 2) { mBluetoothGatt2 = device.connectGatt(this, false, mGattCallback1); mBluetoothDeviceAddress1 = address; } else if (sBluetoothGatt == 3) { mBluetoothGatt3 = device.connectGatt(this, false, mGattCallback2); mBluetoothDeviceAddress2 = address; } else if (sBluetoothGatt == 4) { mBluetoothGatt4 = device.connectGatt(this, false, mGattCallback3); mBluetoothDeviceAddress3 = address; } else if (sBluetoothGatt == 5) { mBluetoothGatt5 = device.connectGatt(this, false, mGattCallback4); mBluetoothDeviceAddress4 = address; } Log.d(TAG, "Trying to create a new connection."); mConnectionState = STATE_CONNECTING; return true; } public void writeLlsAlertLevel(String iDevice, int iAlertLevel, int rank, byte[] bb, int index) { BluetoothGatt mBluetoothGatt30 = null; if (index == 0) { mBluetoothGatt30 = mBluetoothGatt; } else if (index == 1) { mBluetoothGatt30 = mBluetoothGatt2; } else if (index == 2) { mBluetoothGatt30 = mBluetoothGatt3; } else if (index == 3) { mBluetoothGatt30 = mBluetoothGatt4; } else if (index == 4) { mBluetoothGatt30 = mBluetoothGatt5; } Log.i("iDevice", iDevice); if (mBluetoothGatt30 != null) { BluetoothGattService linkLossService = mBluetoothGatt30 .getService(SERVIE_UUID); if (linkLossService == null) { showMessage("link loss Alert service not found!"); return; } // enableBattNoti(iDevice); BluetoothGattCharacteristic alertLevel = null; switch (iAlertLevel) { case 1: // red alertLevel = linkLossService .getCharacteristic(RED_LIGHT_CONTROL_UUID); break; case 2: // red alertLevel = linkLossService .getCharacteristic(GREED_LIGHT_CONTROL_UUID); break; case 3: // red alertLevel = linkLossService .getCharacteristic(BLUE_LIGHT_CONTROL_UUID); break; case 4: // red alertLevel = linkLossService .getCharacteristic(WHITE_LIGHT_CONTROL_UUID); break; case 5: // 特殊 alertLevel = linkLossService .getCharacteristic(WRGB_LIGHT_CONTROL_UUID); break; case 6: // 漸變 alertLevel = linkLossService .getCharacteristic(SHADE_CONTROL_UUID); break; default: break; } if (alertLevel == null) { showMessage("link loss Alert Level charateristic not found!"); return; } boolean status = false; int storedLevel = alertLevel.getWriteType(); Log.d(TAG, "storedLevel() - storedLevel=" + storedLevel); switch (rank) { case 1: // byte[] b = new byte[1]; // 紅色 // b[0] = (byte) bb[0]; // alertLevel.setValue(b); // Log.e("對燈發送指令改變顏色", "b0 " + b[0]); BluetoothGattService disService = mBluetoothGatt30 .getService(SERVIE_UUID); BluetoothGattCharacteristic firmwareIdcharc = disService .getCharacteristic(WRGB_LIGHT_CONTROL_UUID); mBluetoothGatt30.readCharacteristic(firmwareIdcharc); return; case 4:// 調色 byte[] b3 = new byte[1]; b3[0] = (byte) bb[3]; alertLevel.setValue(b3); Log.e("對燈發送指令改變顏色", "b3 " + b3[0]); break; case 5:// 調色 // byte[] b4 = new byte[1]; // b3[0] = (byte) bb[3]; alertLevel.setValue(bb); Log.e("對燈發送指令改變顏色", "b5"); break; } // try { // Thread.sleep(50); // } catch (InterruptedException e) { // // TODO Auto-generated catch block // e.printStackTrace(); // } // sharedata.putInt("byte1", bb[0]); // sharedata.putInt("byte2", bb[1]); // sharedata.putInt("byte3", bb[2]); // sharedata.putInt("byte4", bb[3]); // sharedata.commit(); alertLevel.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE); status = mBluetoothGatt30.writeCharacteristic(alertLevel); Log.d(TAG, "writeLlsAlertLevel() - status=" + status); } } /** * Disconnects an existing connection or cancel a pending connection. The * disconnection result is reported asynchronously through the * {@code BluetoothGattCallback#onConnectionStateChange(android.bluetooth.BluetoothGatt, int, int)} * callback. */ public void disconnect(int i) { switch (i) { case 0: if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.disconnect(); break; case 1: if (mBluetoothAdapter == null || mBluetoothGatt2 == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt2.disconnect(); break; case 2: if (mBluetoothAdapter == null || mBluetoothGatt3 == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt3.disconnect(); break; case 3: if (mBluetoothAdapter == null || mBluetoothGatt4 == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt4.disconnect(); break; case 4: if (mBluetoothAdapter == null || mBluetoothGatt5 == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt5.disconnect(); break; } // 關閉服務 close(i); } /** * After using a given BLE device, the app must call this method to ensure * resources are released properly. */ public void close(int i) { switch (i) { case 0: if (mBluetoothGatt == null) { return; } mBluetoothGatt.close(); // mBluetoothGatt = null; break; case 1: if (mBluetoothGatt2 == null) { return; } mBluetoothGatt2.close(); // mBluetoothGatt2 = null; break; case 2: if (mBluetoothGatt3 == null) { return; } mBluetoothGatt3.close(); // mBluetoothGatt3 = null; break; case 3: if (mBluetoothGatt4 == null) { return; } mBluetoothGatt4.close(); // mBluetoothGatt4 = null; break; case 4: if (mBluetoothGatt5 == null) { return; } mBluetoothGatt5.close(); // mBluetoothGatt5 = null; break; } } /** * Request a read on a given {@code BluetoothGattCharacteristic}. The read * result is reported asynchronously through the * {@code BluetoothGattCallback#onCharacteristicRead(android.bluetooth.BluetoothGatt, android.bluetooth.BluetoothGattCharacteristic, int)} * callback. * * @param characteristic * The characteristic to read from. */ public void readCharacteristic(BluetoothGattCharacteristic characteristic) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.readCharacteristic(characteristic); } /** * Enables or disables notification on a give characteristic. * * @param characteristic * Characteristic to act on. * @param enabled * If true, enable notification. False otherwise. */ public void setCharacteristicNotification( BluetoothGattCharacteristic characteristic, boolean enabled) { if (mBluetoothAdapter == null || mBluetoothGatt == null) { Log.w(TAG, "BluetoothAdapter not initialized"); return; } mBluetoothGatt.setCharacteristicNotification(characteristic, enabled); // This is specific to Heart Rate Measurement. if (UUID_HEART_RATE_MEASUREMENT.equals(characteristic.getUuid())) { BluetoothGattDescriptor descriptor = characteristic .getDescriptor(UUID .fromString(SampleGattAttributes.CLIENT_CHARACTERISTIC_CONFIG)); descriptor .setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); mBluetoothGatt.writeDescriptor(descriptor); } } /** * Retrieves a list of supported GATT services on the connected device. This * should be invoked only after {@code BluetoothGatt#discoverServices()} * completes successfully. * * @return A {@code List} of supported services. */ public ListgetSupportedGattServices() { if (mBluetoothGatt != null) { return mBluetoothGatt.getServices(); // } else if (mBluetoothGatt2 != null) { // return mBluetoothGatt2.getServices(); // } } return null; } private void showMessage(String msg) { Log.e(TAG, msg); } public void setActivityHandler(Handler mHandler) { Log.d(TAG, "Activity Handler set"); mActivityHandler = mHandler; } public void setDeviceListHandler(Handler mHandler) { Log.d(TAG, "Device List Handler set"); mDeviceListHandler = mHandler; } }
上拉刷新,即當ListView滾動到底部的時候,再繼續拉取的時候,將出現一個提示告訴你正在加載數據,稍後提示消失,新的數據出現。在這裡,我提供一個想法:ListView自
分享一個下拉刷新的解決辦法,效果圖: Main.java: package example.com.list; import
Android Studio的代碼自動檢測的錯誤提示方式感覺有點奇葩,和Eclipse差別很大,Eclipse檢測到某個資源文件找不到或者錯誤,都會在Project中對應
一、---框架---1、新建一個布局文件,輸入我們想要使用的線程的個數,包括一個主布局文件和一個progressBar(1)一個包括三個控件的主布局(2)一個只包含Pro