How to move Bluetooth activity into a Service
Solution 1:
I have written a Bluetooth services which runs in the background and can communicate to any Activity in the application using Messenger http://developer.android.com/guide/components/bound-services.html.
public class PrinterService extends Service {
private BluetoothAdapter mBluetoothAdapter;
public static final String BT_DEVICE = "btdevice";
public static final String SPP_UUID = "00001101-0000-1000-8000-00805F9B34FB";
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_LISTEN = 1; // now listening for incoming
// connections
public static final int STATE_CONNECTING = 2; // now initiating an outgoing
// connection
public static final int STATE_CONNECTED = 3; // now connected to a remote
// device
private ConnectThread mConnectThread;
private static ConnectedThread mConnectedThread;
// public mInHangler mHandler = new mInHangler(this);
private static Handler mHandler = null;
public static int mState = STATE_NONE;
public static String deviceName;
public Vector<Byte> packdata = new Vector<Byte>(2048);
public static Device device = null;
@Override
public void onCreate() {
Log.d("PrinterService", "Service started");
super.onCreate();
}
@Override
public IBinder onBind(Intent intent) {
mHandler = ((MyAplication) getApplication()).getHandler();
return mBinder;
}
public class LocalBinder extends Binder {
PrinterService getService() {
return PrinterService.this;
}
}
private final IBinder mBinder = new LocalBinder();
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("PrinterService", "Onstart Command");
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter != null) {
device = (Device) intent.getSerializableExtra(BT_DEVICE);
deviceName = device.getDeviceName();
String macAddress = device.getMacAddress();
if (macAddress != null && macAddress.length() > 0) {
connectToDevice(macAddress);
} else {
stopSelf();
return 0;
}
}
String stopservice = intent.getStringExtra("stopservice");
if (stopservice != null && stopservice.length() > 0) {
stop();
}
return START_STICKY;
}
private synchronized void connectToDevice(String macAddress) {
BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(macAddress);
if (mState == STATE_CONNECTING) {
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
private void setState(int state) {
PrinterService.mState = state;
if (mHandler != null) {
mHandler.obtainMessage(AbstractActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
}
public synchronized void stop() {
setState(STATE_NONE);
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
if (mBluetoothAdapter != null) {
mBluetoothAdapter.cancelDiscovery();
}
stopSelf();
}
@Override
public boolean stopService(Intent name) {
setState(STATE_NONE);
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
mBluetoothAdapter.cancelDiscovery();
return super.stopService(name);
}
private void connectionFailed() {
PrinterService.this.stop();
Message msg = mHandler.obtainMessage(AbstractActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(AbstractActivity.TOAST, getString(R.string.error_connect_failed));
msg.setData(bundle);
mHandler.sendMessage(msg);
}
private void connectionLost() {
PrinterService.this.stop();
Message msg = mHandler.obtainMessage(AbstractActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(AbstractActivity.TOAST, getString(R.string.error_connect_lost));
msg.setData(bundle);
mHandler.sendMessage(msg);
}
private static Object obj = new Object();
public static void write(byte[] out) {
// Create temporary object
ConnectedThread r;
// Synchronize a copy of the ConnectedThread
synchronized (obj) {
if (mState != STATE_CONNECTED)
return;
r = mConnectedThread;
}
// Perform the write unsynchronized
r.write(out);
}
private synchronized void connected(BluetoothSocket mmSocket, BluetoothDevice mmDevice) {
// Cancel the thread that completed the connection
if (mConnectThread != null) {
mConnectThread.cancel();
mConnectThread = null;
}
// Cancel any thread currently running a connection
if (mConnectedThread != null) {
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectedThread = new ConnectedThread(mmSocket);
mConnectedThread.start();
// Message msg =
// mHandler.obtainMessage(AbstractActivity.MESSAGE_DEVICE_NAME);
// Bundle bundle = new Bundle();
// bundle.putString(AbstractActivity.DEVICE_NAME, "p25");
// msg.setData(bundle);
// mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
this.mmDevice = device;
BluetoothSocket tmp = null;
try {
tmp = device.createRfcommSocketToServiceRecord(UUID.fromString(SPP_UUID));
} catch (IOException e) {
e.printStackTrace();
}
mmSocket = tmp;
}
@Override
public void run() {
setName("ConnectThread");
mBluetoothAdapter.cancelDiscovery();
try {
mmSocket.connect();
} catch (IOException e) {
try {
mmSocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
connectionFailed();
return;
}
synchronized (PrinterService.this) {
mConnectThread = null;
}
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e("PrinterService", "close() of connect socket failed", e);
}
}
}
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
mmSocket = socket;
InputStream tmpIn = null;
OutputStream tmpOut = null;
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
} catch (IOException e) {
Log.e("Printer Service", "temp sockets not created", e);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
@Override
public void run() {
while (true) {
try {
if (!encodeData(mmInStream)) {
mState = STATE_NONE;
connectionLost();
break;
} else {
}
// mHandler.obtainMessage(AbstractActivity.MESSAGE_READ,
// bytes, -1, buffer).sendToTarget();
} catch (Exception e) {
e.printStackTrace();
connectionLost();
PrinterService.this.stop();
break;
}
}
}
private byte[] btBuff;
public void write(byte[] buffer) {
try {
mmOutStream.write(buffer);
// Share the sent message back to the UI Activity
mHandler.obtainMessage(AbstractActivity.MESSAGE_WRITE, buffer.length, -1, buffer).sendToTarget();
} catch (IOException e) {
Log.e("PrinterService", "Exception during write", e);
}
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e("PrinterService", "close() of connect socket failed", e);
}
}
}
public void trace(String msg) {
Log.d("AbstractActivity", msg);
toast(msg);
}
public void toast(String msg) {
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show();
}
@Override
public void onDestroy() {
stop();
Log.d("Printer Service", "Destroyed");
super.onDestroy();
}
private void sendMsg(int flag) {
Message msg = new Message();
msg.what = flag;
handler.sendMessage(msg);
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {//
if (!Thread.currentThread().isInterrupted()) {
switch (msg.what) {
case 3:
break;
case 4:
break;
case 5:
break;
case -1:
break;
}
}
super.handleMessage(msg);
}
};
}
UPDATE
you need to use Handler in your MyApplication Class
Handler.Callback realCallback = null;
Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
if (realCallback != null) {
realCallback.handleMessage(msg);
}
};
};
public Handler getHandler() {
return handler;
}
public void setCallBack(Handler.Callback callback) {
this.realCallback = callback;
}