3

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

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

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

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

  • 解析数据时,会发送广播并将记录创建到数据库中。

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

当应用程序在后台并“连接”到远程设备时,它需要继续处理数据流并创建记录。

因此,一旦我连接了套接字,我就会将结果“连接”传递给该onPostExecute()方法。

重要的提示:

1)我所有与socket相关的工作(socket连接、socket数据解析、数据处理程序)都在fragment中。

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 中调用了服务,目的是在应用程序进入后台并处理数据时执行。但是接下来它将如何与 Fragment 通信,因为我的整个数据处理工作都在 Fragment 中。我真的需要它来处理数据还是应该
在这里调用广播接收器,因为它也可以在后台处理?

4

1 回答 1

2

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

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

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

-IPC,如前所述,绝对是您寻求专用蓝牙服务的最佳方法。这个想法是您希望将您的上下文绑定到服务,以便发送和接收消息。文档: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;
                }
        }

    }

}
}
}
于 2014-10-14T11:08:53.743 回答