我创建了一个应用程序,可以很好地执行以下步骤 -
使用蓝牙插座连接远程设备(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中调用了服务,意图是当应用程序进入后台时它将执行 和处理数据。但那么它将如何与片段沟通,因为我的整个工作 数据处理在片段中。我是否真的需要它来处理数据或我应该打电话给 广播接收器在这里,因为它也可以在后台处理?
答案 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;
}
}
}
}
}
}