3

Я создали приложение, которое делает следующие шаги очень хорошо -процесса и создавать записи в фоновом режиме

  • соединяется с удаленным устройством (SPP), используя разъем Bluetooth.

  • Затем прослушивает поток, поступающий с удаленного устройства Bluetooth в отдельной теме.

  • Затем, когда поступает поток данных, он передает поток данных обработчику для его анализа.

  • Когда данные обрабатываются, то широковещательный посылается и создаются записи в базу данных.

Теперь я хочу, чтобы добавить новую функциональность -

Когда приложение находится в заднем месте и «подключен» к удаленному устройству, он должен продолжать обрабатывать поток данных и создавать записи.

Итак, как только я подключу сокет, я передаю результат «подключен» к методу onPostExecute().

ВАЖНО:

1) Мои все гнезда соответствующей работы (подключение гнездо, гнездо синтаксического анализа данных, обработчик данных) в фрагменте.

2) После того, как соединение установлено, частный класс (Thread - ConnectedThread.java) в осколке продолжать слушать InputStream

public class EntryFragment extends Fragment{ 
    //More fragment code here then this 
    public class ConnectedThread extends Thread { 

     public ConnectedThread(BluetoothSocket socket) { 
      //code initialization stuff 
     } 

     public void run() { 
      // Keep listening to the InputStream until an exception occurs 
      while (true) 
      { 
        // Read from the InputStream 
        if(mmInStream.available() > 0) 
        { 
         bytes = mmInStream.read(buffer); 

         mHandler.obtainMessage(MESSAGE_READ, 
         bytes, -1, buffer).sendToTarget(); 
        }    
       } 
      } 
    } 

3) Моего обработчик, который обрабатывает чтение шага 2

case MESSAGE_READ: 

    //Call to AsyncTask to do background processing of data 
    new parseStream(getActivity()).execute(); 
    break; 

4) Я подключен так что-то из onPostExecute() из AsyncTask parseStre Я

@Override 
protected void onPostExecute(Void result) { 
//Database related work here 

//Result is connected so listen to data if app goes to background after this state 
if(result.equals("connected")) 
{ 
     Log.i(TAG, "CONNECTED TO Remote Device!"); 
     Toast.makeText(getActivity(),"CONNECTED TO Remote 
     Device!",Toast.LENGTH_SHORT).show(); 

     //Do something when connected 
     setSetting("STATUS", "Connected"); 

     // Start the thread to manage the connection and perform transmissions 
     mConnectedThread = new ConnectedThread(socket); 
     mConnectedThread.start(); 

     //Do I need to call Service here to handle data ????? 
     Intent serviceIntent= new Intent(context, DataProcessService.class);    
     getActivity().startService(serviceIntent); 
    } 
} 

5) Я назвал обслуживание на шаге 4, с намерением, что он будет выполнять, когда приложение будет идти фоновые и данные процесса. Но тогда как он будет взаимодействовать с Фрагментом, потому что вся моя работа обработки данных находится во фрагменте. Я действительно нуждаюсь в этом для обработки данных. Или я должен позвонить
вещательный приемник здесь, поскольку он также может обрабатываться в фоновом режиме?

ответ

2

Я работал над этим совсем немного. Я поделюсь с вами тем, что лучше всего работает в моем опыте.

-Удаленный сервис bluetooth, работающий в собственном отдельном процессе, для обработки непрерывных потоков данных.

-Улучшение трансляций при получении & манипулирование данными; особенно если это быстро & большие потоки данных. Это ошибка, которую я сделал в прошлом при обработке потоков BT. Я понял, что он может работать нормально для небольших объемов или медленных потоков, но широковещательные передачи очень дороги, и я видел большие улучшения производительности при замене их IPC (поток пользовательского интерфейса < - служба Bluetooth) для передачи данных, которые будут обрабатываться в поток пользовательского интерфейса.

-IPC, как уже упоминалось ранее, определенно лучший способ, если вы пойдете на выделенный Bluetooth-сервис. Идея состоит в том, что вы хотите связать свой контекст с сервисом, чтобы отправлять сообщения &. Документация: http://developer.android.com/guide/components/bound-services.html#Messenger

-Когда объект/контекст привязан к запущенной службе, установите интерфейс так, чтобы активность регистрировалась, кому должна отвечать служба. Таким образом, вы будете передавать любые входящие данные с радио Bluetooth и отправлять сообщения на активность с новыми данными, избегая неприятных, ненужных передач.

-Мы пишем быстрый базовый пример (непроверенный и не скомпилированный) на основе моих мыслей и онлайн-примеров (из документов). Надеюсь, это полезно

public class BluetoothService extends Service { 

    // 
    // API keys for the messages being passed across ui thread <-> service 
    // 
    static final int REGISTER_CLIENT = 3; 
    static final int NEW_DATA = 2; 
    static final int WRITE_DATA = 1; 
    static final int CONNECT_BT = 0; 

     // manages actual connection 
     private BluetoothManager btManager; 

     // who is activity and ready to receive messages? 
     private Messenger clientToReply; 

     public int onStartCommand(Intent intent, int flags, int startId) { 

      btManager = new BluetoothManager(this); 

      return START_STICKY;//makes sure the service keeps running and get's back up if it gets terminated 
     } 

    // 
    // Send data back to your activity 
    // 
    public void sendDataToBoundClient(byte[] bytes) { 
      Message msgToClient = new Message(); 
      msgToClient.what = NEW_DATA; 

      Bundle bNewData = new Bundle(); 
      bNewData.putByteArray("newData", bytes); 

      msgToClient.setData(bNewData); 
      try { 
       clientToReply.send(msgToClient); //send 
      } catch (RemoteException e) { 
       e.printStackTrace(); //couldn't send 
      } 
    } 

    /** 
     * Handles messages received from a bound Context 
     */ 
    public class MessageHandler extends Handler { 
     /* (non-Javadoc) 
     * @see android.os.Handler#handleMessage(android.os.Message) 
     */ 
     @Override 
     public void handleMessage(Message msg) { 

       switch (msg.what) { 

        case REGISTER_CLIENT: 
         // now we know to whom to reply with our messages, callbacks or new data 
         clientToReply = msg.replyTo; 
         break; 

        case WRITE_DATA: 
         break; 

        case CONNECT_BT: 
         // launches Connect & Connected Threads 
         // would follow the same pattern as in http://developer.android.com/guide/topics/connectivity/bluetooth.html#ConnectingAsAClient 
         btManager.connect(); 
         break; 
       } 
     } 
    } 

} 




// 
    // Check examples in http://developer.android.com/guide/topics/connectivity/bluetooth.html#ConnectingAsAClient 
    // 
    public class BluetoothManager { 
     private ConnectThread connectThread; //thread to connect 
     private ConnectedThread connectedThread; //thread manages connection 

     private BluetoothService service; 

     public BluetoothManager(BluetoothService service) { 
      this.service = service; 
     } 

     // 
     // stuff omitted... 
     // 

     public void connect() { 
       connectThread = new ConnectThread(); 
       connectThread.start(); 
     } 


     public void writeData(byte[] bytes) { 
       connectedThread.write(bytes); 
     } 

     public void onDataRead(byte[] bytes) { 
      // service knows how to forward this to the client (bound activity, for example) 
      this.service.sendDataToBoundClient(bytes); 
     } 
    } 

// 
// Based on the example from http://developer.android.com/guide/components/bound-services.html#Messenger 
// 
public class ActivityMessenger extends Activity { 
    /** Messenger for communicating with the service. */ 
    Messenger mService = null; 

    // handle incoming messages 
    protected Messenger messagesFromService = new Messenger(new IncomingHandler()); 

    /** Flag indicating whether we have called bind on the service. */ 
    boolean mBound; 

    /** 
    * Class for interacting with the main interface of the service. 
    */ 
    private ServiceConnection mConnection = new ServiceConnection() { 
     public void onServiceConnected(ComponentName className, IBinder service) { 
      // This is called when the connection with the service has been 
      // established, giving us the object we can use to 
      // interact with the service. We are communicating with the 
      // service using a Messenger, so here we get a client-side 
      // representation of that from the raw IBinder object. 
      mService = new Messenger(service); 
      mBound = true; 
     } 

     public void onServiceDisconnected(ComponentName className) { 
      // This is called when the connection with the service has been 
      // unexpectedly disconnected -- that is, its process crashed. 
      mService = null; 
      mBound = false; 
     } 
    }; 

    public void registerAsClient() { 
     if (!mBound) return; 
     // Create and send a message to the service, using a supported 'what' value 
     Message msg = new Message(); 
     msg.what = BluetoothService.REGISTER_CLIENT; 
     msg.replyTo = messagesFromService; // reply to "me"! 

     try { 
      mService.send(msg); 
     } catch (RemoteException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     // Bind to the service 
     bindService(new Intent(this, MessengerService.class), mConnection, 
      Context.BIND_AUTO_CREATE); 
    } 

    @Override 
    protected void onStop() { 
     super.onStop(); 
     // Unbind from the service 
     if (mBound) { 
      unbindService(mConnection); 
      mBound = false; 
     } 
    } 


    public class IncomingHandler extends Handler { 

     @Override 
     public void handleMessage(Message msg) { 
       switch (msg.what) { 
         case BluetoothService.NEW_DATA: 
         Bundle data = msg.getData; 
         // handle your new data! 
         break; 
       } 
     } 

    } 

} 
} 
} 
+0

Нужно ли нам звонить службе через определенные промежутки времени, чтобы получить данные из сокета? Я уже реализовал логику подключения и обработки данных в фрагменте, поэтому мне нужно перенести его в класс BluetoothManager, как в коде выше? Предполагается, что служба запускается после подключения сокета из этого фрагмента, поэтому я думаю, что класс BluetoothManager должен быть повторно реализован. Посмотрите мое обновление! –

+0

@VedPrakash, вам не нужно будет звонить в службу через определенные промежутки времени. Служба уведомляет (путем отправки нового сообщения) основную тему каждый раз, когда появляются новые данные. – bmartins

+0

@VedPrakash, я также добавлю, что вы действительно должны учитывать последствия работы вашего bluetooth-процесса в фрагменте. Вы подвергаетесь управлению жизненным циклом Android и не можете должным образом повторно использовать свой рабочий процесс bluetooth вне области вашего фрагмента. – bmartins