Advertisement
Guest User

Untitled

a guest
Feb 28th, 2017
64
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.68 KB | None | 0 0
  1. protected class ConnectBroadcastReceiver extends BroadcastReceiver {
  2.  
  3. @Override
  4. public void onReceive(@NonNull Context context, @NonNull Intent intent) {
  5. logger.v(TAG + "------------------------ConnectBroadcastReceiver : onReceive " + intent.getAction());
  6. if ((intent.getAction().equals(BluetoothDevice.ACTION_ACL_CONNECTED))) {
  7. logger.v(TAG + "------------------------ConnectBroadcastReceiver : onReceive " + intent.getAction());
  8. logger.v(TAG + "PairingBroadcastReceiver : CONNECTED");
  9. }
  10. if (intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
  11. BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  12. if (bluetoothAdapter.isEnabled()) {
  13. bleDeviceManager.setApplicationContext(BluetoothLeService.this);
  14. bleDeviceManager.connectAll(bluetoothAdapter);
  15. }
  16. }
  17. }
  18. }
  19.  
  20. IntentFilter filter = new IntentFilter();
  21. filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECT_REQUESTED);
  22. filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
  23. filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
  24. filter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
  25. filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
  26. registerReceiver(connectBroadcastReceiver, filter);
  27.  
  28. @Override
  29. public void connectAll(final BluetoothAdapter bluetoothAdapter) {
  30. mainThreadHandler.postDelayed(new Runnable() {
  31. @Override
  32. public void run() {
  33. connectedGatt.clear();
  34. devicesList.clear();
  35. deviceHandlerMap.clear();
  36. logger.d(TAG + "connectAll");
  37. List<Sensor> sensors = databaseRepository.getConnectedSensors();
  38. for (Sensor sensor : sensors) {
  39. BluetoothDevice device = bluetoothAdapter.getRemoteDevice(sensor.getAddress());
  40. connectedGatt.add(new BleConnectionCompat(applicationContext, logger).connectGatt(device, true, callback));
  41. logger.d(TAG + "connect " + device.getName() + " " + device.getAddress());
  42. }
  43.  
  44. }
  45. }, 10000);
  46. }
  47.  
  48. public class BleConnectionCompat {
  49.  
  50. private final Context context;
  51. private Logger logger;
  52.  
  53. public BleConnectionCompat(Context context, Logger logger) {
  54. this.context = context;
  55. this.logger = logger;
  56. }
  57.  
  58. public BluetoothGatt connectGatt(BluetoothDevice remoteDevice, boolean autoConnect, BluetoothGattCallback bluetoothGattCallback) {
  59.  
  60. if (remoteDevice == null) {
  61. return null;
  62. }
  63.  
  64. /**
  65. * Issue that caused a race condition mentioned below was fixed in 7.0.0_r1
  66. * https://android.googlesource.com/platform/frameworks/base/+/android-7.0.0_r1/core/java/android/bluetooth/BluetoothGatt.java#649
  67. * compared to
  68. * https://android.googlesource.com/platform/frameworks/base/+/android-6.0.1_r72/core/java/android/bluetooth/BluetoothGatt.java#739
  69. * issue: https://android.googlesource.com/platform/frameworks/base/+/d35167adcaa40cb54df8e392379dfdfe98bcdba2%5E%21/#F0
  70. */
  71. if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || !autoConnect) {
  72. return connectGattCompat(bluetoothGattCallback, remoteDevice, autoConnect);
  73. }
  74.  
  75. /**
  76. * Some implementations of Bluetooth Stack have a race condition where autoConnect flag
  77. * is not properly set before calling connectGatt. That's the reason for using reflection
  78. * to set the flag manually.
  79. */
  80.  
  81. try {
  82. logger.v("Trying to connectGatt using reflection.");
  83. Object iBluetoothGatt = getIBluetoothGatt(getIBluetoothManager());
  84.  
  85. if (iBluetoothGatt == null) {
  86. logger.w("Couldn't get iBluetoothGatt object");
  87. return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
  88. }
  89.  
  90. BluetoothGatt bluetoothGatt = createBluetoothGatt(iBluetoothGatt, remoteDevice);
  91.  
  92. if (bluetoothGatt == null) {
  93. logger.w("Couldn't create BluetoothGatt object");
  94. return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
  95. }
  96.  
  97. boolean connectedSuccessfully = connectUsingReflection(bluetoothGatt, bluetoothGattCallback, true);
  98.  
  99. if (!connectedSuccessfully) {
  100. logger.w("Connection using reflection failed, closing gatt");
  101. bluetoothGatt.close();
  102. }
  103.  
  104. return bluetoothGatt;
  105. } catch (NoSuchMethodException
  106. | IllegalAccessException
  107. | IllegalArgumentException
  108. | InvocationTargetException
  109. | InstantiationException
  110. | NoSuchFieldException exception) {
  111. logger.w(exception + "Error during reflection");
  112. return connectGattCompat(bluetoothGattCallback, remoteDevice, true);
  113. }
  114. }
  115.  
  116. private BluetoothGatt connectGattCompat(BluetoothGattCallback bluetoothGattCallback, BluetoothDevice device, boolean autoConnect) {
  117. logger.v("Connecting without reflection");
  118.  
  119. if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
  120. return device.connectGatt(context, autoConnect, bluetoothGattCallback, TRANSPORT_LE);
  121. } else {
  122. return device.connectGatt(context, autoConnect, bluetoothGattCallback);
  123. }
  124. }
  125.  
  126. private boolean connectUsingReflection(BluetoothGatt bluetoothGatt, BluetoothGattCallback bluetoothGattCallback, boolean autoConnect)
  127. throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
  128. logger.v("Connecting using reflection");
  129. setAutoConnectValue(bluetoothGatt, autoConnect);
  130. Method connectMethod = bluetoothGatt.getClass().getDeclaredMethod("connect", Boolean.class, BluetoothGattCallback.class);
  131. connectMethod.setAccessible(true);
  132. return (Boolean) (connectMethod.invoke(bluetoothGatt, true, bluetoothGattCallback));
  133. }
  134.  
  135. @TargetApi(Build.VERSION_CODES.M)
  136. private BluetoothGatt createBluetoothGatt(Object iBluetoothGatt, BluetoothDevice remoteDevice)
  137. throws IllegalAccessException, InvocationTargetException, InstantiationException {
  138. Constructor bluetoothGattConstructor = BluetoothGatt.class.getDeclaredConstructors()[0];
  139. bluetoothGattConstructor.setAccessible(true);
  140. logger.v("Found constructor with args count = " + bluetoothGattConstructor.getParameterTypes().length);
  141.  
  142. if (bluetoothGattConstructor.getParameterTypes().length == 4) {
  143. return (BluetoothGatt) (bluetoothGattConstructor.newInstance(context, iBluetoothGatt, remoteDevice, TRANSPORT_LE));
  144. } else {
  145. return (BluetoothGatt) (bluetoothGattConstructor.newInstance(context, iBluetoothGatt, remoteDevice));
  146. }
  147. }
  148.  
  149. private Object getIBluetoothGatt(Object iBluetoothManager)
  150. throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  151.  
  152. if (iBluetoothManager == null) {
  153. return null;
  154. }
  155.  
  156. Method getBluetoothGattMethod = getMethodFromClass(iBluetoothManager.getClass(), "getBluetoothGatt");
  157. return getBluetoothGattMethod.invoke(iBluetoothManager);
  158. }
  159.  
  160. private Object getIBluetoothManager() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
  161.  
  162. BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  163.  
  164. if (bluetoothAdapter == null) {
  165. return null;
  166. }
  167.  
  168. Method getBluetoothManagerMethod = getMethodFromClass(bluetoothAdapter.getClass(), "getBluetoothManager");
  169. return getBluetoothManagerMethod.invoke(bluetoothAdapter);
  170. }
  171.  
  172. private Method getMethodFromClass(Class<?> cls, String methodName) throws NoSuchMethodException {
  173. Method method = cls.getDeclaredMethod(methodName);
  174. method.setAccessible(true);
  175. return method;
  176. }
  177.  
  178. private void setAutoConnectValue(BluetoothGatt bluetoothGatt, boolean autoConnect) throws NoSuchFieldException, IllegalAccessException {
  179. Field autoConnectField = bluetoothGatt.getClass().getDeclaredField("mAutoConnect");
  180. autoConnectField.setAccessible(true);
  181. autoConnectField.setBoolean(bluetoothGatt, autoConnect);
  182. }
  183. }
  184.  
  185. connectedGatt.add(device.connectGatt(applicationContext, true, callback));
  186.  
  187. public void connectAll(final BluetoothAdapter btAdapter) {
  188. final BluetoothAdapter bluetoothAdapter;
  189. logger.d(TAG + "reconnectAll");
  190. mainThreadHandler.postDelayed(new Runnable() {
  191. @Override
  192. public void run() {
  193. for (BluetoothGatt gatt : connectedGatt) {
  194. gatt.connect();
  195. }
  196. }
  197. }, 1000);
  198. }
  199.  
  200. 02-27 18:13:12.639 24192-24192/com.tel.btandroid.debug core::DevManager :: reconnectAll
  201. 02-27 18:13:12.643 24192-24192/com.tel.btandroid.debug E/BluetoothGatt: android.os.DeadObjectException
  202. at android.os.BinderProxy.transactNative(Native Method)
  203. at android.os.BinderProxy.transact(Binder.java:503)
  204. at android.bluetooth.IBluetoothGatt$Stub$Proxy.unregisterClient(IBluetoothGatt.java:891)
  205. at android.bluetooth.BluetoothGatt.unregisterApp(BluetoothGatt.java:692)
  206. at android.bluetooth.BluetoothGatt.close(BluetoothGatt.java:631)
  207. at com.tel.android.core.sensors.bluetooth.BLEDeviceManagerImpl$8.run(BLEDeviceManagerImpl.java:404)
  208. at android.os.Handler.handleCallback(Handler.java:739)
  209. at android.os.Handler.dispatchMessage(Handler.java:95)
  210. at android.os.Looper.loop(Looper.java:148)
  211. at android.app.ActivityThread.main(ActivityThread.java:5551)
  212. at java.lang.reflect.Method.invoke(Native Method)
  213. at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:730)
  214. at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:620)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement