diff --git a/easyble/src/main/java/com/ficat/easyble/BleDevice.java b/easyble/src/main/java/com/ficat/easyble/BleDevice.java index 833d60a..910b9c9 100644 --- a/easyble/src/main/java/com/ficat/easyble/BleDevice.java +++ b/easyble/src/main/java/com/ficat/easyble/BleDevice.java @@ -11,39 +11,79 @@ */ public class BleDevice implements Parcelable { - public volatile boolean connected; - public volatile boolean connecting; - public String address; - public String name; - private BluetoothDevice device; + private static final String DEFAULT_NAME = "unknown"; + + /** + * Connection state constants + */ + public static final int DISCONNECTED = 1; + public static final int CONNECTING = 2; + public static final int CONNECTED = 3; + + /** + * Current connection state + */ + private volatile int connState = DISCONNECTED; + + private String name; + private final BluetoothDevice device; BleDevice(BluetoothDevice device) { this.device = device; - this.address = device.getAddress(); + tryToGetName(); + } + + public String getAddress() { + return device.getAddress(); + } + + public String getName() { + if (TextUtils.isEmpty(name) || name.equals(DEFAULT_NAME)) { + tryToGetName(); + } + return name; + } + + public boolean isConnected() { + return connState == CONNECTED; + } + + public boolean isConnecting() { + return connState == CONNECTING; + } + public void setConnectionState(int newState) { + synchronized (this) { + this.connState = newState; + } + } + + public int getConnectionState() { + return this.connState; + } + + public BluetoothDevice getDevice() { + return device; + } + + private void tryToGetName() { //Android12(api31) or higher,Bluetooth#getName() needs 'BLUETOOTH_CONNECT' permission try { this.name = device.getName(); } catch (Exception e) { - Logger.e("Failed to call BluetoothDevice#getName() because of no 'BLUETOOTH_CONNECT' permission"); + Logger.d("Failed to call BluetoothDevice#getName() because of no 'BLUETOOTH_CONNECT' permission"); } finally { //Device name got from BluetoothDevice#getName() may be null, so check it - if (TextUtils.isEmpty(this.name)){ - this.name = "unknown"; + if (TextUtils.isEmpty(this.name)) { + this.name = DEFAULT_NAME; } } } - public BluetoothDevice getDevice() { - return device; - } - @Override public String toString() { return "BleDevice{" + - "connected=" + connected + - ", connecting=" + connecting + - ", address='" + address + '\'' + + "connState=" + connState + ", name='" + name + '\'' + ", device=" + device + '}'; @@ -56,17 +96,13 @@ public int describeContents() { @Override public void writeToParcel(Parcel dest, int flags) { - dest.writeByte(this.connected ? (byte) 1 : (byte) 0); - dest.writeByte(this.connecting ? (byte) 1 : (byte) 0); - dest.writeString(this.address); + dest.writeInt(this.connState); dest.writeString(this.name); dest.writeParcelable(this.device, flags); } protected BleDevice(Parcel in) { - this.connected = in.readByte() != 0; - this.connecting = in.readByte() != 0; - this.address = in.readString(); + this.connState = in.readInt(); this.name = in.readString(); this.device = in.readParcelable(BluetoothDevice.class.getClassLoader()); } diff --git a/easyble/src/main/java/com/ficat/easyble/BleManager.java b/easyble/src/main/java/com/ficat/easyble/BleManager.java index a4a33a2..2524724 100644 --- a/easyble/src/main/java/com/ficat/easyble/BleManager.java +++ b/easyble/src/main/java/com/ficat/easyble/BleManager.java @@ -8,7 +8,6 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.location.LocationManager; import android.os.Build; @@ -16,8 +15,8 @@ import com.ficat.easyble.gatt.BleGatt; import com.ficat.easyble.gatt.BleGattImpl; -import com.ficat.easyble.gatt.bean.CharacteristicInfo; -import com.ficat.easyble.gatt.bean.ServiceInfo; +import com.ficat.easyble.gatt.data.CharacteristicInfo; +import com.ficat.easyble.gatt.data.ServiceInfo; import com.ficat.easyble.gatt.callback.BleConnectCallback; import com.ficat.easyble.gatt.callback.BleMtuCallback; import com.ficat.easyble.gatt.callback.BleNotifyCallback; @@ -30,7 +29,7 @@ import com.ficat.easyble.scan.BleScanner; import com.ficat.easyble.utils.PermissionChecker; -import java.lang.reflect.Constructor; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.UUID; @@ -53,14 +52,12 @@ private BleManager() { public BleManager init(Context context) { if (mContext != null) { - Logger.d("you have called init() already"); + Logger.d("You have called init() already!"); return this; } - if (context == null) { - throw new IllegalArgumentException("context is null"); - } + checkNotNull(context, Context.class); if (context instanceof Activity) { - Logger.w("Activity Leak Risk:" + context.getClass().getSimpleName()); + Logger.w("Activity Leak Risk: " + context.getClass().getName()); } mContext = context; mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); @@ -118,9 +115,7 @@ public void startScan(BleScanCallback callback) { } public void startScan(ScanOptions options, BleScanCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("BleScanCallback is null"); - } + checkNotNull(callback, BleScanCallback.class); if (!isBluetoothOn()) { callback.onStart(false, "Bluetooth is not turned on"); return; @@ -163,12 +158,8 @@ public void connect(BleDevice device, BleConnectCallback callback) { } public void connect(BleDevice device, ConnectOptions options, BleConnectCallback callback) { - if (callback == null) { - throw new IllegalArgumentException("BleConnectCallback is null"); - } - if (device == null) { - throw new IllegalArgumentException("BleDevice is null"); - } + checkNotNull(callback, BleConnectCallback.class); + checkNotNull(device, BleDevice.class); if (!isBluetoothOn()) { callback.onStart(false, "Bluetooth is not turned on", device); return; @@ -193,7 +184,7 @@ public void connect(String address, BleConnectCallback callback) { public void connect(String address, ConnectOptions options, BleConnectCallback callback) { checkBluetoothAddress(address); BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address); - BleDevice bleDevice = newBleDevice(device); + BleDevice bleDevice = new BleDevice(device); connect(bleDevice, options, callback); } @@ -203,10 +194,8 @@ public void connect(String address, ConnectOptions options, BleConnectCallback c * @param device remote device */ public void disconnect(BleDevice device) { - if (device == null) { - throw new IllegalArgumentException("BleDevice is null"); - } - disconnect(device.address); + checkNotNull(device, BleDevice.class); + disconnect(device.getAddress()); } /** @@ -346,7 +335,7 @@ public Map> getDeviceServices(BleDevice de if (device == null) { return null; } - return getDeviceServices(device.address); + return getDeviceServices(device.getAddress()); } /** @@ -356,9 +345,7 @@ public Map> getDeviceServices(BleDevice de * @return service information */ public Map> getDeviceServices(String address) { - if (!isAddressValid(address)) { - return null; - } + checkBluetoothAddress(address); return mGatt.getDeviceServices(address); } @@ -379,13 +366,7 @@ public List getConnectedDevices() { */ public boolean isConnected(String address) { checkBluetoothAddress(address); - List deviceList = getConnectedDevices(); - for (BleDevice d : deviceList) { - if (address.equals(d.address)) { - return true; - } - } - return false; + return mGatt.isConnected(address); } /** @@ -433,9 +414,7 @@ private void unregisterBleReceiver() { * Return true if this device supports ble */ public static boolean supportBle(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context is null"); - } + checkNotNull(context, Context.class); return BluetoothAdapter.getDefaultAdapter() != null && context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE); } @@ -446,31 +425,32 @@ public static boolean supportBle(Context context) { *

* Note that if Android12(api31) or higher, only the permission * {@link android.Manifest.permission#BLUETOOTH_CONNECT} has been granted by user, - * calling this method can work. + * calling this method can work, or it will return false directly. * * @param activity activity, note that to get the result whether users have granted * or rejected to enable bluetooth, you should handle the method * onActivityResult() of this activity * @param requestCode enable bluetooth request code + * @return true if the request to turn on bluetooth has started successfully, otherwise false */ - public static void enableBluetooth(Activity activity, int requestCode) { - if (activity == null) { - throw new IllegalArgumentException("Activity is null"); - } + public static boolean enableBluetooth(Activity activity, int requestCode) { + checkNotNull(activity, Activity.class); if (requestCode < 0) { throw new IllegalArgumentException("Request code cannot be negative"); } if (Build.VERSION.SDK_INT >= 31 && !PermissionChecker.isPermissionGranted(activity, Manifest.permission.BLUETOOTH_CONNECT)) { - Logger.e("Android12 or higher, BleManager#enableBluetooth(Activity,int) needs the " + + Logger.i("Android12 or higher, BleManager#enableBluetooth(Activity,int) needs the " + "permission 'android.permission.BLUETOOTH_CONNECT'"); - return; + return false; } BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter != null && !adapter.isEnabled()) { Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); activity.startActivityForResult(intent, requestCode); + return true; } + return false; } /** @@ -491,17 +471,17 @@ public static void toggleBluetooth(boolean enable) { return; } try { - if (enable) { - adapter.enable(); - } else { - if (adapter.isEnabled()) { - adapter.disable(); - } + if (enable == adapter.isEnabled()) { + return; } + // Now, especially high version android device, the result of enable() + // or disable() is unreliable. On some devices even if bluetooth state + // has changed or the request dialog used to turn on/off bluetooth has + // showed, it still return false. + boolean result = enable ? adapter.enable() : adapter.disable(); } catch (SecurityException e) { Logger.e("Android12 or higher, BleManager#toggleBluetooth(boolean) needs the" + " permission 'android.permission.BLUETOOTH_CONNECT'"); - e.printStackTrace(); } } @@ -525,13 +505,32 @@ public static boolean isAddressValid(String address) { return BluetoothAdapter.checkBluetoothAddress(address); } + /** + * Get all permissions BLE required + * + * @return all BLE permissions + */ + public static List getBleRequiredPermissions() { + List list = new ArrayList<>(); + //BLE required permissions + if (Build.VERSION.SDK_INT >= 31) { //Android12 + //BLUETOOTH_SCAN: enable this central device to scan peripheral devices + //BLUETOOTH_CONNECT: used to get peripheral device name (BluetoothDevice#getName()) + list.add(Manifest.permission.BLUETOOTH_SCAN); + list.add(Manifest.permission.BLUETOOTH_CONNECT); + } else if (Build.VERSION.SDK_INT >= 29) {//Android10 + list.add(Manifest.permission.ACCESS_FINE_LOCATION); + } else if (Build.VERSION.SDK_INT >= 23) {//Android6 + list.add(Manifest.permission.ACCESS_COARSE_LOCATION); + } + return list; + } + /** * Check if scan-permission has been granted */ public static boolean isScanPermissionGranted(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context is null"); - } + checkNotNull(context, Context.class); if (Build.VERSION.SDK_INT >= 31) { //Android12 //BLUETOOTH_SCAN: enable this central device to scan peripheral devices //BLUETOOTH_CONNECT: used to get peripheral device name (BluetoothDevice#getName()) @@ -551,9 +550,7 @@ public static boolean isScanPermissionGranted(Context context) { * Check if connection-permission has been granted */ public static boolean isConnectionPermissionGranted(Context context) { - if (context == null) { - throw new IllegalArgumentException("Context is null"); - } + checkNotNull(context, Context.class); //Android12(api31) or higher, BLUETOOTH_CONNECT permission is necessary return Build.VERSION.SDK_INT < 31 || PermissionChecker.isPermissionGranted(context, Manifest.permission.BLUETOOTH_CONNECT); } @@ -577,19 +574,8 @@ public BluetoothGatt getBluetoothGatt(String address) { return mGatt.getBluetoothGatt(address); } - private static int getTargetVersion(Context context) { - int targetSdkVersion = -100; - try { - PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); - targetSdkVersion = info.applicationInfo.targetSdkVersion; - } catch (PackageManager.NameNotFoundException e) { - e.printStackTrace(); - } - return targetSdkVersion; - } - private void checkBluetoothAddress(String address) { - if (!BluetoothAdapter.checkBluetoothAddress(address)) { + if (!isAddressValid(address)) { throw new IllegalArgumentException("Invalid address: " + address); } } @@ -603,16 +589,9 @@ private boolean isGpsOn() { return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); } - private BleDevice newBleDevice(BluetoothDevice device) { - Class clasz = BleDevice.class; - try { - Constructor constructor = clasz.getDeclaredConstructor(BluetoothDevice.class); - constructor.setAccessible(true); - BleDevice d = (BleDevice) constructor.newInstance(device); - return d; - } catch (Exception e) { - Logger.i("Encounter an exception while creating a BleDevice object by reflection: " + e.getMessage()); - return null; + private static void checkNotNull(Object object, Class clasz) { + if (object == null) { + throw new IllegalArgumentException(clasz.getSimpleName() + " is null"); } } diff --git a/easyble/src/main/java/com/ficat/easyble/BleReceiver.java b/easyble/src/main/java/com/ficat/easyble/BleReceiver.java index 1f5268a..defccee 100644 --- a/easyble/src/main/java/com/ficat/easyble/BleReceiver.java +++ b/easyble/src/main/java/com/ficat/easyble/BleReceiver.java @@ -45,8 +45,7 @@ public synchronized void unregisterBluetoothStateChangedListener(BluetoothStateC private void checkNotNull(Object object, Class clasz) { if (object == null) { - String claszSimpleName = clasz.getSimpleName(); - throw new IllegalArgumentException(claszSimpleName + " is null"); + throw new IllegalArgumentException(clasz.getName() + " is null"); } } diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/BleGatt.java b/easyble/src/main/java/com/ficat/easyble/gatt/BleGatt.java index e924bae..1e1fbf4 100644 --- a/easyble/src/main/java/com/ficat/easyble/gatt/BleGatt.java +++ b/easyble/src/main/java/com/ficat/easyble/gatt/BleGatt.java @@ -4,8 +4,8 @@ import android.bluetooth.BluetoothGatt; import com.ficat.easyble.BleDevice; -import com.ficat.easyble.gatt.bean.CharacteristicInfo; -import com.ficat.easyble.gatt.bean.ServiceInfo; +import com.ficat.easyble.gatt.data.CharacteristicInfo; +import com.ficat.easyble.gatt.data.ServiceInfo; import com.ficat.easyble.gatt.callback.BleConnectCallback; import com.ficat.easyble.gatt.callback.BleMtuCallback; import com.ficat.easyble.gatt.callback.BleNotifyCallback; @@ -46,5 +46,7 @@ public interface BleGatt { boolean isConnecting(String address); + boolean isConnected(String address); + void destroy(); } diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/BleGattImpl.java b/easyble/src/main/java/com/ficat/easyble/gatt/BleGattImpl.java index a8a5705..ed9e07a 100644 --- a/easyble/src/main/java/com/ficat/easyble/gatt/BleGattImpl.java +++ b/easyble/src/main/java/com/ficat/easyble/gatt/BleGattImpl.java @@ -16,8 +16,8 @@ import com.ficat.easyble.BleDevice; import com.ficat.easyble.Logger; -import com.ficat.easyble.gatt.bean.CharacteristicInfo; -import com.ficat.easyble.gatt.bean.ServiceInfo; +import com.ficat.easyble.gatt.data.CharacteristicInfo; +import com.ficat.easyble.gatt.data.ServiceInfo; import com.ficat.easyble.gatt.callback.BleCallback; import com.ficat.easyble.gatt.callback.BleConnectCallback; import com.ficat.easyble.gatt.callback.BleMtuCallback; @@ -30,7 +30,7 @@ import java.lang.reflect.Method; import java.util.ArrayList; -import java.util.Collections; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -46,6 +46,9 @@ public class BleGattImpl implements BleGatt { private static final String CHARACTERISTIC_CONFIG = "00002902-0000-1000-8000-00805f9b34fb"; private static final int MAX_CONNECTION_NUM = 7; + private static final int MTU_MAX = 512; + private static final int MTU_MIN = 23; + private static final int ATT_OCCUPY_BYTES_NUM = 3; private Context mContext; private int mConnectTimeout = 10000;//default 10s @@ -58,7 +61,6 @@ public class BleGattImpl implements BleGatt { private Map mNotifyCallbackMap; private Map mReadCallbackMap; private Map mWriteCallbackMap; - private List mConnectedDevices; public BleGattImpl(Context context) { mContext = context; @@ -71,7 +73,6 @@ public BleGattImpl(Context context) { mRssiCallbackMap = new ConcurrentHashMap<>(); mGattMap = new ConcurrentHashMap<>(); mServicesMap = new ConcurrentHashMap<>(); - mConnectedDevices = Collections.synchronizedList(new ArrayList()); } private BluetoothGattCallback mGattCallback = new BluetoothGattCallback() { @@ -94,10 +95,10 @@ public void onConnectionStateChange(BluetoothGatt gatt, final int status, int ne gatt.discoverServices(); break; case BluetoothProfile.STATE_DISCONNECTED: - device.connected = false; refreshDeviceCache(gatt); gatt.close(); removeDevice(device); + device.setConnectionState(BleDevice.DISCONNECTED); mHandler.post(new Runnable() { @Override public void run() { @@ -111,17 +112,17 @@ public void run() { } else { gatt.close(); removeDevice(device); - if (device.connecting) { - device.connecting = false; + if (device.isConnecting()) { mHandler.removeCallbacksAndMessages(address); + device.setConnectionState(BleDevice.DISCONNECTED); mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "connect fail, status = " + status, device); + callback.onFailure(BleCallback.FAIL_OTHER, "Connection failed, status = " + status, device); } }); - } else if (device.connected && newState == BluetoothProfile.STATE_DISCONNECTED) { - device.connected = false; + } else if (device.isConnected() && newState == BluetoothProfile.STATE_DISCONNECTED) { + device.setConnectionState(BleDevice.DISCONNECTED); mHandler.post(new Runnable() { @Override public void run() { @@ -147,16 +148,11 @@ public void onServicesDiscovered(BluetoothGatt gatt, int status) { Map> servicesInfoMap = getServiceInfoMap(gattServices); mServicesMap.put(address, servicesInfoMap); - if (!mConnectedDevices.contains(address)) { - mConnectedDevices.add(address); - } - final BleConnectCallback callback = entry.getValue(); final BleDevice device = entry.getKey(); //remove connection timeout message mHandler.removeCallbacksAndMessages(address); - device.connected = true; - device.connecting = false; + device.setConnectionState(BleDevice.CONNECTED); mHandler.post(new Runnable() { @Override public void run() { @@ -174,8 +170,8 @@ public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic if (status == BluetoothGatt.GATT_SUCCESS) { String address = gatt.getDevice().getAddress(); String serviceUuid = characteristic.getService().getUuid().toString(); - String characteristicUuid = characteristic.getUuid().toString(); - OperationIdentify identify = getOperationIdentifyFromMap(mReadCallbackMap, address, serviceUuid, characteristicUuid); + String charUuid = characteristic.getUuid().toString(); + OperationIdentify identify = getOperationIdentifyFromMap(mReadCallbackMap, address, serviceUuid, charUuid); if (identify == null) { return; } @@ -199,8 +195,8 @@ public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristi if (status == BluetoothGatt.GATT_SUCCESS) { String address = gatt.getDevice().getAddress(); String serviceUuid = characteristic.getService().getUuid().toString(); - String characteristicUuid = characteristic.getUuid().toString(); - OperationIdentify identify = getOperationIdentifyFromMap(mWriteCallbackMap, address, serviceUuid, characteristicUuid); + String charUuid = characteristic.getUuid().toString(); + OperationIdentify identify = getOperationIdentifyFromMap(mWriteCallbackMap, address, serviceUuid, charUuid); if (identify == null) { return; } @@ -223,8 +219,8 @@ public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteris super.onCharacteristicChanged(gatt, characteristic); String address = gatt.getDevice().getAddress(); String serviceUuid = characteristic.getService().getUuid().toString(); - String characteristicUuid = characteristic.getUuid().toString(); - OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, address, serviceUuid, characteristicUuid); + String charUuid = characteristic.getUuid().toString(); + OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, address, serviceUuid, charUuid); if (identify == null) { return; } @@ -247,8 +243,13 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri if (status == BluetoothGatt.GATT_SUCCESS) { String address = gatt.getDevice().getAddress(); String serviceUuid = descriptor.getCharacteristic().getService().getUuid().toString(); - final String characteristicUuid = descriptor.getCharacteristic().getUuid().toString(); - OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, address, serviceUuid, characteristicUuid); + final String charUuid = descriptor.getCharacteristic().getUuid().toString(); + boolean notifiable = Arrays.equals(descriptor.getValue(), BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE) + || Arrays.equals(descriptor.getValue(), BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); + if (!notifiable) { + return; + } + OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, address, serviceUuid, charUuid); if (identify == null) { return; } @@ -258,7 +259,7 @@ public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descri @Override public void run() { if (callback != null) { - callback.onNotifySuccess(characteristicUuid, device); + callback.onNotifySuccess(charUuid, device); } } }); @@ -313,27 +314,25 @@ public void run() { String tips = reachConnectionMaxNum() ? "The master device has reached maximum connection number" : "Turn on bluetooth before starting connecting device"; - callback.onStart(false, - tips, device); + callback.onStart(false, tips, device); } }); return; } - final BleDevice d = getBleDeviceFromMap(device.address, mConnectCallbackMap); + final BleDevice d = getBleDeviceFromMap(device.getAddress(), mConnectCallbackMap); if (d != null) { - if (d.connecting || d.connected) { + if (d.isConnecting() || d.isConnected()) { mHandler.post(new Runnable() { @Override public void run() { - String tips = d.connecting ? - "Connection between master device and the target remote device is in progress" : - "The master device has already connected to this device"; + String tips = d.isConnecting() ? "Connection is establishing" : + "Connection has been established already"; callback.onStart(false, tips, d); } }); return; } - if (d != device) {//we tend to use the newest BleDevice object + if (d != device) {//use the newest BleDevice object mConnectCallbackMap.remove(d); } } @@ -342,34 +341,34 @@ public void run() { final BluetoothGatt gatt = device.getDevice().connectGatt(mContext, false, mGattCallback); if (gatt != null) { - device.connecting = true; - mGattMap.put(device.address, gatt); + device.setConnectionState(BleDevice.CONNECTING); + mGattMap.put(device.getAddress(), gatt); if (connectTimeout > 0) { mConnectTimeout = connectTimeout; } mHandler.post(new Runnable() { @Override public void run() { - callback.onStart(true, "Start connection success!", device); + callback.onStart(true, "Connection started successfully", device); } }); Message msg = Message.obtain(mHandler, new Runnable() { @Override public void run() { - device.connecting = false; refreshDeviceCache(gatt); gatt.close(); - mGattMap.remove(device.address); - callback.onFailure(BleConnectCallback.FAIL_CONNECT_TIMEOUT, "connect timeout", device); + mGattMap.remove(device.getAddress()); + device.setConnectionState(BleDevice.DISCONNECTED); + callback.onFailure(BleCallback.FAIL_CONNECTION_TIMEOUT, "Connection timed out", device); } }); - msg.obj = device.address; + msg.obj = device.getAddress(); mHandler.sendMessageDelayed(msg, mConnectTimeout); } else { mHandler.post(new Runnable() { @Override public void run() { - callback.onStart(false, "unknown reason", device); + callback.onStart(false, "Unknown reason", device); } }); } @@ -385,14 +384,24 @@ public void disconnect(String address) { return; } gatt.disconnect(); - //remove connection timeout message if a connection attempt currently is in progress + //Remove connection timeout message if connection is establishing mHandler.removeCallbacksAndMessages(address); Map.Entry entry = findMapEntry(mConnectCallbackMap, address); if (entry != null) { BleDevice d = entry.getKey(); - if (d.connecting) { - d.connecting = false; + if (d.isConnecting()) { removeDevice(d); + d.setConnectionState(BleDevice.DISCONNECTED); + BleConnectCallback callback = entry.getValue(); + mHandler.post(new Runnable() { + @Override + public void run() { + if (callback != null) { + callback.onFailure(BleCallback.FAIL_CONNECTION_CANCELED, + "You have canceled this connection by calling disconnect() or disconnectAll()", d); + } + } + }); } } } @@ -410,28 +419,28 @@ public void notify(final BleDevice device, String serviceUuid, final String noti if (!checkConnection(device, callback)) { return; } - BluetoothGatt gatt = mGattMap.get(device.address); + BluetoothGatt gatt = mGattMap.get(device.getAddress()); if (!checkUuid(serviceUuid, notifyUuid, gatt, device, callback)) { return; } - OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, device.address, serviceUuid, notifyUuid); + OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, device.getAddress(), serviceUuid, notifyUuid); if (identify != null) { mNotifyCallbackMap.put(identify, callback); } else { - mNotifyCallbackMap.put(new OperationIdentify(device.address, serviceUuid, notifyUuid), callback); + mNotifyCallbackMap.put(new OperationIdentify(device.getAddress(), serviceUuid, notifyUuid), callback); } BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid)); BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(notifyUuid)); - boolean notify = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0; - boolean indicate = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0; - if (!notify && !indicate) { + boolean notifiable = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0; + boolean indicative = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0; + if (!notifiable && !indicative) { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, - "this characteristic doesn't support notification or indication", device); + callback.onFailure(BleNotifyCallback.FAIL_NOTIFICATION_OR_INDICATION_UNSUPPORTED, + "This characteristic doesn't support notification or indication", device); } }); return; @@ -447,10 +456,10 @@ public void run() { }); return; } - if (notify) { + if (notifiable) { descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE); } - if (indicate) { + if (indicative) { descriptor.setValue(BluetoothGattDescriptor.ENABLE_INDICATION_VALUE); } if (gatt.writeDescriptor(descriptor)) { @@ -460,17 +469,41 @@ public void run() { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "setting characteristic notification fail", device); + callback.onFailure(BleCallback.FAIL_OTHER, "Failed to setting characteristic notification", device); } }); } @Override public void cancelNotify(BleDevice device, String serviceUuid, String notifyUuid) { - OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, device.address, serviceUuid, notifyUuid); + OperationIdentify identify = getOperationIdentifyFromMap(mNotifyCallbackMap, device.getAddress(), serviceUuid, notifyUuid); if (identify != null) { mNotifyCallbackMap.remove(identify); } + BluetoothGatt gatt = mGattMap.get(device.getAddress()); + if (gatt == null) { + return; + } + BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid)); + if (service == null) { + return; + } + BluetoothGattCharacteristic characteristic = service.getCharacteristic(UUID.fromString(notifyUuid)); + if (characteristic == null) { + return; + } + boolean notifiable = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0; + boolean indicative = (characteristic.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0; + if (notifiable || indicative) { + if (gatt.setCharacteristicNotification(characteristic, false)) { + BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(CHARACTERISTIC_CONFIG)); + if (descriptor == null) { + return; + } + descriptor.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE); + gatt.writeDescriptor(descriptor); + } + } } @Override @@ -479,16 +512,16 @@ public void read(final BleDevice device, String serviceUuid, String readUuid, fi if (!checkConnection(device, callback)) { return; } - BluetoothGatt gatt = mGattMap.get(device.address); + BluetoothGatt gatt = mGattMap.get(device.getAddress()); if (!checkUuid(serviceUuid, readUuid, gatt, device, callback)) { return; } - OperationIdentify identify = getOperationIdentifyFromMap(mReadCallbackMap, device.address, serviceUuid, readUuid); + OperationIdentify identify = getOperationIdentifyFromMap(mReadCallbackMap, device.getAddress(), serviceUuid, readUuid); if (identify != null) { mReadCallbackMap.put(identify, callback); } else { - mReadCallbackMap.put(new OperationIdentify(device.address, serviceUuid, readUuid), callback); + mReadCallbackMap.put(new OperationIdentify(device.getAddress(), serviceUuid, readUuid), callback); } BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid)); @@ -498,7 +531,7 @@ public void read(final BleDevice device, String serviceUuid, String readUuid, fi mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "the characteristic is not readable", device); + callback.onFailure(BleCallback.FAIL_READ_UNSUPPORTED, "The characteristic is not readable", device); } }); return; @@ -507,7 +540,7 @@ public void run() { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "read fail because of unknown reason", device); + callback.onFailure(BleCallback.FAIL_OTHER, "Failed to initiate the read operation", device); } }); } @@ -516,27 +549,29 @@ public void run() { @Override public void write(final BleDevice device, String serviceUuid, String writeUuid, byte[] data, final BleWriteCallback callback) { checkNotNull(callback, BleWriteCallback.class); - if (data == null || data.length < 1 || data.length > 509) { - callback.onFailure(BleCallback.FAIL_OTHER, data == null ? "data is null" : - "data length must range from 1 to 509", device); + int maxNumPerPack = MTU_MAX - ATT_OCCUPY_BYTES_NUM; + int minNumPerPack = MTU_MIN - ATT_OCCUPY_BYTES_NUM; + if (data == null || data.length < 1 || data.length > maxNumPerPack) { + callback.onFailure(BleCallback.FAIL_OTHER, data == null ? "Data is null" : + "Data length must range from 1 to " + maxNumPerPack, device); return; } - if (data.length > 20) { - Logger.w("data length is greater than the default(20 bytes), make sure MTU >= " + (data.length + 3)); + if (data.length > minNumPerPack) { + Logger.w("Data length is greater than the default(20 Bytes), make sure MTU >= " + (data.length + 3)); } if (!checkConnection(device, callback)) { return; } - BluetoothGatt gatt = mGattMap.get(device.address); + BluetoothGatt gatt = mGattMap.get(device.getAddress()); if (!checkUuid(serviceUuid, writeUuid, gatt, device, callback)) { return; } - OperationIdentify identify = getOperationIdentifyFromMap(mWriteCallbackMap, device.address, serviceUuid, writeUuid); + OperationIdentify identify = getOperationIdentifyFromMap(mWriteCallbackMap, device.getAddress(), serviceUuid, writeUuid); if (identify != null) { mWriteCallbackMap.put(identify, callback); } else { - mWriteCallbackMap.put(new OperationIdentify(device.address, serviceUuid, writeUuid), callback); + mWriteCallbackMap.put(new OperationIdentify(device.getAddress(), serviceUuid, writeUuid), callback); } BluetoothGattService service = gatt.getService(UUID.fromString(serviceUuid)); @@ -547,7 +582,7 @@ public void write(final BleDevice device, String serviceUuid, String writeUuid, mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "the characteristic is not writable", device); + callback.onFailure(BleCallback.FAIL_WRITE_UNSUPPORTED, "The characteristic is not writable", device); } }); return; @@ -556,7 +591,7 @@ public void run() { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "write fail because of unknown reason", device); + callback.onFailure(BleCallback.FAIL_OTHER, "Failed to initiate the write operation", device); } }); } @@ -567,11 +602,12 @@ public void writeByBatch(BleDevice device, final String serviceUuid, final Strin final byte[] writeData, int lengthPerPackage, final long writeDelay, final BleWriteByBatchCallback callback) { checkNotNull(callback, BleWriteByBatchCallback.class); if (writeData == null || writeData.length == 0) { - callback.onFailure(BleCallback.FAIL_OTHER, "writeData is null or no writing data", device); + callback.onFailure(BleCallback.FAIL_OTHER, "WriteData is null or no writing data", device); return; } - if (lengthPerPackage < 1 || lengthPerPackage > 509) { - callback.onFailure(BleCallback.FAIL_OTHER, "lengthPerPackage is invalid, it must range from 1 to 509", device); + int maxNumPerPack = MTU_MAX - ATT_OCCUPY_BYTES_NUM; + if (lengthPerPackage < 1 || lengthPerPackage > maxNumPerPack) { + callback.onFailure(BleCallback.FAIL_OTHER, "LengthPerPackage is invalid, it must range from 1 to " + maxNumPerPack, device); return; } final Queue queue = SplitBleDataUtils.getBatchData(writeData, lengthPerPackage); @@ -611,13 +647,13 @@ public void readRssi(final BleDevice device, final BleRssiCallback callback) { if (!checkConnection(device, callback)) { return; } - mRssiCallbackMap.put(device.address, callback); - BluetoothGatt gatt = mGattMap.get(device.address); + mRssiCallbackMap.put(device.getAddress(), callback); + BluetoothGatt gatt = mGattMap.get(device.getAddress()); if (gatt == null || !gatt.readRemoteRssi()) { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "fail to read rssi because of unknown reason", device); + callback.onFailure(BleCallback.FAIL_OTHER, "Failed to request RSSI value", device); } }); } @@ -640,18 +676,18 @@ public void run() { if (!checkConnection(device, callback)) { return; } - mMtuCallbackMap.put(device.address, callback); - BluetoothGatt gatt = mGattMap.get(device.address); - if (mtu < 23) { - mtu = 23; - } else if (mtu > 512) { - mtu = 512; + mMtuCallbackMap.put(device.getAddress(), callback); + BluetoothGatt gatt = mGattMap.get(device.getAddress()); + if (mtu < MTU_MIN) { + mtu = MTU_MIN; + } else if (mtu > MTU_MAX) { + mtu = MTU_MAX; } if (gatt == null || !gatt.requestMtu(mtu)) { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, "fail to read rssi because of unknown reason", device); + callback.onFailure(BleCallback.FAIL_OTHER, "Failed to request MTU value", device); } }); } @@ -660,9 +696,10 @@ public void run() { @Override public List getConnectedDevices() { List deviceList = new ArrayList<>(); - for (String address : mConnectedDevices) { - BleDevice d = getBleDeviceFromMap(address, mConnectCallbackMap); - deviceList.add(d); + for (BleDevice d : mConnectCallbackMap.keySet()) { + if (d.isConnected()) { + deviceList.add(d); + } } return deviceList; } @@ -670,7 +707,17 @@ public List getConnectedDevices() { @Override public boolean isConnecting(String address) { for (BleDevice d : mConnectCallbackMap.keySet()) { - if (d.connecting && d.address.equals(address)) { + if (d.isConnecting() && d.getAddress().equals(address)) { + return true; + } + } + return false; + } + + @Override + public boolean isConnected(String address) { + for (BleDevice d : mConnectCallbackMap.keySet()) { + if (d.isConnected() && d.getAddress().equals(address)) { return true; } } @@ -699,24 +746,23 @@ public void destroy() { private void checkNotNull(Object object, Class clasz) { if (object == null) { - String claszSimpleName = clasz.getSimpleName(); - throw new IllegalArgumentException(claszSimpleName + " is null"); + throw new IllegalArgumentException(clasz.getSimpleName() + " is null"); } } private boolean checkConnection(final BleDevice device, final BleCallback callback) { checkNotNull(device, BleDevice.class); - if (!mConnectedDevices.contains(device.address)) { + boolean connected = device.isConnected(); + if (!connected) { mHandler.post(new Runnable() { @Override public void run() { callback.onFailure(BleCallback.FAIL_DISCONNECTED, - "Connection between master device and target remote device has not been established yet", device); + "Connection is established yet", device); } }); - return false; } - return true; + return connected; } private boolean checkUuid(String serviceUuid, String charUuid, BluetoothGatt gatt, @@ -729,8 +775,9 @@ private boolean checkUuid(String serviceUuid, String charUuid, BluetoothGatt gat mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, - "the remote device doesn't contain this service uuid", device); + callback.onFailure(BleCallback.FAIL_SERVICE_NOT_FOUND, + "The specified service was not found in the remote device, " + + "make sure service uuid is correct", device); } }); return false; @@ -740,8 +787,9 @@ public void run() { mHandler.post(new Runnable() { @Override public void run() { - callback.onFailure(BleCallback.FAIL_OTHER, - "the service of remote device doesn't contain this characteristic uuid", device); + callback.onFailure(BleCallback.FAIL_CHARACTERISTIC_NOT_FOUND_IN_SERVICE, + "The specified characteristic was not found in the service," + + " make sure characteristic and service uuid is correct", device); } }); return false; @@ -755,7 +803,7 @@ private Map.Entry findMapEntry(Map map, String a } Set> set = map.entrySet(); for (Map.Entry entry : set) { - if (entry.getKey().address.equals(address)) { + if (entry.getKey().getAddress().equals(address)) { return entry; } } @@ -788,17 +836,15 @@ private OperationIdentify getOperationIdentifyFromMap(Map> getServiceInfoMap(List gattServices) { Map> servicesInfoMap = new HashMap<>(); for (BluetoothGattService service : gattServices) { - String uuid = service.getUuid().toString(); - ServiceInfo serviceInfo = new ServiceInfo(uuid); + ServiceInfo serviceInfo = new ServiceInfo(service.getUuid()); List charactInfos = new ArrayList<>(); for (BluetoothGattCharacteristic ch : service.getCharacteristics()) { - String chUuid = ch.getUuid().toString(); boolean readable = (ch.getProperties() & BluetoothGattCharacteristic.PROPERTY_READ) > 0; boolean writable = (ch.getProperties() & (BluetoothGattCharacteristic.PROPERTY_WRITE | BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE)) > 0; - boolean notify = (ch.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0; + boolean notifiable = (ch.getProperties() & BluetoothGattCharacteristic.PROPERTY_NOTIFY) > 0; boolean indicate = (ch.getProperties() & BluetoothGattCharacteristic.PROPERTY_INDICATE) > 0; - CharacteristicInfo charactInfo = new CharacteristicInfo(chUuid, readable, writable, notify, indicate); + CharacteristicInfo charactInfo = new CharacteristicInfo(ch.getUuid(), readable, writable, notifiable, indicate); charactInfos.add(charactInfo); } servicesInfoMap.put(serviceInfo, charactInfos); @@ -808,14 +854,13 @@ private Map> getServiceInfoMap(List void removeOperationIdentify(String address, Map map) { @@ -835,7 +880,6 @@ private void clearAllCallbacks() { mRssiCallbackMap.clear(); mGattMap.clear(); mServicesMap.clear(); - mConnectedDevices.clear(); } /** @@ -858,7 +902,7 @@ private boolean isBluetoothEnable() { } private boolean reachConnectionMaxNum() { - return mConnectedDevices.size() >= MAX_CONNECTION_NUM; + return getConnectedDevices().size() >= MAX_CONNECTION_NUM; } private static final class OperationIdentify { diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/bean/CharacteristicInfo.java b/easyble/src/main/java/com/ficat/easyble/gatt/bean/CharacteristicInfo.java deleted file mode 100644 index 8b2adfa..0000000 --- a/easyble/src/main/java/com/ficat/easyble/gatt/bean/CharacteristicInfo.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.ficat.easyble.gatt.bean; - -import java.io.Serializable; - -/** - * Created by pw on 2018/9/19. - */ - -public class CharacteristicInfo implements Serializable { - public String uuid; - public boolean readable; - public boolean writable; - public boolean notify; - public boolean indicative; - - public CharacteristicInfo(String uuid, boolean readable, boolean writable, boolean notify, boolean indicative) { - this.uuid = uuid; - this.readable = readable; - this.writable = writable; - this.notify = notify; - this.indicative = indicative; - } - - @Override - public String toString() { - return "CharacteristicInfo{" + - "uuid='" + uuid + '\'' + - ", readable=" + readable + - ", writable=" + writable + - ", notify=" + notify + - ", indicative=" + indicative + - '}'; - } -} diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/bean/ServiceInfo.java b/easyble/src/main/java/com/ficat/easyble/gatt/bean/ServiceInfo.java deleted file mode 100644 index b953f4b..0000000 --- a/easyble/src/main/java/com/ficat/easyble/gatt/bean/ServiceInfo.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.ficat.easyble.gatt.bean; - -import java.io.Serializable; - - -public class ServiceInfo implements Serializable { - public String uuid; - - public ServiceInfo(String uuid) { - this.uuid = uuid; - } - - @Override - public String toString() { - return "ServiceInfo{" + - "uuid='" + uuid + '\'' + - '}'; - } -} diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleCallback.java b/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleCallback.java index a574f6d..1dd6153 100644 --- a/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleCallback.java +++ b/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleCallback.java @@ -8,8 +8,15 @@ */ public interface BleCallback { - int FAIL_DISCONNECTED = 200; - int FAIL_OTHER = 201; + int FAIL_DISCONNECTED = 200; //connection with remote device is not established yet + int FAIL_CONNECTION_TIMEOUT = 201;//connection timed out + int FAIL_CONNECTION_CANCELED = 202;//connection canceled + int FAIL_SERVICE_NOT_FOUND = 203; //specified service not found + int FAIL_CHARACTERISTIC_NOT_FOUND_IN_SERVICE = 204; //specified characteristic not found in specified service + int FAIL_NOTIFICATION_OR_INDICATION_UNSUPPORTED = 205; //specified characteristic doesn't support notification or indication + int FAIL_READ_UNSUPPORTED = 206; //specified characteristic doesn't support reading + int FAIL_WRITE_UNSUPPORTED = 207; //specified characteristic doesn't support writing + int FAIL_OTHER = 208;//unknown reason void onFailure(int failCode, String info, BleDevice device); } diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleConnectCallback.java b/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleConnectCallback.java index f7a82d3..af9506e 100644 --- a/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleConnectCallback.java +++ b/easyble/src/main/java/com/ficat/easyble/gatt/callback/BleConnectCallback.java @@ -4,9 +4,7 @@ import com.ficat.easyble.BleDevice; public interface BleConnectCallback extends BleCallback { - int FAIL_CONNECT_TIMEOUT = 300; - - void onStart(boolean startConnectSuccess, String info, BleDevice device); + void onStart(boolean startSuccess, String info, BleDevice device); void onConnected(BleDevice device); diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/data/CharacteristicInfo.java b/easyble/src/main/java/com/ficat/easyble/gatt/data/CharacteristicInfo.java new file mode 100644 index 0000000..8f7e8bd --- /dev/null +++ b/easyble/src/main/java/com/ficat/easyble/gatt/data/CharacteristicInfo.java @@ -0,0 +1,55 @@ +package com.ficat.easyble.gatt.data; + +import java.io.Serializable; +import java.util.UUID; + +/** + * Created by pw on 2018/9/19. + */ + +public class CharacteristicInfo implements Serializable { + private final UUID uuid; + private final boolean readable; + private final boolean writable; + private final boolean notifiable; + private final boolean indicative; + + public CharacteristicInfo(UUID uuid, boolean readable, boolean writable, boolean notifiable, boolean indicative) { + this.uuid = new UUID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + this.readable = readable; + this.writable = writable; + this.notifiable = notifiable; + this.indicative = indicative; + } + + public UUID getUuid() { + return uuid; + } + + public boolean isReadable() { + return readable; + } + + public boolean isWritable() { + return writable; + } + + public boolean isNotifiable() { + return notifiable; + } + + public boolean isIndicative() { + return indicative; + } + + @Override + public String toString() { + return "CharacteristicInfo{" + + "uuid=" + uuid + + ", readable=" + readable + + ", writable=" + writable + + ", notifiable=" + notifiable + + ", indicative=" + indicative + + '}'; + } +} diff --git a/easyble/src/main/java/com/ficat/easyble/gatt/data/ServiceInfo.java b/easyble/src/main/java/com/ficat/easyble/gatt/data/ServiceInfo.java new file mode 100644 index 0000000..82ecac7 --- /dev/null +++ b/easyble/src/main/java/com/ficat/easyble/gatt/data/ServiceInfo.java @@ -0,0 +1,24 @@ +package com.ficat.easyble.gatt.data; + +import java.io.Serializable; +import java.util.UUID; + + +public class ServiceInfo implements Serializable { + private final UUID uuid; + + public ServiceInfo(UUID uuid) { + this.uuid = new UUID(uuid.getMostSignificantBits(), uuid.getLeastSignificantBits()); + } + + public UUID getUuid() { + return uuid; + } + + @Override + public String toString() { + return "ServiceInfo{" + + "uuid=" + uuid + + '}'; + } +} diff --git a/sample/src/main/java/com/ficat/sample/MainActivity.java b/sample/src/main/java/com/ficat/sample/MainActivity.java index 8116dfa..8df481a 100644 --- a/sample/src/main/java/com/ficat/sample/MainActivity.java +++ b/sample/src/main/java/com/ficat/sample/MainActivity.java @@ -163,7 +163,7 @@ private void startScan() { @Override public void onLeScan(BleDevice device, int rssi, byte[] scanRecord) { for (BleDevice d : deviceList) { - if (device.address.equals(d.address)) { + if (device.getAddress().equals(d.getAddress())) { return; } } diff --git a/sample/src/main/java/com/ficat/sample/OperateActivity.java b/sample/src/main/java/com/ficat/sample/OperateActivity.java index a3201b1..ced9736 100644 --- a/sample/src/main/java/com/ficat/sample/OperateActivity.java +++ b/sample/src/main/java/com/ficat/sample/OperateActivity.java @@ -16,13 +16,14 @@ import com.ficat.easyble.BleDevice; import com.ficat.easyble.BleManager; import com.ficat.easyble.Logger; -import com.ficat.easyble.gatt.bean.CharacteristicInfo; -import com.ficat.easyble.gatt.bean.ServiceInfo; +import com.ficat.easyble.gatt.callback.BleCallback; import com.ficat.easyble.gatt.callback.BleConnectCallback; import com.ficat.easyble.gatt.callback.BleNotifyCallback; import com.ficat.easyble.gatt.callback.BleReadCallback; import com.ficat.easyble.gatt.callback.BleRssiCallback; import com.ficat.easyble.gatt.callback.BleWriteCallback; +import com.ficat.easyble.gatt.data.CharacteristicInfo; +import com.ficat.easyble.gatt.data.ServiceInfo; import com.ficat.sample.adapter.DeviceServiceInfoAdapter; import com.ficat.sample.utils.ByteUtils; @@ -63,7 +64,7 @@ private void initData() { private void addDeviceInfoDataAndUpdate() { if (device == null) return; - Map> deviceInfo = BleManager.getInstance().getDeviceServices(device.address); + Map> deviceInfo = BleManager.getInstance().getDeviceServices(device.getAddress()); if (deviceInfo == null) { return; } @@ -108,9 +109,9 @@ private void initView() { tvWrite.setOnClickListener(this); tvNotify.setOnClickListener(this); - tvDeviceName.setText(getResources().getString(R.string.device_name_prefix) + device.name); - tvAddress.setText(getResources().getString(R.string.device_address_prefix) + device.address); - updateConnectionStateUi(BleManager.getInstance().isConnected(device.address)); + tvDeviceName.setText(getResources().getString(R.string.device_name_prefix) + device.getName()); + tvAddress.setText(getResources().getString(R.string.device_address_prefix) + device.getAddress()); + updateConnectionStateUi(BleManager.getInstance().isConnected(device.getAddress())); } private void initElv() { @@ -136,27 +137,27 @@ public boolean onChildClick(ExpandableListView expandableListView, View view, in private void updateOperationUi(ServiceInfo service, CharacteristicInfo charInfo) { String extra = getResources().getString(R.string.current_operate_uuid) + "\n" + "service:\n " + - service.uuid + "\n" + "characteristic:\n " + charInfo.uuid; + service.getUuid().toString() + "\n" + "characteristic:\n " + charInfo.getUuid().toString(); tvInfoCurrentUuid.setText(extra); tvWriteResult.setText(R.string.write_result); tvReadResult.setText(R.string.read_result); - llRead.setVisibility(charInfo.readable ? View.VISIBLE : View.GONE); - llWrite.setVisibility(charInfo.writable ? View.VISIBLE : View.GONE); - tvNotify.setVisibility((charInfo.notify || charInfo.indicative) ? View.VISIBLE : View.GONE); + llRead.setVisibility(charInfo.isReadable() ? View.VISIBLE : View.GONE); + llWrite.setVisibility(charInfo.isWritable() ? View.VISIBLE : View.GONE); + tvNotify.setVisibility((charInfo.isNotifiable() || charInfo.isIndicative()) ? View.VISIBLE : View.GONE); } private void updateConnectionStateUi(boolean connected) { String state; - if (device.connected) { + if (device.isConnected()) { state = getResources().getString(R.string.connection_state_connected); - } else if (device.connecting) { + } else if (device.isConnecting()) { state = getResources().getString(R.string.connection_state_connecting); } else { state = getResources().getString(R.string.connection_state_disconnected); } - pb.setVisibility(device.connecting ? View.VISIBLE : View.INVISIBLE); + pb.setVisibility(device.isConnecting() ? View.VISIBLE : View.INVISIBLE); tvConnectionState.setText(state); - tvConnectionState.setTextColor(getResources().getColor(device.connected ? R.color.bright_blue : R.color.bright_red)); + tvConnectionState.setTextColor(getResources().getColor(device.isConnected() ? R.color.bright_blue : R.color.bright_red)); } private void updateNotificationInfo(String notification) { @@ -190,22 +191,23 @@ private void reset() { @Override public void onClick(View v) { if (v.getId() == R.id.tv_connect) { - BleManager.getInstance().connect(device.address, connectCallback); + BleManager.getInstance().connect(device.getAddress(), connectCallback); return; } - if (!BleManager.getInstance().isConnected(device.address)) { + if (!BleManager.getInstance().isConnected(device.getAddress())) { Toast.makeText(this, getResources().getString(R.string.tips_connection_disconnected), Toast.LENGTH_SHORT).show(); return; } switch (v.getId()) { case R.id.tv_disconnect: - BleManager.getInstance().disconnect(device.address); + BleManager.getInstance().disconnect(device.getAddress()); break; case R.id.tv_read_rssi: BleManager.getInstance().readRssi(device, rssiCallback); break; case R.id.tv_read: - BleManager.getInstance().read(device, curService.uuid, curCharacteristic.uuid, readCallback); + BleManager.getInstance().read(device, curService.getUuid().toString(), + curCharacteristic.getUuid().toString(), readCallback); break; case R.id.tv_write: String str = etWrite.getText().toString(); @@ -213,10 +215,12 @@ public void onClick(View v) { Toast.makeText(this, getResources().getString(R.string.tips_write_operation), Toast.LENGTH_SHORT).show(); return; } - BleManager.getInstance().write(device, curService.uuid, curCharacteristic.uuid, ByteUtils.hexStr2Bytes(str), writeCallback); + BleManager.getInstance().write(device, curService.getUuid().toString(), + curCharacteristic.getUuid().toString(), ByteUtils.hexStr2Bytes(str), writeCallback); break; case R.id.tv_notify_or_indicate: - BleManager.getInstance().notify(device, curService.uuid, curCharacteristic.uuid, notifyCallback); + BleManager.getInstance().notify(device, curService.getUuid().toString(), + curCharacteristic.getUuid().toString(), notifyCallback); break; default: break; @@ -226,8 +230,8 @@ public void onClick(View v) { @Override protected void onStop() { super.onStop(); - if (isFinishing() && device != null && !TextUtils.isEmpty(device.address)) { - BleManager.getInstance().disconnect(device.address); + if (isFinishing() && device != null && !TextUtils.isEmpty(device.getAddress())) { + BleManager.getInstance().disconnect(device.getAddress()); } } @@ -259,7 +263,7 @@ public void onDisconnected(String info, int status, BleDevice device) { public void onFailure(int failCode, String info, BleDevice device) { Logger.e("connect fail:" + info); Toast.makeText(OperateActivity.this, - getResources().getString(failCode == BleConnectCallback.FAIL_CONNECT_TIMEOUT ? + getResources().getString(failCode == BleCallback.FAIL_CONNECTION_TIMEOUT ? R.string.tips_connect_timeout : R.string.tips_connect_fail), Toast.LENGTH_LONG).show(); reset(); updateConnectionStateUi(false); diff --git a/sample/src/main/java/com/ficat/sample/adapter/DeviceServiceInfoAdapter.java b/sample/src/main/java/com/ficat/sample/adapter/DeviceServiceInfoAdapter.java index d40f7f3..ed2fd48 100644 --- a/sample/src/main/java/com/ficat/sample/adapter/DeviceServiceInfoAdapter.java +++ b/sample/src/main/java/com/ficat/sample/adapter/DeviceServiceInfoAdapter.java @@ -5,8 +5,8 @@ import android.view.ViewGroup; import android.widget.TextView; -import com.ficat.easyble.gatt.bean.CharacteristicInfo; -import com.ficat.easyble.gatt.bean.ServiceInfo; +import com.ficat.easyble.gatt.data.CharacteristicInfo; +import com.ficat.easyble.gatt.data.ServiceInfo; import com.ficat.sample.R; import java.util.List; @@ -21,25 +21,25 @@ public DeviceServiceInfoAdapter(@NonNull Context context, @NonNull List