java 如果连接丢失,Android 会重新连接到蓝牙设备
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30069577/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android reconnect to bluetooth device if connection lost
提问by Tadej Vengust
My phone is connecting to a bluetooth device and it works normally. It connect and the connection holds. I can change orientation, have my app in the background, I can close app and when I turn it back on it will automatically connect. But from app users I get some reports that the connection is lost after a period of time(no pattern detected). I have tried to recreate this but with no luck. So to avoid this problem I want to implement an automatic reconnect to the previously selected device if connection is lost.
我的手机正在连接蓝牙设备并且工作正常。它连接并且连接保持。我可以改变方向,让我的应用程序在后台运行,我可以关闭应用程序,当我重新打开它时,它会自动连接。但是从应用程序用户那里我得到一些报告说一段时间后连接丢失(没有检测到模式)。我试图重新创建这个,但没有运气。所以为了避免这个问题,如果连接丢失,我想实现自动重新连接到先前选择的设备。
I did some reasearch that this could be done by implementing a broadcast reciever that would detect: android.bluetooth.device.action.ACL_DISCONNECTED
我做了一些研究,这可以通过实现一个广播接收器来检测: android.bluetooth.device.action.ACL_DISCONNECTED
What my questions are:
我的问题是:
- I already have a broadcast reciever that is triggered on device bootup. Should I extend this reciever to add the ACL_DISCONNECTED or add a separate reciever?
- My BluetoothService is initialised on my mainactivity, but I will need to reconnect from the intent. How to do that.
- 我已经有一个在设备启动时触发的广播接收器。我应该扩展这个接收器来添加 ACL_DISCONNECTED 还是添加一个单独的接收器?
- 我的 BluetoothService 是在我的主要活动上初始化的,但我需要从意图重新连接。怎么做。
Thanks for your answer.
感谢您的回答。
BluetoothServis code:
蓝牙服务代码:
public class BluetoothService
{
// Debugging
private static final String TAG = "BluetoothService";
private static final UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
// Member fields
private final BluetoothAdapter mAdapter;
private final Handler mHandler;
private final Context mContext;
private ConnectThread mConnectThread;
private ConnectedThread mConnectedThread;
private int mState;
// Constants that indicate the current connection state
public static final int STATE_NONE = 0; // we're doing nothing
public static final int STATE_CONNECTING = 1; // now initiating an outgoing connection
public static final int STATE_CONNECTED = 2; // now connected to a remote device
public BluetoothService(Context context, Handler handler)
{
mAdapter = BluetoothAdapter.getDefaultAdapter();
mState = STATE_NONE;
mHandler = handler;
mContext = context;
}
private synchronized void setState(int state)
{
mState = state;
mHandler.obtainMessage(MainActivity.MESSAGE_STATE_CHANGE, state, -1).sendToTarget();
}
public synchronized int getState()
{
return mState;
}
public synchronized void start()
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
}
public synchronized void connect(BluetoothDevice device)
{
if (mState == STATE_CONNECTING)
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
}
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectThread = new ConnectThread(device);
mConnectThread.start();
setState(STATE_CONNECTING);
}
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device, final String socketType)
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
mConnectedThread = new ConnectedThread(socket, socketType);
mConnectedThread.start();
Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_DEVICE_NAME);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.DEVICE_NAME, device.getName());
msg.setData(bundle);
mHandler.sendMessage(msg);
setState(STATE_CONNECTED);
}
public synchronized void stop()
{
if (mConnectThread != null)
{
mConnectThread.cancel();
mConnectThread = null;
}
if (mConnectedThread != null)
{
mConnectedThread.cancel();
mConnectedThread = null;
}
setState(STATE_NONE);
}
public void write(byte[] out)
{
ConnectedThread r;
synchronized (this)
{
if (mState != STATE_CONNECTED) return;
r = mConnectedThread;
}
r.write(out);
}
private void connectionFailed()
{
Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.TOAST, mContext.getResources().getString(R.string.cant_connect));
msg.setData(bundle);
mHandler.sendMessage(msg);
BluetoothService.this.start();
}
private class ConnectThread extends Thread
{
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
private String mSocketType;
public ConnectThread(BluetoothDevice device)
{
mmDevice = device;
BluetoothSocket tmp = null;
mSocketType = "Secure";
// another option createInsecureRfcommSocketToServiceRecord
try
{
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
}
catch (IOException e)
{
Log.e(TAG, "Socket Type: " + mSocketType + "create() failed", e);
}
/*
Method m = null;
try {
m = mmDevice.getClass().getMethod("createRfcommSocket", new Class[] {int.class});
tmp = (BluetoothSocket) m.invoke(mmDevice, 1);
} catch (Exception e) {
e.printStackTrace();
}*/
mmSocket = tmp;
}
public void run()
{
Log.i(TAG, "BEGIN mConnectThread SocketType:" + mSocketType);
setName("ConnectThread" + mSocketType);
mAdapter.cancelDiscovery();
try
{
mmSocket.connect();
Log.i(TAG, "ConnectThread running");
}
catch (IOException e)
{
try
{
mmSocket.close();
}
catch (IOException e2)
{
Log.e(TAG, "unable to close() " + mSocketType + " socket during connection failure", e2);
}
connectionFailed();
return;
}
synchronized (BluetoothService.this)
{
mConnectThread = null;
}
connected(mmSocket, mmDevice, mSocketType);
}
public void cancel()
{
try
{
mmSocket.close();
}
catch (IOException e)
{
Log.e(TAG, "close() of connect " + mSocketType + " socket failed", e);
}
}
}
private class ConnectedThread extends Thread
{
private final BluetoothSocket mmSocket;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket, String socketType)
{
mmSocket = socket;
OutputStream tmpOut = null;
try
{
tmpOut = socket.getOutputStream();
}
catch (IOException e)
{
Log.e(TAG, "temp sockets not created", e);
}
mmOutStream = tmpOut;
}
public void run()
{
}
public void write(byte[] buffer)
{
try
{
mmOutStream.write(buffer);
try
{
sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
catch (IOException e)
{
Log.e(TAG, "Exception during write", e);
}
}
public void cancel()
{
try
{
mmSocket.close();
}
catch (IOException e)
{
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
}
}
回答by Tadej Vengust
I solved this in 2 stages. First I created a new broadcast reciever because my existing one was for ACTION_BOOT_COMPLETED and had to be declared in the android manifest. The one I created had to be dynamic because I needed an instance of MainActivity:
我分两个阶段解决了这个问题。首先,我创建了一个新的广播接收器,因为我现有的广播接收器用于 ACTION_BOOT_COMPLETED 并且必须在 android manifest 中声明。我创建的必须是动态的,因为我需要一个 MainActivity 实例:
if (bluetoothLostReceiver == null)
{
bluetoothLostReceiver = new BluetoothLostReceiver();
bluetoothLostReceiver.setMainActivity(this);
IntentFilter filter = new IntentFilter("android.bluetooth.device.action.ACL_DISCONNECTED");
registerReceiver(bluetoothLostReceiver, filter);
}
And in my reciever I tried a new connect to the printer. I added an additional paramenter tryBluetoothReconnect so that if I wanted to close the connection it wouldn't try to reconnect.
在我的接收器中,我尝试了与打印机的新连接。我添加了一个额外的参数 tryBluetoothReconnect,这样如果我想关闭连接,它就不会尝试重新连接。
public class BluetoothLostReceiver extends BroadcastReceiver {
MainActivity main = null;
public void setMainActivity(MainActivity main)
{
this.main = main;
}
@Override
public void onReceive(Context context, Intent intent) {
if(BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(intent.getAction()) && Global.tryBluetoothReconnect)
{
if(Global.PosPrinterDeviceName != null && !Global.PosPrinterDeviceName.equals(""))
main.connectPrinter(Global.PosPrinterDeviceName);
}else
{
Global.tryBluetoothReconnect = true;
}
}
}
I also upgraded my Bluetooth service so that if connection was not successful (connectionFailed() method) it would try 4 more times:
我还升级了我的蓝牙服务,以便如果连接不成功(connectionFailed() 方法)它会再尝试 4 次:
if(tryCount >= 4)
{
tryCount = 0;
Message msg = mHandler.obtainMessage(MainActivity.MESSAGE_TOAST);
Bundle bundle = new Bundle();
bundle.putString(MainActivity.TOAST, mContext.getResources().getString(R.string.cant_connect));
msg.setData(bundle);
mHandler.sendMessage(msg);
BluetoothService.this.start();
}
else
{
tryCount++;
connect(bluetoothDevice);
}
Hope this helps anyone with the same problem.
希望这可以帮助任何有同样问题的人。