TShopping

 找回密碼
 註冊
搜索
查看: 244|回復: 0

[教學] Android 藍芽如何背景執行(切換Activity不會斷連)

[複製鏈接]
發表於 2020-5-5 20:14:06 | 顯示全部樓層 |閱讀模式
 
Push to Facebook Push to Plurk  
續上篇 Android BLE ESP32的onCharacteristicChanged沒有回撥及getDescriptor null
如何在Android BLE 發送數據 ESP32?
如何在Android BLE 發送到 ESP32 超過20個字元的數據?
自己照著Android Bluetooth原始碼寫,因為要轉換Activity切換畫面
但一離開Activity馬上出現離線的LOG


這時就想起手機在打開藍牙連線的時候,不管換了多少APP都不會斷連
網路上GOOGLE Buletooth background Service找到了這篇


BluetoothLeService.java Activity加入以下代碼
測試之後,順暢穩定執行
  1. public class BluetoothServices extends Service {

  2. private BluetoothAdapter mBluetoothAdapter;
  3. public static final String B_DEVICE = "MY DEVICE";
  4. public static final String B_UUID = "00001101-0000-1000-8000-00805f9b34fb"; //藍芽串口服務
  5. // 00000000-0000-1000-8000-00805f9b34fb

  6. public static final int STATE_NONE = 0;
  7. public static final int STATE_LISTEN = 1;
  8. public static final int STATE_CONNECTING = 2;
  9. public static final int STATE_CONNECTED = 3;

  10. private ConnectBtThread mConnectThread;
  11. private static ConnectedBtThread mConnectedThread;

  12. private static Handler mHandler = null;
  13. public static int mState = STATE_NONE;
  14. public static String deviceName;
  15. public static BluetoothDevice sDevice = null;
  16. public Vector<Byte> packData = new Vector<>(2048);

  17. //IBinder mIBinder = new LocalBinder();


  18. @Nullable
  19. @Override
  20. public IBinder onBind(Intent intent) {
  21.     //mHandler = getApplication().getHandler();
  22.     return mBinder;
  23. }
  24. public void toast(String mess){
  25.     Toast.makeText(this,mess,Toast.LENGTH_SHORT).show();
  26. }
  27. private final IBinder mBinder = new LocalBinder();

  28. public class LocalBinder extends Binder {
  29.     BluetoothServices getService() {
  30.         // Return this instance of LocalService so clients can call public methods
  31.         return BluetoothServices.this;
  32.     }
  33. }

  34. @Override
  35. public int onStartCommand(Intent intent, int flags, int startId) {
  36.     String deviceg = intent.getStringExtra("bluetooth_device");
  37.     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
  38.     connectToDevice(deviceg);

  39.     return START_STICKY;
  40. }
  41. private synchronized void connectToDevice(String macAddress){
  42.     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
  43.     if (mState == STATE_CONNECTING){
  44.         if (mConnectThread != null){
  45.             mConnectThread.cancel();
  46.             mConnectThread = null;
  47.         }
  48.     }
  49.     if (mConnectedThread != null){
  50.         mConnectedThread.cancel();
  51.         mConnectedThread = null;
  52.     }
  53.     mConnectThread = new ConnectBtThread(device);
  54.     toast("connecting");
  55.     mConnectThread.start();
  56.     setState(STATE_CONNECTING);
  57. }

  58. private void setState(int state){
  59.     mState = state;
  60.     if (mHandler != null){
  61.        // mHandler.obtainMessage();
  62.     }
  63. }

  64. public synchronized void stop(){
  65.     setState(STATE_NONE);
  66.     if (mConnectThread != null){
  67.         mConnectThread.cancel();
  68.         mConnectThread = null;
  69.     }
  70.     if (mConnectedThread != null){
  71.         mConnectedThread.cancel();
  72.         mConnectedThread = null;
  73.     }
  74.     if (mBluetoothAdapter != null){
  75.         mBluetoothAdapter.cancelDiscovery();
  76.     }

  77.     stopSelf();
  78. }

  79. public void sendData(String message){
  80.     if (mConnectedThread!= null){
  81.         mConnectedThread.write(message.getBytes());
  82.         toast("sent data");
  83.     }else {
  84.         Toast.makeText(BluetoothServices.this,"Failed to send data",Toast.LENGTH_SHORT).show();
  85.     }
  86. }

  87. @Override
  88. public boolean stopService(Intent name) {
  89.     setState(STATE_NONE);

  90.     if (mConnectThread != null){
  91.         mConnectThread.cancel();
  92.         mConnectThread = null;
  93.     }

  94.     if (mConnectedThread != null){
  95.         mConnectedThread.cancel();
  96.         mConnectedThread = null;
  97.     }

  98.     mBluetoothAdapter.cancelDiscovery();
  99.     return super.stopService(name);
  100. }

  101. /*private synchronized void connected(BluetoothSocket mmSocket){

  102.     if (mConnectThread != null){
  103.         mConnectThread.cancel();
  104.         mConnectThread = null;
  105.     }
  106.     if (mConnectedThread != null){
  107.         mConnectedThread.cancel();
  108.         mConnectedThread = null;
  109.     }

  110.     mConnectedThread = new ConnectedBtThread(mmSocket);
  111.     mConnectedThread.start();

  112.     setState(STATE_CONNECTED);
  113. }*/

  114. private class ConnectBtThread extends Thread{
  115.     private final BluetoothSocket mSocket;
  116.     private final BluetoothDevice mDevice;

  117.     public ConnectBtThread(BluetoothDevice device){
  118.         mDevice = device;
  119.         BluetoothSocket socket = null;
  120.         try {
  121.             socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
  122.         } catch (IOException e) {
  123.             e.printStackTrace();
  124.         }
  125.         mSocket = socket;
  126.     }

  127.     @Override
  128.     public void run() {
  129.         mBluetoothAdapter.cancelDiscovery();

  130.         try {
  131.             mSocket.connect();
  132.             Log.d("service","connect thread run method (connected)");
  133.             SharedPreferences pre = getSharedPreferences("BT_NAME",0);
  134.             pre.edit().putString("bluetooth_connected",mDevice.getName()).apply();

  135.         } catch (IOException e) {

  136.             try {
  137.                 mSocket.close();
  138.                 Log.d("service","connect thread run method ( close function)");
  139.             } catch (IOException e1) {
  140.                 e1.printStackTrace();
  141.             }
  142.             e.printStackTrace();
  143.         }
  144.         //connected(mSocket);
  145.         mConnectedThread = new ConnectedBtThread(mSocket);
  146.         mConnectedThread.start();
  147.     }

  148.     public void cancel(){
  149.         try {
  150.             mSocket.close();
  151.             Log.d("service","connect thread cancel method");
  152.         } catch (IOException e) {
  153.             e.printStackTrace();
  154.         }
  155.     }
  156. }

  157. private class ConnectedBtThread extends Thread{
  158.     private final BluetoothSocket cSocket;
  159.     private final InputStream inS;
  160.     private final OutputStream outS;
  161.     private byte[] buffer;

  162.     public ConnectedBtThread(BluetoothSocket socket){
  163.         cSocket = socket;
  164.         InputStream tmpIn = null;
  165.         OutputStream tmpOut = null;

  166.         try {
  167.             tmpIn = socket.getInputStream();

  168.         } catch (IOException e) {
  169.             e.printStackTrace();
  170.         }

  171.         try {
  172.             tmpOut = socket.getOutputStream();
  173.         } catch (IOException e) {
  174.             e.printStackTrace();
  175.         }

  176.         inS = tmpIn;
  177.         outS = tmpOut;
  178.     }

  179.     @Override
  180.     public void run() {
  181.         buffer = new byte[1024];
  182.         int mByte;
  183.         try {
  184.             mByte= inS.read(buffer);
  185.         } catch (IOException e) {
  186.             e.printStackTrace();
  187.         }
  188.         Log.d("service","connected thread run method");
  189.     }

  190.     public void write(byte[] buff){
  191.         try {
  192.             outS.write(buff);
  193.         } catch (IOException e) {
  194.             e.printStackTrace();
  195.         }
  196.     }

  197.     private void cancel(){
  198.         try {
  199.             cSocket.close();
  200.             Log.d("service","connected thread cancel method");
  201.         } catch (IOException e) {
  202.             e.printStackTrace();
  203.         }
  204.     }
  205. }

  206. @Override
  207. public void onDestroy() {
  208.     this.stop();
  209.     super.onDestroy();
  210. }
複製代碼
關於service與actvity綁定的知識,但是在調試過程中無意中出現了上述的bug,後來經分析,當清理後台activity時就會報這個錯誤
重寫的onDestroy的回調方法中加入了對服務的解綁操作即unbindService就成功解決了

在MainActivity.jaca加入以下代碼
  1. protected void onDestroy() {
  2.         // TODO 自动生成的方法存根
  3.         super.onDestroy();
  4.         unbindService(mServiceConnection);
  5.     }
複製代碼
其實這個錯誤有點類似於dialog中如果activity已經finish()掉但dialog還沒dissmiss()時也會報類似的溢出錯誤,希望大家引以為戒,多多注意自己的代碼習慣,做好防護的措施。


來源
http://www.netyea.com

參考文章
https://blog.csdn.net/as02446418/article/details/46790843

 

臉書網友討論
您需要登錄後才可以回帖 登錄 | 註冊 |

本版積分規則



Archiver|手機版|小黑屋|免責聲明|TShopping

GMT+8, 2020-5-26 14:13 , Processed in 0.053007 second(s), 21 queries .

本論壇言論純屬發表者個人意見,與 TShopping綜合論壇 立場無關 如有意見侵犯了您的權益 請寫信聯絡我們。

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回復 返回頂部 返回列表