| 
 | 
 
 
續上篇 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加入以下代碼 
測試之後,順暢穩定執行 
- public class BluetoothServices extends Service {
 
  
- private BluetoothAdapter mBluetoothAdapter;
 
 - public static final String B_DEVICE = "MY DEVICE";
 
 - public static final String B_UUID = "00001101-0000-1000-8000-00805f9b34fb"; //藍芽串口服務
 
 - // 00000000-0000-1000-8000-00805f9b34fb
 
  
- public static final int STATE_NONE = 0;
 
 - public static final int STATE_LISTEN = 1;
 
 - public static final int STATE_CONNECTING = 2;
 
 - public static final int STATE_CONNECTED = 3;
 
  
- private ConnectBtThread mConnectThread;
 
 - private static ConnectedBtThread mConnectedThread;
 
  
- private static Handler mHandler = null;
 
 - public static int mState = STATE_NONE;
 
 - public static String deviceName;
 
 - public static BluetoothDevice sDevice = null;
 
 - public Vector<Byte> packData = new Vector<>(2048);
 
  
- //IBinder mIBinder = new LocalBinder();
 
  
 
- @Nullable
 
 - @Override
 
 - public IBinder onBind(Intent intent) {
 
 -     //mHandler = getApplication().getHandler();
 
 -     return mBinder;
 
 - }
 
 - public void toast(String mess){
 
 -     Toast.makeText(this,mess,Toast.LENGTH_SHORT).show();
 
 - }
 
 - private final IBinder mBinder = new LocalBinder();
 
  
- public class LocalBinder extends Binder {
 
 -     BluetoothServices getService() {
 
 -         // Return this instance of LocalService so clients can call public methods
 
 -         return BluetoothServices.this;
 
 -     }
 
 - }
 
  
- @Override
 
 - public int onStartCommand(Intent intent, int flags, int startId) {
 
 -     String deviceg = intent.getStringExtra("bluetooth_device");
 
 -     mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
 
 -     connectToDevice(deviceg);
 
  
-     return START_STICKY;
 
 - }
 
 - private synchronized void connectToDevice(String macAddress){
 
 -     BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
 
 -     if (mState == STATE_CONNECTING){
 
 -         if (mConnectThread != null){
 
 -             mConnectThread.cancel();
 
 -             mConnectThread = null;
 
 -         }
 
 -     }
 
 -     if (mConnectedThread != null){
 
 -         mConnectedThread.cancel();
 
 -         mConnectedThread = null;
 
 -     }
 
 -     mConnectThread = new ConnectBtThread(device);
 
 -     toast("connecting");
 
 -     mConnectThread.start();
 
 -     setState(STATE_CONNECTING);
 
 - }
 
  
- private void setState(int state){
 
 -     mState = state;
 
 -     if (mHandler != null){
 
 -        // mHandler.obtainMessage();
 
 -     }
 
 - }
 
  
- public synchronized void stop(){
 
 -     setState(STATE_NONE);
 
 -     if (mConnectThread != null){
 
 -         mConnectThread.cancel();
 
 -         mConnectThread = null;
 
 -     }
 
 -     if (mConnectedThread != null){
 
 -         mConnectedThread.cancel();
 
 -         mConnectedThread = null;
 
 -     }
 
 -     if (mBluetoothAdapter != null){
 
 -         mBluetoothAdapter.cancelDiscovery();
 
 -     }
 
  
-     stopSelf();
 
 - }
 
  
- public void sendData(String message){
 
 -     if (mConnectedThread!= null){
 
 -         mConnectedThread.write(message.getBytes());
 
 -         toast("sent data");
 
 -     }else {
 
 -         Toast.makeText(BluetoothServices.this,"Failed to send data",Toast.LENGTH_SHORT).show();
 
 -     }
 
 - }
 
  
- @Override
 
 - public boolean stopService(Intent name) {
 
 -     setState(STATE_NONE);
 
  
-     if (mConnectThread != null){
 
 -         mConnectThread.cancel();
 
 -         mConnectThread = null;
 
 -     }
 
  
-     if (mConnectedThread != null){
 
 -         mConnectedThread.cancel();
 
 -         mConnectedThread = null;
 
 -     }
 
  
-     mBluetoothAdapter.cancelDiscovery();
 
 -     return super.stopService(name);
 
 - }
 
  
- /*private synchronized void connected(BluetoothSocket mmSocket){
 
  
-     if (mConnectThread != null){
 
 -         mConnectThread.cancel();
 
 -         mConnectThread = null;
 
 -     }
 
 -     if (mConnectedThread != null){
 
 -         mConnectedThread.cancel();
 
 -         mConnectedThread = null;
 
 -     }
 
  
-     mConnectedThread = new ConnectedBtThread(mmSocket);
 
 -     mConnectedThread.start();
 
  
-     setState(STATE_CONNECTED);
 
 - }*/
 
  
- private class ConnectBtThread extends Thread{
 
 -     private final BluetoothSocket mSocket;
 
 -     private final BluetoothDevice mDevice;
 
  
-     public ConnectBtThread(BluetoothDevice device){
 
 -         mDevice = device;
 
 -         BluetoothSocket socket = null;
 
 -         try {
 
 -             socket = device.createInsecureRfcommSocketToServiceRecord(UUID.fromString(B_UUID));
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
 -         mSocket = socket;
 
 -     }
 
  
-     @Override
 
 -     public void run() {
 
 -         mBluetoothAdapter.cancelDiscovery();
 
  
-         try {
 
 -             mSocket.connect();
 
 -             Log.d("service","connect thread run method (connected)");
 
 -             SharedPreferences pre = getSharedPreferences("BT_NAME",0);
 
 -             pre.edit().putString("bluetooth_connected",mDevice.getName()).apply();
 
  
-         } catch (IOException e) {
 
  
-             try {
 
 -                 mSocket.close();
 
 -                 Log.d("service","connect thread run method ( close function)");
 
 -             } catch (IOException e1) {
 
 -                 e1.printStackTrace();
 
 -             }
 
 -             e.printStackTrace();
 
 -         }
 
 -         //connected(mSocket);
 
 -         mConnectedThread = new ConnectedBtThread(mSocket);
 
 -         mConnectedThread.start();
 
 -     }
 
  
-     public void cancel(){
 
 -         try {
 
 -             mSocket.close();
 
 -             Log.d("service","connect thread cancel method");
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
 -     }
 
 - }
 
  
- private class ConnectedBtThread extends Thread{
 
 -     private final BluetoothSocket cSocket;
 
 -     private final InputStream inS;
 
 -     private final OutputStream outS;
 
 -     private byte[] buffer;
 
  
-     public ConnectedBtThread(BluetoothSocket socket){
 
 -         cSocket = socket;
 
 -         InputStream tmpIn = null;
 
 -         OutputStream tmpOut = null;
 
  
-         try {
 
 -             tmpIn = socket.getInputStream();
 
  
-         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
  
-         try {
 
 -             tmpOut = socket.getOutputStream();
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
  
-         inS = tmpIn;
 
 -         outS = tmpOut;
 
 -     }
 
  
-     @Override
 
 -     public void run() {
 
 -         buffer = new byte[1024];
 
 -         int mByte;
 
 -         try {
 
 -             mByte= inS.read(buffer);
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
 -         Log.d("service","connected thread run method");
 
 -     }
 
  
-     public void write(byte[] buff){
 
 -         try {
 
 -             outS.write(buff);
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
 -     }
 
  
-     private void cancel(){
 
 -         try {
 
 -             cSocket.close();
 
 -             Log.d("service","connected thread cancel method");
 
 -         } catch (IOException e) {
 
 -             e.printStackTrace();
 
 -         }
 
 -     }
 
 - }
 
  
- @Override
 
 - public void onDestroy() {
 
 -     this.stop();
 
 -     super.onDestroy();
 
 - }
 
  複製代碼 關於service與actvity綁定的知識,但是在調試過程中無意中出現了上述的bug,後來經分析,當清理後台activity時就會報這個錯誤 
重寫的onDestroy的回調方法中加入了對服務的解綁操作即unbindService就成功解決了 
 
在MainActivity.jaca加入以下代碼 
- protected void onDestroy() {
 
 -         // TODO 自动生成的方法存根
 
 -         super.onDestroy();
 
 -         unbindService(mServiceConnection);
 
 -     }
 
  複製代碼 其實這個錯誤有點類似於dialog中如果activity已經finish()掉但dialog還沒dissmiss()時也會報類似的溢出錯誤,希望大家引以為戒,多多注意自己的代碼習慣,做好防護的措施。 
 
 
來源 
http://www.netyea.com 
 
參考文章 
https://blog.csdn.net/as02446418/article/details/46790843 
 |   
 
 
 
 |