如果连接丢失,Android将重新连接到蓝牙设备

时间:2015-05-06 06:53:57

标签: java android bluetooth android-broadcast android-bluetooth

我的手机正在连接蓝牙设备并且正常工作。它连接并且连接成立。我可以更改方向,在后台安装我的应用程序,我可以关闭应用程序,当我将其重新打开时,它将自动连接。但是从应用程序用户那里我得到一些报告说连接在一段时间后丢失(没有检测到模式)。我试图重新创造这个,但没有运气。因此,为了避免这个问题,如果连接丢失,我想实现自动重新连接到之前选择的设备。

我做了一些研究,可以通过实施一个可以检测到的广播接收器来完成:android.bluetooth.device.action.ACL_DISCONNECTED

我的问题是:

  • 我已经有一个在设备上触发的广播接收器 在启动。我应该扩展此接收器以添加ACL_DISCONNECTED或 添加一个单独的收货人?
  • 我的BluetoothService初始化了我的mainactivity,但是我需要重新连接intent。怎么做。

感谢您的回答。

BluetoothServis代码:

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);
        }
    }
}

}

1 个答案:

答案 0 :(得分:6)

我分两个阶段解决了这个问题。 首先我创建了一个新的广播接收器,因为我现有的广播接收器是ACTION_BOOT_COMPLETED并且必须在android清单中声明。我创建的那个必须是动态的,因为我需要一个MainActivity实例:

 if (bluetoothLostReceiver == null)
        {
            bluetoothLostReceiver = new BluetoothLostReceiver();
            bluetoothLostReceiver.setMainActivity(this);
            IntentFilter filter = new IntentFilter("android.bluetooth.device.action.ACL_DISCONNECTED");
            registerReceiver(bluetoothLostReceiver, filter);
        }

在我的收件人中,我尝试了一个新的连接到打印机。我添加了一个额外的参数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;
        }
    }
}

我还升级了我的蓝牙服务,这样如果连接不成功(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);
    }

希望这可以帮助任何有同样问题的人。