尽管我不太确定我是如何做到的,但这似乎已解决,因此已包含代码供其他人使用。我做了很多重组以确保正确清理连接资源,现在当按下后退按钮时调用 onPause 和 onDestroy 方法。
仅供参考,此活动打开蓝牙连接并将传感器数据发送到另一台计算机以用于控制 LEGO NXT 机器人。
package uk.co.moonsit.apps.sensors.remote;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.TimeUnit;
import uk.co.moonsit.apps.sensors.R;
import uk.co.moonsit.bluetooth.BluetoothConnection;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
import android.view.Menu;
import android.view.WindowManager;
import android.widget.TextView;
public class RemoteLinearAccelerationActivity extends Activity implements
SensorEventListener {
private static final String TAG = "RemoteLinearAccelerationActivity";
private BlockingQueue<String> queue;
private SensorManager mSensorManager;
private Sensor mLinAcc;
private String format = "%.3f";
private String type;
private BluetoothConnection btConnection;
private String delimiter = "|";
private String cr;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_remote_linear_acceleration);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
byte[] crb = new byte[1];
crb[0] = 13;
cr = new String(crb);
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
mLinAcc = mSensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
queue = new SynchronousQueue<String>();
type = "LinAcc";
btConnection = new BluetoothConnection(queue, "00001101-0000-1000-8000-00805F9B34FB", "<MAC address here>", "11", "28,13");
Log.i(TAG, "+++ onCreate ");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.remote_linear_acceleration, menu);
return true;
}
@Override
public void onAccuracyChanged(Sensor arg0, int arg1) {
}
@Override
public void onSensorChanged(SensorEvent event) {
TextView tvX = (TextView) findViewById(R.id.textViewRemLinAccX);
TextView tvY = (TextView) findViewById(R.id.textViewRemLinAccY);
TextView tvZ = (TextView) findViewById(R.id.textViewRemLinAccZ);
String x = String.format(format, event.values[0]);
String y = String.format(format, event.values[1]);
String z = String.format(format, event.values[2]);
tvX.setText(x);
tvY.setText(y);
tvZ.setText(z);
try {
String msg = constructData(x, y, z);
if (btConnection.isRunning()) {
Log.i(TAG, "+++ queue values");
queue.offer(msg, 10, TimeUnit.SECONDS);
}
} catch (InterruptedException e) {
Log.e(TAG, "+++ err " + e.toString());
}
}
private String constructData(String x, String y, String z) {
StringBuilder sb = new StringBuilder();
sb.append(type + delimiter);
sb.append(x + delimiter);
sb.append(y + delimiter);
sb.append(z);
sb.append(cr);
return sb.toString();
}
@Override
protected void onPause() {
super.onPause();
Log.i(TAG, "+++ onPause unregisterListener ");
mSensorManager.unregisterListener(this);
}
@Override
protected void onResume() {
super.onResume();
Log.i(TAG, "+++ onResume registerListener ");
mSensorManager.registerListener(this, mLinAcc, SensorManager.SENSOR_DELAY_NORMAL);
Log.i(TAG, "+++ onResume start btConnection");
new Thread(btConnection).start();
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.i(TAG, "+++ onDestroy closing btConnection");
btConnection.stop();
}
}
package uk.co.moonsit.bluetooth;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.UUID;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.TimeUnit;
import uk.co.moonsit.messaging.BeginEndEnvelope;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
//import android.os.ParcelUuid;
import android.util.Log;
public class BluetoothConnection implements Runnable {
private static final String TAG = "BluetoothConnection";
private final BlockingQueue<String> queue;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice device;
private BluetoothSocket clientSocket;
private DataInputStream in = null;
private DataOutputStream out = null;
private String address;
private boolean isConnected = false;
private BeginEndEnvelope envelope;
private String uuid;
private boolean isRunning = true;
public BluetoothConnection(BlockingQueue<String> q, String ud, String a,
String start, String end) {
uuid = ud;
queue = q;
address = a;
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
envelope = new BeginEndEnvelope(start, end);
}
private void getDevice() throws IOException {
device = mBluetoothAdapter.getRemoteDevice(address);
}
private void getSocket() throws IOException {
clientSocket = device.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
mBluetoothAdapter.cancelDiscovery();
}
private boolean connect() {
if (!isConnected) {
Log.i(TAG, "+++ connecting");
try {
getSocket();
Log.i(TAG, "+++ b4 connect");
clientSocket.connect();
Log.i(TAG, "+++ connected");
isConnected = true;
in = new DataInputStream(clientSocket.getInputStream());
out = new DataOutputStream(clientSocket.getOutputStream());
Log.i(TAG, "+++ streams created");
} catch (IOException e) {
Long sleep = (long) 10000;
Log.e(TAG, "+++ connection failed, sleep for " + sleep);
try {
Thread.sleep(sleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}
return isConnected;
}
public void run() {
try {
getDevice();
} catch (IOException e) {
Log.e(TAG, "+++ device error " + e.toString());
}
while (isRunning) {
try {
processData();
} catch (Exception e) {
Log.e(TAG, "+++ data error " + e.toString());
}
}
close();
Log.i(TAG, "+++ ending bluetooth run");
}
private void closeSocket() {
if (clientSocket != null)
try {
clientSocket.close();
Log.d(TAG, "+++ socket closed");
} catch (IOException e) {
e.printStackTrace();
}
}
private void closeStreams() {
if (in != null)
try {
in.close();
Log.d(TAG, "+++ input stream closed");
} catch (IOException e) {
Log.e(TAG, "+++ input stream not closed " + e.toString());
}
if (out != null)
try {
out.close();
Log.d(TAG, "+++ output stream closed");
} catch (IOException e) {
Log.e(TAG, "+++ output stream not closed " + e.toString());
}
}
private void close() {
closeStreams();
closeSocket();
isConnected = false;
}
public void stop() {
isRunning = false;
}
public boolean isRunning() {
return isRunning;
}
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
private void processData() throws Exception {
try {
String outData = null;
int timer = 0;
while (outData == null) {
if (!connect())
return;
Log.i(TAG, "+++ waiting on queue ");
outData = queue.poll(1, TimeUnit.SECONDS);// .take();
if (timer++ > 15) {
return;
}
}
envelope.sendMessage(outData, out);
String inData = envelope.receiveMessage(in);
Log.i(TAG, "+++ response " + inData);
} catch (Exception e) {
Log.e(TAG, "+++ processData error " + e.toString());
close();
throw e;
}
}
}