处理数据流并在后台创建记录

时间:2014-10-09 14:53:34

标签: android sockets android-broadcast android-bluetooth android-background

我创建了一个应用程序,可以很好地执行以下步骤 -

  • 使用蓝牙插座连接远程设备(SPP)。

  • 然后侦听来自远程蓝牙设备的流 在一个单独的主题中。

  • 然后,当数据流到来时,它会将数据流传递给处理程序以进行解析。

  • 解析数据时,会发送广播并创建记录 进入数据库。

现在我想添加一项新功能 -

  

当应用程序处于后台并且已连接时#34;对于远程设备,它需要继续处理数据流并创建记录。

所以一旦我连接了socket,我就会传递结果" connected"到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)我已连接,所以从AsyncTask parseStream的onPostExecute()做一些事情

 @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中调用了服务,意图是当应用程序进入后台时它将执行     和处理数据。但那么它将如何与片段沟通,因为我的整个工作     数据处理在片段中。我是否真的需要它来处理数据或我应该打电话给     广播接收器在这里,因为它也可以在后台处理?

1 个答案:

答案 0 :(得分:2)

我已经在这方面做了很多工作。我将与您分享我的经验中最有效的方法。

- 专用蓝牙服务,运行在自己独立的流程中,用于处理连续的数据流。

- 获取和播放时播放广播操纵数据;特别是如果它是快速和大量的数据流。这是我在处理bt流时过去的一个错误。我意识到,它可能适用于少量或慢流,但是,广播非常昂贵,当我用IPC(UI线程< - 蓝牙服务)替换它们以传递要处理的数据时,我看到了巨大的性能改进在UI线程中。

如前所述,如果你想要专门的蓝牙服务,那么绝对是最好的方法。我们的想法是,您希望将Context绑定到服务,以便发送和接收消息。文档:http://developer.android.com/guide/components/bound-services.html#Messenger

- 当活动/上下文绑定到正在运行的服务时,请设置一个接口,以便注册该服务应该回复的活动。因此,您将从蓝牙无线电传递任何传入数据,并使用新数据向活动发送消息,避免讨厌的不必要的广播。

- 我正在根据我的想法和在线示例(来自文档)编写一个快速,基本的示例(未经测试且未编译)。希望这很有用

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;
                }
        }

    }

}
}
}