Good day! I am writing an application in which the connection between the device and the smartphone via bluetooth takes place, namely, I send a command to the device, it sends me a line of data that needs to be parsed. Receive messages by using Handler . The problem is that in the application I have several activities, and when the activity changes, the team is sent, but the device does not receive it. Help to understand the problem. I believe that when changing bluetooth activities, the socket is broken, so the device does not receive a command from me. And another problem is how much need a handler ? For each activity of its own, or one for all?
Bluetooth Service
public class BluetoothService extends Service { public BluetoothAdapter bluetoothAdapter = null; BluetoothSocket mmSocket; public static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB"; //public static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); private ConnectThread mConnectThread; private ConnectedThread mConnectedThread; private static Handler mHandler = new MainActivity.mHandler(); public static int mState = Constants.STATE_NONE; StringBuilder sb; public static int TypeMessage; @Override public void onCreate() { Log.d(Constants.LOG_TAG, "***Service started***"); super.onCreate(); } @Override public IBinder onBind(Intent intent) { Log.d(Constants.LOG_TAG, "***Binding***"); //mHandler = ((MyApplication) getApplication()).getHandler(); return mBinder; } public class LocalBinder extends Binder { BluetoothService getService() { return BluetoothService.this; } } private final IBinder mBinder = new LocalBinder(); @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(Constants.LOG_TAG, "***OnStart Command***"); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter != null) { String MACaddr = intent.getStringExtra("mac"); Log.d(Constants.LOG_TAG, MACaddr); if (MACaddr != null && MACaddr.length() > 0) { connectToDevice(MACaddr); } else { stopSelf(); return START_STICKY_COMPATIBILITY; } } return START_STICKY; } /*final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); deviceName = device.getName(); MAC = device.getAddress(); Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_DEVICE); Bundle bundle = new Bundle(); bundle.putString("name", deviceName); bundle.putString("mac", MAC); msg.setData(bundle); mHandler.sendMessage(msg); Log.d(Constants.LOG_TAG, deviceName + MAC); } } };*/ private synchronized void connectToDevice(String MACaddr) { BluetoothDevice device = bluetoothAdapter.getRemoteDevice(MACaddr); Log.d(Constants.LOG_TAG, "***Получили удаленный Device***" + device.getName()); if (mState == Constants.STATE_CONNECTING) { if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } } // Cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } mConnectThread = new ConnectThread(device); mConnectThread.start(); Log.d(Constants.LOG_TAG, "***Соединение с " + device.getName() + " успешно установлено***"); setState(Constants.STATE_CONNECTING); } /*public synchronized void connectToDevice(String MAC) { BluetoothDevice device = bluetoothAdapter.getRemoteDevice(MAC); Log.d(Constants.LOG_TAG, "***Получили удаленный Device***" + device.getName()); try { bluetoothSocket = device.createRfcommSocketToServiceRecord(MY_UUID); Log.d(Constants.LOG_TAG, "...Создали сокет..."); } catch (IOException e) { MyError("Fatal Error", "В onResume() Не могу создать сокет: " + e.getMessage() + "."); } bluetoothAdapter.cancelDiscovery(); Log.d(Constants.LOG_TAG, "***Отменили поиск других устройств***"); Log.d(Constants.LOG_TAG, "***Соединяемся...***"); try { bluetoothSocket.connect(); Log.d(Constants.LOG_TAG, "***Соединение успешно установлено***"); } catch (IOException e) { try { bluetoothSocket.close(); } catch (IOException e2) { MyError("Fatal Error", "В onResume() не могу закрыть сокет" + e2.getMessage() + "."); } } mConnectedThread = new ConnectedThread(bluetoothSocket); mConnectedThread.start(); TypeMessage = Constants.GET_GROUP_INFO; mConnectedThread.sendData("[GET_GROUP_INFO]"); //setState(Constants.STATE_CONNECTING); } private void MyError(String title, String message){ Toast.makeText(getBaseContext(), title + " - " + message, Toast.LENGTH_LONG).show(); stopSelf(); }*/ private void setState(int state) { BluetoothService.mState = state; if (mHandler != null) { mHandler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget(); } } public synchronized void stop() { setState(Constants.STATE_NONE); if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } if (bluetoothAdapter != null) { bluetoothAdapter.cancelDiscovery(); } stopSelf(); } @Override public boolean stopService(Intent name) { setState(Constants.STATE_NONE); if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } bluetoothAdapter.cancelDiscovery(); return super.stopService(name); } private void connectionFailed() { BluetoothService.this.stop(); Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(Constants.TOAST, getString(R.string.error_connect_failed)); msg.setData(bundle); mHandler.sendMessage(msg); } private void connectionLost() { BluetoothService.this.stop(); Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST); Bundle bundle = new Bundle(); bundle.putString(Constants.TOAST, getString(R.string.error_connect_lost)); msg.setData(bundle); mHandler.sendMessage(msg); } private static Object obj = new Object(); private synchronized void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) { // Cancel the thread that completed the connection if (mConnectThread != null) { mConnectThread.cancel(); mConnectThread = null; } // Cancel any thread currently running a connection if (mConnectedThread != null) { mConnectedThread.cancel(); mConnectedThread = null; } mConnectedThread = new ConnectedThread(mmSocket); mConnectedThread.start(); setState(Constants.STATE_CONNECTED); } private class ConnectThread extends Thread { private final BluetoothDevice mmDevice; public ConnectThread(BluetoothDevice device) { this.mmDevice = device; BluetoothSocket tmp = null; try { tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID)); Log.d(Constants.LOG_TAG, "...Создали сокет..."); } catch (IOException e) { e.printStackTrace(); } mmSocket = tmp; } @Override public void run() { setName("ConnectThread"); bluetoothAdapter.cancelDiscovery(); Log.d(Constants.LOG_TAG, "***Отменили поиск других устройств***"); try { mmSocket.connect(); } catch (IOException e) { try { mmSocket.close(); } catch (IOException e1) { e1.printStackTrace(); } connectionFailed(); return; } synchronized (BluetoothService.this) { mConnectThread = null; } connected(mmSocket, mmDevice); } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(Constants.LOG_TAG, "***close() of connect socket failed***", e); } } } private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; private byte[] buffer; public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(Constants.LOG_TAG, "***temp sockets not created***", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } @Override public void run() { buffer = new byte[1024]; int bytes; StringBuilder sb = new StringBuilder(); while (true) { try { bytes = mmInStream.read(buffer); String message = new String(buffer, 0, bytes); sb.append(message); handler.obtainMessage(0, buffer.length, -1, buffer).sendToTarget(); sb.setLength(0); } catch (Exception e) { e.printStackTrace(); BluetoothService.this.stop(); break; } } } public void sendData(String message) { byte[] msgBuffer = message.getBytes(); Log.d(Constants.LOG_TAG, "***Отправляем данные: " + message + "***" ); try { mmOutStream.write(msgBuffer); } catch (IOException e) { Log.e(Constants.LOG_TAG, "***Exception during write***", e); } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(Constants.LOG_TAG, "***close() of connect socket failed***", e); } } } public void trace(String msg) { Log.d(Constants.LOG_TAG, msg); toast(msg); } public void toast(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onDestroy() { stop(); Log.d(Constants.LOG_TAG, "***Service Destroyed***"); //unregisterReceiver(broadcastReceiver); //Log.d(Constants.LOG_TAG, "***Receiver unregistered***"); super.onDestroy(); } private void sendMsg(int flag) { Message msg = new Message(); msg.what = flag; handler.sendMessage(msg); } private Handler handler = new Handler() { @Override public void handleMessage(Message msg) {// if (!Thread.currentThread().isInterrupted()) { switch (TypeMessage) { case Constants.GET_GROUP_INFO: break; case Constants.DATETIME_setD: break; case Constants.DATETIME: break; } } super.handleMessage(msg); } }; MainActivity
public class MainActivity extends Activity { public static final int MESSAGE_STATE_CHANGE = 1; public static final int MESSAGE_TOAST = 2; public static final int MESSAGE_WRITE = 3; public static final int MESSAGE_DEVICE = 4; public static final int MESSAGE_ANSWER = 5; BluetoothAdapter bluetoothAdapter; BluetoothService btService; boolean mBound = false; static ArrayAdapter<String> btArrayAdapter; BluetoothDevice device; private StringBuilder sb = new StringBuilder(); public static TextView text, status, impWeight, curValueMeter, curDate, addressAPN, loginAPN, passAPN, URL, num1, num2, comSessMode, curSupVoltage, curBBVoltage, imei, levelGSM, repDate, backupInterval, maxSession, meterSinceFirst, meterFail, curRecInArch, meterType, meterSerNumber; Button synchr; ListView listView; static ProgressBar pb; Context context; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); status = (TextView) findViewById(R.id.textView); impWeight = (TextView) findViewById(R.id.textView2); curValueMeter = (TextView) findViewById(R.id.textView3); curDate = (TextView) findViewById(R.id.textView4); addressAPN = (TextView) findViewById(R.id.textView5); loginAPN = (TextView) findViewById(R.id.textView6); passAPN = (TextView) findViewById(R.id.textView7); URL = (TextView) findViewById(R.id.textView8); num1 = (TextView) findViewById(R.id.textView9); num2 = (TextView) findViewById(R.id.textView10); comSessMode = (TextView) findViewById(R.id.textView11); curSupVoltage = (TextView) findViewById(R.id.textView12); curBBVoltage = (TextView) findViewById(R.id.textView13); imei = (TextView) findViewById(R.id.textView14); levelGSM = (TextView) findViewById(R.id.textView15); repDate = (TextView) findViewById(R.id.textView16); backupInterval = (TextView) findViewById(R.id.textView17); maxSession = (TextView) findViewById(R.id.textView18); meterSinceFirst = (TextView) findViewById(R.id.textView19); meterFail = (TextView) findViewById(R.id.textView20); curRecInArch = (TextView) findViewById(R.id.textView21); meterType = (TextView) findViewById(R.id.textView22); meterSerNumber = (TextView) findViewById(R.id.textView23); bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (bluetoothAdapter == null) { Toast.makeText(getBaseContext(), "Device does not support Bluetooth", Toast.LENGTH_SHORT).show(); finish(); } else { if (!bluetoothAdapter.isEnabled()) { Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(enableBtIntent, 1); } } text = (TextView) findViewById(R.id.textView); pb = (ProgressBar) findViewById(R.id.pb); synchr = (Button) findViewById(R.id.synchr); synchr.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { SimpleDateFormat dateFormat = new SimpleDateFormat("dd.MM.yy,HH:mm:ss"); final String d = dateFormat.format(new Date()); runOnUiThread(new Runnable() { @Override public void run() { } }); } }); } @Override protected void onStart() { super.onStart(); Intent intent = new Intent(this, BluetoothService.class); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); } @Override protected void onStop() { super.onStop(); if (mBound) { unbindService(mConnection); mBound = false; } } private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { Log.d(Constants.LOG_TAG, "***Service connected***"); BluetoothService.LocalBinder binder = (BluetoothService.LocalBinder) service; btService = binder.getService(); mBound = true; } @Override public void onServiceDisconnected(ComponentName name) { mBound = false; } }; final BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothDevice.ACTION_FOUND.equals(action)) { device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); btArrayAdapter.add(device.getName() + "\n" + device.getAddress()); btArrayAdapter.notifyDataSetChanged(); } } }; public void search() { if (bluetoothAdapter.isDiscovering()) { bluetoothAdapter.cancelDiscovery(); } else { btArrayAdapter.clear(); bluetoothAdapter.startDiscovery(); registerReceiver(broadcastReceiver, new IntentFilter(BluetoothDevice.ACTION_FOUND)); } } @Override protected void onResume() { super.onResume(); //startService(new Intent(this, BluetoothService.class)); //Log.d(Constants.LOG_TAG, "***OnStartCommand started***"); pb.setVisibility(View.VISIBLE); setup(); search(); } private void setup() { listView = (ListView) findViewById(R.id.listView); btArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1); listView.setAdapter(btArrayAdapter); listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { pb.setVisibility(ProgressBar.GONE); listView.setVisibility(View.GONE); synchr.setVisibility(View.VISIBLE); String itemValue = (String) listView.getItemAtPosition(position); String MAC = itemValue.substring(itemValue.length() - 17); Intent serviceIntent = new Intent(MainActivity.this, BluetoothService.class); serviceIntent.putExtra("mac", MAC); startService(serviceIntent); } }); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(broadcastReceiver); Log.d(Constants.LOG_TAG, "***Receiver unregistered***"); } public static class mHandler extends Handler { @Override public void handleMessage (android.os.Message msg){ switch (msg.what) { case (MESSAGE_STATE_CHANGE): switch (msg.arg1) { case Constants.STATE_CONNECTED: break; case Constants.STATE_CONNECTING: break; case Constants.STATE_NONE: break; case Constants.STATE_ERROR: break; } break; case (MESSAGE_TOAST): msg.getData().getString(Constants.TOAST); break; case (MESSAGE_WRITE): break; case (MESSAGE_DEVICE): String deviceName = msg.getData().getString("name"); String MACAddr = msg.getData().getString("mac"); btArrayAdapter.add(deviceName +"\n" +MACAddr); btArrayAdapter.notifyDataSetChanged(); break; case (MESSAGE_ANSWER): String GGI = msg.getData().getString("GGI"); String[] result = GGI.split(";"); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < result.length; i++) { stringBuilder.append(result[i]); if (i != result.length - 1) { stringBuilder.append("\n"); status.setTextColor(Color.GREEN); status.setText("Статус: НОРМА"); impWeight.setText("Вес импульса: " + result[1]); curValueMeter.setText("Текущее значение счётчика: " + result[2]); curDate.setText("Текущая дата: " + result[3]); addressAPN.setText("Адрес APN: " + result[4]); loginAPN.setText("Логин APN: " + result[5]); passAPN.setText("Пароль APN: " + result[6]); URL.setText("URL адрес сервера: " + result[7]); num1.setText("Телефон для СМС №1: " + result[8]); num2.setText("Телефон для СМС №2: " + result[9]); String comsesmode = result[10]; String[] split = comsesmode.split(","); StringBuilder sbb = new StringBuilder(); for (int j = 0; j < split.length; j++) { sbb.append(split[j]); if (j != split.length - 1) { sbb.append(","); } } int k = Integer.parseInt(split[0]); if (k == 1) { comSessMode.setTextColor(Color.RED); comSessMode.setText("Режим сеанса связи: каждый час"); } if (k == 2) { comSessMode.setText("Режим сеанса связи: каждый день в " + split[1]); } if (k == 3) { comSessMode.setText("Режим сеанса связи: каждую неделю в " + split[2] + " день недели в " + split[1]); } if (k == 4) { comSessMode.setText("Режим сеанса связи: " + split[2] + " числа каждый месяц в " + split[1]); } curSupVoltage.setText("Текущее напряжение питания в mV: " + result[11]); curBBVoltage.setText("Текущее напряжение резервной батареи в mV: " + result[12]); imei.setText("IMEI модема: " + result[13]); levelGSM.setText("Уровень GSM сигнала: " + result[14]); repDate.setText("Отчётная дата: " + result[15]); backupInterval.setText("Резервный интервал: " + result[16]); maxSession.setText("Максимальное число сеансов связи: " + result[17]); meterSinceFirst.setText("Счётчик числа сеансов связи с момента первого включения: " + result[18]); meterFail.setText("Счётчик количества неуд. попыток связи до успешной связи: " + result[19]); curRecInArch.setText("Номер текущей записи в интервальном архиве: " + result[20]); meterType.setText("Тип счётчика: " + result[21]); meterSerNumber.setText("Серийный номер счетчика: " + result[22]); } } break; default: break; } } }