From 2d718876b97478b26c25ce0a16b77f460b60a026 Mon Sep 17 00:00:00 2001 From: Douglas Nassif Roma Junior Date: Mon, 10 Apr 2017 16:10:59 -0300 Subject: [PATCH] - Fixing issue with run in main thread - Fixing bug on try to connect to BLE withou TRANSPORT_LE type --- .../BluetoothService.java | 39 +++++++++++++++++-- .../BluetoothLeService.java | 35 +++++++++++++++-- 2 files changed, 68 insertions(+), 6 deletions(-) diff --git a/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothService.java b/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothService.java index 481587d..7527a80 100755 --- a/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothService.java +++ b/BluetoothClassicLibrary/src/main/java/com/github/douglasjunior/bluetoothclassiclibrary/BluetoothService.java @@ -2,6 +2,7 @@ import android.bluetooth.BluetoothDevice; import android.content.Context; +import android.os.Build; import android.os.Handler; import android.os.Looper; import android.util.Log; @@ -92,13 +93,13 @@ public void run() { } protected void runOnMainThread(Runnable runnable, long delayMillis) { - if (!mConfig.callListenersInMainThread || Looper.myLooper() == Looper.getMainLooper()) { - runnable.run(); - } else { + if ((mConfig.callListenersInMainThread && Looper.myLooper() != Looper.getMainLooper()) || delayMillis > 0) { if (delayMillis > 0) handler.postDelayed(runnable, delayMillis); else handler.post(runnable); + } else { + runnable.run(); } } @@ -106,6 +107,12 @@ protected void runOnMainThread(Runnable runnable) { runOnMainThread(runnable, 0); } + protected void removeRunnableFromHandler(Runnable runnable) { + if (handler != null) { + handler.removeCallbacks(runnable); + } + } + public synchronized BluetoothStatus getStatus() { return mStatus; } @@ -147,6 +154,32 @@ public static class BluetoothConfiguration { public UUID uuid; public UUID uuidService; public UUID uuidCharacteristic; + /** + * @see BluetoothDevice#TRANSPORT_AUTO + * @see BluetoothDevice#TRANSPORT_BREDR + * @see BluetoothDevice#TRANSPORT_LE + */ + public int transport; public boolean callListenersInMainThread = true; + + public BluetoothConfiguration() { + setDefaultTransport(); + } + + private void setDefaultTransport() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + transport = BluetoothDevice.TRANSPORT_LE; + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // From Android LOLLIPOP (21) the transport types exists, but them are hide for use, + // so is needed to use relfection to get the value + try { + transport = BluetoothDevice.class.getDeclaredField("TRANSPORT_LE").getInt(null); + } catch (Exception ex) { + Log.d(TAG, "Error on get BluetoothDevice.TRANSPORT_LE with reflection.", ex); + } + } else { + transport = -1; + } + } } } diff --git a/BluetoothLowEnergyLibrary/src/main/java/com/github/douglasjunior/bluetoothlowenergylibrary/BluetoothLeService.java b/BluetoothLowEnergyLibrary/src/main/java/com/github/douglasjunior/bluetoothlowenergylibrary/BluetoothLeService.java index f8f7b27..3f8b067 100644 --- a/BluetoothLowEnergyLibrary/src/main/java/com/github/douglasjunior/bluetoothlowenergylibrary/BluetoothLeService.java +++ b/BluetoothLowEnergyLibrary/src/main/java/com/github/douglasjunior/bluetoothlowenergylibrary/BluetoothLeService.java @@ -11,12 +11,14 @@ import android.bluetooth.BluetoothManager; import android.bluetooth.BluetoothProfile; import android.content.Context; +import android.os.Build; import android.support.annotation.RequiresPermission; import android.util.Log; import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothService; import com.github.douglasjunior.bluetoothclassiclibrary.BluetoothStatus; +import java.lang.reflect.Method; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; @@ -231,8 +233,35 @@ public void connect(BluetoothDevice bluetoothDevice) { if (bluetoothGatt != null) { bluetoothGatt.disconnect(); } + updateState(BluetoothStatus.CONNECTING); - bluetoothGatt = bluetoothDevice.connectGatt(mConfig.context, false, btleGattCallback); + + /* + About this issue: + https://code.google.com/p/android/issues/detail?id=92949 + http://stackoverflow.com/q/27633680/2826279 + */ + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + // If android verion is greather or equal to Android M (23), then call the connectGatt with TRANSPORT_LE. + bluetoothGatt = bluetoothDevice.connectGatt(mConfig.context, false, btleGattCallback, mConfig.transport); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + // From Android LOLLIPOP (21) the transport types exists, but them are hide for use, + // so is needed to use relfection to get the value + try { + Method connectGattMethod = bluetoothDevice.getClass().getDeclaredMethod("connectGatt", Context.class, boolean.class, BluetoothGattCallback.class, int.class); + connectGattMethod.setAccessible(true); + bluetoothGatt = (BluetoothGatt) connectGattMethod.invoke(bluetoothDevice, mConfig.context, false, btleGattCallback, mConfig.transport); + } catch (Exception ex) { + Log.d(TAG, "Error on call BluetoothDevice.connectGatt with reflection.", ex); + } + } + + // If any try is fail, then call the connectGatt without transport + if (bluetoothGatt == null) { + bluetoothGatt = bluetoothDevice.connectGatt(mConfig.context, false, btleGattCallback); + } + } } @@ -338,9 +367,9 @@ private List parseUUIDs(final byte[] advertisedData) { @RequiresPermission(Manifest.permission.BLUETOOTH_ADMIN) @Override public void stopScan() { - runOnMainThread(mStopScanRunnable); + removeRunnableFromHandler(mStopScanRunnable); btAdapter.stopLeScan(mLeScanCallback); - + if (onScanCallback != null) runOnMainThread(new Runnable() { @Override