未连接到目标设备

未连接到目标设备

本文介绍了BluetoothSocket 未连接到目标设备的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试通过蓝牙将我的设备连接到另一个设备,但是当我选择要连接的设备时,我收到一个 IOException

读取失败,套接字可能关闭或超时,读取 ret: -1

为了说明我的应用程序是如何工作的,我有一个 RecyclerView 填充了我的蓝牙扫描找到的设备,然后当我点击一个项目时,应用程序应该与该设备连接.>

以下是我的连接线程代码:

private val MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")私有 lateinit var 设备:BluetoothDeviceprivate lateinit var onDeviceActionListener: OnDeviceActionListener私有 lateinit var 套接字:BluetoothSocket有趣的初始化(设备:蓝牙设备,onDeviceActionListener: OnDeviceActionListener): ConnectionThread {this.device = 设备this.onDeviceActionListener = onDeviceActionListener尝试 {socket = device.createRfcommSocketToServiceRecord(MY_UUID)} catch (e: IOException) {Log.e(TAG, "创建套接字时出错", e)}返回这个}覆盖乐趣运行(){尝试 {套接字连接()} catch (openException: IOException) {Log.e(TAG, 打开连接时出错.试图关闭...", openException)尝试 {socket.close()} 捕捉(关闭异常:IOException){Log.e(TAG, "关闭套接字时出错", closeException)}返回}onDeviceActionListener.onDeviceConnect(设备)}

我的猜测是我的 UUID 有问题.我已经尝试了一些其他的值,但仍然没有奏效.

任何帮助将不胜感激.

解决方案

好吧,我不明白你在这里做错了什么.但是,我已经做了相当多的蓝牙工作.最近只专注于 BLE.您应该能够发现附近的 BT 设备并查看它们的 UUID.

我大约 3 年前写了一个辅助类,所以它有点旧,但应该大部分是相同的代码.如果有帮助,很高兴与您分享.

public class BluetoothConnector {private static final String TAG = Globals.SEARCH_STRING + BluetoothConnector.class.getSimpleName();private static final String DEFAULT_SERVER_NAME_FOR_APP = "tn_bt_default_server";私有静态最终 int DEFAULT_DISCOVERABLE_DURATION_MS = 30000;private static final UUID DEFAULT_UUID = UUID.fromString("6534c201-039c-4e4f-89f9-5ca8cfeb9667");public static final int ENABLE_DISCOVER_INTENT = 1002;protected boolean mIsToastEnabled = false;//从调用类访问以在必要时启用进度烘烤到屏幕私人处理程序 mUIHandler;私有静态 ServerSocketThread mServerSocketThread;私有静态 ClientSocketThread mClientSocketThread;私有 ManageConnectionThread mManageConnectionThread;私有上下文 mContext;私有 IBluetoothDataListener mBluetoothDataListener;public final Object ServerSocketLock = new Object();public final Object ClientSocketLock = new Object();public final Object ManageConnectionLock = new Object();公共蓝牙连接器(上下文上下文,IBluetoothDataListener 侦听器){this(context, new Handler(Looper.getMainLooper()), listener);}公共蓝牙连接器(上下文上下文,处理程序 UIHandler,IBluetoothDataListener 侦听器){Log.v(TAG, "BluetoothConnector(context=" + context + ", Handler=" + UIHandler.getClass().getSimpleName() + ", IBluetoothDataListener=" + listener.getClass().getSimpleName());mContext = 上下文;mUIHandler = UIHandler;mBluetoothDataListener = 监听器;}公共无效makeThisDeviceDiscoverable(活动调用活动){makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), DEFAULT_DISCOVERABLE_DURATION_MS);}公共无效makeThisDeviceDiscoverable(活动调用活动,蓝牙适配器适配器){makeThisDeviceDiscoverable(调用Activity,适配器,DEFAULT_DISCOVERABLE_DURATION_MS);}公共无效makeThisDeviceDiscoverable(活动调用活动,int durationInMs){makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), durationInMs);}public void makeThisDeviceDiscoverable(Activity callActivity, BluetoothAdapter adapter, int durationInMs) {Log.v(TAG, "makeThisDeviceDiscoverable(callingActivity=" + callsActivity.getClass().getSimpleName() + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()) + ", duration=" + String.valueOf(durationInMs));如果(适配器 == 空){Log.v(TAG, "适配器为空");}else if(adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {Log.v(TAG, "启动活动以请求可发现权限");Intent discoveryableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,durationInMs);调用Activity.startActivityForResult(discoverableIntent, ENABLE_DISCOVER_INTENT);}别的{Log.v(TAG, "适配器已处于扫描模式");}}公共无效 awaitConnectionFromDevice(){awaitConnectionFromDevice(DEFAULT_UUID, BluetoothAdapter.getDefaultAdapter());}public void awaitConnectionFromDevice(UUID commonKey){awaitConnectionFromDevice(commonKey, BluetoothAdapter.getDefaultAdapter());}public void awaitConnectionFromDevice(BluetoothAdapter 适配器){awaitConnectionFromDevice(DEFAULT_UUID,适配器);}public void awaitConnectionFromDevice(UUID commonKey,BluetoothAdapter 适配器){Log.v(TAG, "awaitConnectionFromDevice for UUID: " + String.valueOf(commonKey) + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));取消发现();同步(ServerSocketLock){如果(mServerSocketThread != null){Log.v(TAG, "服务器套接字线程不为空​​所以取消当前线程");mServerSocketThread.cancel();}Log.v(TAG, "试图启动新的 ServerThread");mServerSocketThread = new ServerSocketThread(commonKey, adapter);mServerSocketThread.start();}}public void cancelAwaitingConnectionFromDevice(){Log.v(TAG, "cancelAwaitingConnectionFromDevice");同步(ServerSocketLock){如果(mServerSocketThread != null){mServerSocketThread.cancel();mServerSocketThread = null;Log.v(TAG, "取消服务器套接字线程");}别的{Log.v(TAG, "Server Socket null, so not canceling");}}}公共无效开始发现(){startDiscovery(BluetoothAdapter.getDefaultAdapter());}public void startDiscovery(蓝牙适配器适配器){Log.v(TAG, "startDiscovery 以查找范围内的设备列表");适配器.startDiscovery();}公共无效取消发现(){cancelDiscovery(BluetoothAdapter.getDefaultAdapter());}公共无效取消发现(蓝牙适配器适配器){Log.v(TAG, "cancelDiscovery");适配器.cancelDiscovery();}公共无效connectToDevice(蓝牙设备设备){连接到设备(设备,DEFAULT_UUID);}public void connectToDevice(蓝牙设备设备,UUID commonKey){Log.v(TAG, "connectToDevice(BluetoothDevice=" + (device == null ? "null" : device.getName()) + ", UUID=" + String.valueOf(commonKey));同步(ClientSocketLock){if(mClientSocketThread != null){Log.v(TAG, "客户端套接字线程不为空​​所以取消当前线程");mClientSocketThread.cancel();}别的{Log.v(TAG, "Client Socket Thread is NULL 所以不会取消");}Log.v(TAG, "ClientSocketThread 启动");mClientSocketThread = new ClientSocketThread(device, commonKey);mClientSocketThread.start();}}公共蓝牙设备 getBluetoothDeviceByMac(字符串 mac){Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac);返回 getBluetoothDeviceByMac(mac, BluetoothAdapter.getDefaultAdapter());}public BluetoothDevice getBluetoothDeviceByMac(字符串mac,BluetoothAdapter适配器){Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));返回适配器.getRemoteDevice(mac);}公共 ArrayListgetPairedDevices(){返回 getPairedDevices(BluetoothAdapter.getDefaultAdapter());}公共 ArrayListgetPairedDevices(蓝牙适配器适配器){ArrayListBondDevices = new ArrayList();设置pairedDevices = adapter.getBondedDevices();Log.v(TAG, "getPairedDevices Found " + pairedDevices.size() + " 配对设备数量");//如果有配对的设备如果 (pairedDevices.size() > 0) {//遍历配对设备对于(蓝牙设备:pairedDevices){//将名称和地址添加到数组适配器以显示在 ListView 中bondDevices.add(new KeyValueModel(device.getAddress(), device.getName()));}}返回bondedDevices;}public static void unpairDevice(BluetoothDevice device){Log.v(TAG, "unpairDevice");尝试{Method method = device.getClass().getMethod("removeBond", (Class[]) null);method.invoke(device, (Object[]) null);}catch(异常前){Log.e(TAG, "错误取消配对设备:" + ex.getMessage());}}public boolean sendDataToConnectedDevice(byte[] data){Log.v(TAG, "sendDataToConnectedDevice");同步(管理连接锁){mManageConnectionThread.write(data);返回真;}}public void setBluetoothDataListener(IBluetoothDataListener 监听器){mBluetoothDataListener = 监听器;}公共布尔 getIsConnected(){同步(管理连接锁){返回 mManageConnectionThread != null &&mManageConnectionThread.isAlive();}}private void startManageConnectionThread(BluetoothSocket socket){Log.v(TAG, "startManageConnectionThread for Socket:" + (socket == null ? "null" : socket.getClass().getSimpleName()));同步(管理连接锁){mManageConnectionThread = new ManageConnectionThread(socket);mManageConnectionThread.start();}}private void handleDataReceivedFromConnectedDevice(final byte[] bytes){Log.v(TAG, "handleDataReceivedFromConnectedDevice");Log.v(TAG, "要监听的字节数:" + new String(bytes));if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onReceivedPayloadFromConnectedDevice(bytes);}}});}别的{Log.v(TAG, "UIHandler 为空,因此跳过将有效负载发送到侦听器");}}私有无效句柄连接(){Log.e(TAG, "handleConnected");if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onConnectedToTargetDevice();}}});}别的{Log.v(TAG, "UIHandler 为空,因此跳过将有效负载发送到侦听器");}}私有无效handleDisconnected(){Log.e(TAG, "handleDisconnected");if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onDisconnectedFromTargetDevice();}}});}别的{Log.v(TAG, "UIHandler 或 Listener 为空,因此跳过将有效负载发送到侦听器");}}私有无效 handleFailedToConnectAsServer(最终异常前){Log.e(TAG, "handleFailedToConnectAsServer ex:" + ex.getMessage());if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onFailedToReceiveConnectionFromTargetDevice(ex);}}});}别的{Log.v(TAG, "UIHandler 或 Listener 为空,因此跳过将有效负载发送到侦听器");}}私有无效 handleFailedToConnectAsClient(最终异常前){Log.e(TAG, "handleFailedToConnectAsClient ex:" + ex.getMessage());if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onFailedToConnectToTargetDevice(ex);}}});}别的{Log.v(TAG, "UIHandler 或 Listener 为空,因此跳过将有效负载发送到侦听器");}}私有无效handleErrorInRetrievingData(最终异常前){Log.e(TAG, "handleErrorInRetrievingData ex:" + ex.getMessage());if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onErrorReceivingPayloadFromConnectedDevice(ex);}}});}别的{Log.v(TAG, "UIHandler 或 Listener 为空,因此跳过将有效负载发送到侦听器");}}私有无效handleFailedToSendDataToConnectedDevice(最终异常前){Log.e(TAG, "handleFailedToSendDataToConnectedDevice ex:" + ex.getMessage());if(mUIHandler != null && mBluetoothDataListener != null){mUIHandler.post(new Runnable() {@覆盖公共无效运行(){如果(mBluetoothDataListener != null){mBluetoothDataListener.onFailedToSendDataToConnectedDevice(ex);}}});}别的{Log.v(TAG, "UIHandler 或 Listener 为空,因此跳过将有效负载发送到侦听器");}}私有无效toastMessage(最终字符串值){if(!mIsToastEnabled || mUIHandler == null) {返回;}mUIHandler.post(new Runnable() {@覆盖公共无效运行(){尝试{Toast.makeText(mContext, value, Toast.LENGTH_SHORT).show();}catch(异常前){Log.v(TAG, "Error Toasting, 可能是错误的处理程序,或上下文:" + ex.getMessage());}}});}私有类 ServerSocketThread 扩展了 Thread{私有最终字符串标记 = Globals.SEARCH_STRING + ServerSocketThread.class.getSimpleName();私有最终 BluetoothServerSocket mServerSocket;public ServerSocketThread(UUID commonKey,BluetoothAdapter 适配器){Log.v(TAG, "ServerSocketThread 构造函数");BluetoothServerSocket tmp = null;尝试 {Log.v(TAG, "侦听 RFComas 服务器: " + DEFAULT_SERVER_NAME_FOR_APP + ", and commonKey: " + String.valueOf(commonKey));//MY_UUID 是应用程序的 UUID 字符串,也由客户端代码使用tmp = adapter.listenUsingRfcommWithServiceRecord(DEFAULT_SERVER_NAME_FOR_APP, commonKey);toastMessage("在 UUID 上侦听 RFComm 作为服务器:" + String.valueOf(commonKey));} catch (IOException e) {Log.e(TAG, "创建 ServerSocket 时出错:" + e.getMessage());toastMessage("创建ServerSocket时出错:" + e.getMessage());}mServerSocket = tmp;}公共无效运行(){Log.v(TAG, "ServerSocket 运行");BluetoothSocket 套接字 = null;//一直监听直到发生异常或返回套接字while (mServerSocket != null) {尝试 {Log.v(TAG, "ServerSocket.accept()");toastMessage("ServerSocket.accept()");//等待Client Connection通过Socket,然后我们关闭socket = mServerSocket.accept();} catch (IOException e) {Log.e(TAG, "ServerSocket.accept() 错误:" + e.getMessage());toastMessage("ServerSocket.accept() 错误:" + e.getMessage());handleFailedToConnectAsServer(e);休息;}//如果连接被接受,我们不需要保持服务器监听,除非需要多个客户端/服务器连接,否则关闭如果(套接字!= null){尝试{Log.v(TAG, "ServerSocket 接受客户端套接字,开始监听连接线程");toastMessage("ServerSocket 接受客户端套接字,开始监听连接线程");//做管理连接的工作(在一个单独的线程中)startManageConnectionThread(socket);//mServerSocket.close();}catch(异常前){Log.e(TAG, "异常关闭服务器套接字");}//休息;//如果要关闭监听连接,则添加Break}别的{Log.v(TAG, "套接字未被接受");toastMessage("套接字未被接受");handleFailedToConnectAsServer(new Exception("Socket is Null"));}}Log.v(TAG, "退出服务器接受线程");}公共无效取消(){尝试 {Log.v(TAG, "ServerSocketThread 取消");mServerSocket.close();} catch (IOException e) {Log.e(TAG, "ServerSocketThread 错误:" + e.getMessage());}}}私有类 ClientSocketThread 扩展了 Thread{私有BluetoothSocket mSocket;私有最终蓝牙设备 mDevice;公共 ClientSocketThread(蓝牙设备设备,UUID commonKey){Log.v(TAG, "ClientSocketThread 构造函数");//使用稍后分配给 mmSocket 的临时对象,//因为 mmSocket 是最终的BluetoothSocket tmp = null;mDevice = 设备;//获取一个BluetoothSocket 来连接给定的BluetoothDevice尝试 {Log.v(TAG, "客户端使用 UUID 创建到服务器的 RFComm 套接字:" + String.valueOf(commonKey));toastMessage("客户端使用 UUID 创建到服务器的 RFComm 套接字:" + String.valueOf(commonKey));//MY_UUID 是应用程序的 UUID 字符串,也由服务器代码使用tmp = device.createRfcommSocketToServiceRecord(commonKey);} catch (IOException e) {Log.e(TAG, "创建客户端套接字时出错:" + e.getMessage());toastMessage("创建套接字异常:" + e.getMessage());handleFailedToConnectAsClient(e);}mSocket = tmp;}公共无效运行(){尝试 {if(mSocket == null){Log.e(TAG, "Error Client Socket is Null, Canceling Client Thread");返回;}Log.v(TAG, "客户端连接");//连接到服务器,最终还是超时toastMessage("客户端连接");mSocket.connect();} catch (IOException connectException) {//无法连接;关闭socket,尝试使用反射的fallback方法与端口连接尝试 {Log.e("", "尝试回退...");toastMessage("客户端连接失败异常:" + connectException.getMessage());mSocket = (BluetoothSocket) mDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mDevice, 1);toastMessage("客户端再次连接尝试 2,但有回退反射和端口");Log.v(TAG, "Client Connect Again Attempt 2, but with fall back Reflection and port");mSocket.connect();Log.e("", "已连接");toastMessage("客户端连接");} 捕捉(异常前){Log.e("", "无法建立蓝牙连接!");toastMessage("客户端无法与服务器建立连接:" + ex.getMessage());handleFailedToConnectAsClient(ex);返回;}}//做管理连接的工作(在一个单独的线程中)startManageConnectionThread(mSocket);}公共无效取消(){尝试 {Log.v(TAG, "客户端套接字取消");mSocket.close();} catch (IOException e) {Log.e(TAG, "关闭套接字时出错");}}}私有类 ManageConnectionThread 扩展线程 {///////////////成员///////////////private final String TAG = Globals.SEARCH_STRING + ManageConnectionThread.class.getSimpleName();私有最终 BluetoothSocket mSocket;私有最终 InputStream mInStream;私有最终输出流 mOutStream;/////////////////////构造函数/////////////////////公共管理连接线程(蓝牙套接字){mSocket = 套接字;句柄连接();输入流 tmpIn = null;输出流 tmpOut = null;//使用临时对象获取输入和输出流,因为尝试 {Log.v(TAG, "ManageConnectionThread 构造函数");Log.v(TAG, "连接到套接字 = " + String.valueOf(socket.isConnected()));toastMessage("监听输入或输出流");Log.v(TAG, "获取输入流");tmpIn = socket.getInputStream();Log.v(TAG, "获取输出流");tmpOut = socket.getOutputStream();} catch (IOException e) {Log.e(TAG, "获取套接字流时出错:" + e.getMessage());toastMessage("连接线程:错误:" + e.getMessage());handleErrorInRetrievingData(e);}mInStream = tmpIn;mOutStream = tmpOut;}/////////////////覆盖/////////////////公共无效运行(){//一直监听InputStream,直到发生异常而(真){尝试 {//从输入流中读取字节[]数据=新字节[16384];int nRead;ByteArrayOutputStream 缓冲区 = new ByteArrayOutputStream();while ((nRead = mInStream.read(data, 0, data.length)) != -1) {//Log.v(TAG, "bytes Read:" + String.valueOf(nRead));buffer.write(data, 0, nRead);//TODO 寻找更好的方法来找到消息结束而不是寻找 }String temp = new String(buffer.toByteArray());//Log.v(TAG, "当前数据:" + temp);if(temp.contains("}")){Log.v(TAG, "字节读取完成");handleDataReceivedFromConnectedDevice(buffer.toByteArray());缓冲区.flush();缓冲区 = 新的 ByteArrayOutputStream();}别的{Log.v(TAG, "更多可用字节");}}} catch (IOException e) {Log.e(TAG, "读取输入流时出错");handleErrorInRetrievingData(e);休息;}}Log.v(TAG, "退出托管连接线程");处理断开();}///////////////方法///////////////公共无效写(字节[]字节){尝试 {Log.v(TAG, "ManageConnectionThread write(bytes)");mOutStream.write(bytes);} catch (IOException e) {Log.e(TAG, "错误写入流:" + e.getMessage());handleFailedToSendDataToConnectedDevice(e);}}公共无效取消(){尝试 {Log.v(TAG, "ManageConnectionThread 取消");处理断开();mSocket.close();} catch (IOException e) {Log.e(TAG, "关闭蓝牙套接字时出错:" + e.getMessage());}}}公共接口 IBluetoothDataListener{///////////////////////重写方法///////////////////////void onReceivedPayloadFromConnectedDevice(byte[] payload);void onErrorReceivingPayloadFromConnectedDevice(Exception ex);void onFailedToConnectToTargetDevice(Exception ex);void onFailedToReceiveConnectionFromTargetDevice(Exception ex);void onFailedToSendDataToConnectedDevice(Exception ex);void onConnectedToTargetDevice();void onDisconnectedFromTargetDevice();}

}

当然,您需要确保设置了广播接收器:

 

I'm trying to connect my device to another one via Bluetooth, but when I select the device I want to connect with, I get an IOException saying

Just to illustrate how my app works, I have a RecyclerView populated with the devices my Bluetooth scan has found, then when I click an item the app is supposed to connect with that device.

Below is my the code for my connection thread:

private val MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb")

private lateinit var device: BluetoothDevice
private lateinit var onDeviceActionListener: OnDeviceActionListener
private lateinit var socket: BluetoothSocket

fun init(device: BluetoothDevice,
         onDeviceActionListener: OnDeviceActionListener): ConnectionThread {
    this.device = device
    this.onDeviceActionListener = onDeviceActionListener
    try {
        socket = device.createRfcommSocketToServiceRecord(MY_UUID)
    } catch (e: IOException) {
        Log.e(TAG, "Error creating socket", e)
    }
    return this
}

override fun run() {
    try {
        socket.connect()
    } catch (openException: IOException) {
        Log.e(TAG, "Error opening connection. Trying to close...", openException)
        try {
            socket.close()
        } catch (closeException: IOException) {
            Log.e(TAG, "Error closing socket", closeException)
        }
        return
    }
    onDeviceActionListener.onDeviceConnect(device)
}

My guess is there is something wrong with my UUID. I've tried some other values but still didn't work.

Any help will be much appreciated.

解决方案

Well, I don't see exactly what you are doing wrong here. However, I have done quite a bit of Bluetooth work. More recently just focused in BLE. You should be able to discover your nearby BT devices and see their UUIDs.

I have written a helper class about 3 years ago so it's a little old, but should be mostly the same code. Happy to share it with you if it helps.

public class BluetoothConnector {

private static final String TAG = Globals.SEARCH_STRING + BluetoothConnector.class.getSimpleName();
private static final String DEFAULT_SERVER_NAME_FOR_APP = "tn_bt_default_server";
private static final int DEFAULT_DISCOVERABLE_DURATION_MS = 30000;
private static final UUID DEFAULT_UUID = UUID.fromString("6534c201-039c-4e4f-89f9-5ca8cfeb9667");
public static final int ENABLE_DISCOVER_INTENT = 1002;

protected boolean mIsToastEnabled = false; //Access from calling class to enable toasting of progress to screen if necessary
private Handler mUIHandler;
private static ServerSocketThread mServerSocketThread;
private static ClientSocketThread mClientSocketThread;
private ManageConnectionThread mManageConnectionThread;
private Context mContext;
private IBluetoothDataListener mBluetoothDataListener;
public final Object ServerSocketLock = new Object();
public final Object ClientSocketLock = new Object();
public final Object ManageConnectionLock = new Object();



public BluetoothConnector(Context context, IBluetoothDataListener listener){
    this(context, new Handler(Looper.getMainLooper()), listener);

}
public BluetoothConnector(Context context, Handler UIHandler, IBluetoothDataListener listener){
    Log.v(TAG, "BluetoothConnector(context=" + context + ", Handler=" + UIHandler.getClass().getSimpleName() + ", IBluetoothDataListener=" + listener.getClass().getSimpleName());
    mContext = context;
    mUIHandler = UIHandler;
    mBluetoothDataListener = listener;

}


public void makeThisDeviceDiscoverable(Activity callingActivity){
    makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), DEFAULT_DISCOVERABLE_DURATION_MS);

}
public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter){
    makeThisDeviceDiscoverable(callingActivity, adapter, DEFAULT_DISCOVERABLE_DURATION_MS);

}
public void makeThisDeviceDiscoverable(Activity callingActivity, int durationInMs){
    makeThisDeviceDiscoverable(callingActivity, BluetoothAdapter.getDefaultAdapter(), durationInMs);

}
public void makeThisDeviceDiscoverable(Activity callingActivity, BluetoothAdapter adapter, int durationInMs) {
    Log.v(TAG, "makeThisDeviceDiscoverable(callingActivity=" + callingActivity.getClass().getSimpleName() + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()) + ", duration=" + String.valueOf(durationInMs));
    if(adapter == null){
        Log.v(TAG, "adapter is null");

    }else if(adapter.getScanMode() != BluetoothAdapter.SCAN_MODE_CONNECTABLE_DISCOVERABLE) {
        Log.v(TAG, "Launching Activity to request Discoverable Permission");
        Intent discoverableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
        discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, durationInMs);
        callingActivity.startActivityForResult(discoverableIntent, ENABLE_DISCOVER_INTENT);

    }else{
        Log.v(TAG, "adapter is already in SCAN MODE");

    }

}
public void awaitConnectionFromDevice(){
    awaitConnectionFromDevice(DEFAULT_UUID, BluetoothAdapter.getDefaultAdapter());

}
public void awaitConnectionFromDevice(UUID commonKey){
    awaitConnectionFromDevice(commonKey, BluetoothAdapter.getDefaultAdapter());

}
public void awaitConnectionFromDevice(BluetoothAdapter adapter){
    awaitConnectionFromDevice(DEFAULT_UUID, adapter);

}
public void awaitConnectionFromDevice(UUID commonKey, BluetoothAdapter adapter){
    Log.v(TAG, "awaitConnectionFromDevice for UUID: " + String.valueOf(commonKey) + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
    cancelDiscovery();

    synchronized (ServerSocketLock){
        if(mServerSocketThread != null){
            Log.v(TAG, "Server Socket Thread was not null so canceling current Thread");
            mServerSocketThread.cancel();

        }

        Log.v(TAG, "Attempting to Start new ServerThread");
        mServerSocketThread = new ServerSocketThread(commonKey, adapter);
        mServerSocketThread.start();

    }

}
public void cancelAwaitingConnectionFromDevice(){
    Log.v(TAG, "cancelAwaitingConnectionFromDevice");
    synchronized (ServerSocketLock){
        if(mServerSocketThread != null){
            mServerSocketThread.cancel();
            mServerSocketThread = null;
            Log.v(TAG, "canceling Server Socket Thread");

        }else{
            Log.v(TAG, "Server Socket null, so not canceling");

        }

    }

}

public void startDiscovery() {
    startDiscovery(BluetoothAdapter.getDefaultAdapter());

}
public void startDiscovery(BluetoothAdapter adapter){
    Log.v(TAG, "startDiscovery to find list of devices in range");
    adapter.startDiscovery();

}
public void cancelDiscovery() {
    cancelDiscovery(BluetoothAdapter.getDefaultAdapter());

}
public void cancelDiscovery(BluetoothAdapter adapter){
    Log.v(TAG, "cancelDiscovery");
    adapter.cancelDiscovery();

}
public void connectToDevice(BluetoothDevice device){
    connectToDevice(device, DEFAULT_UUID);

}
public void connectToDevice(BluetoothDevice device, UUID commonKey){
    Log.v(TAG, "connectToDevice(BluetoothDevice=" + (device == null ? "null" : device.getName()) + ", UUID=" + String.valueOf(commonKey));
    synchronized (ClientSocketLock){
        if(mClientSocketThread != null){
            Log.v(TAG, "Client Socket Thread was not null so canceling current Thread");
            mClientSocketThread.cancel();

        }else{
            Log.v(TAG, "Client Socket Thread is NULL so not canceling");

        }

        Log.v(TAG, "ClientSocketThread Starting");
        mClientSocketThread = new ClientSocketThread(device, commonKey);
        mClientSocketThread.start();

    }

}
public BluetoothDevice getBluetoothDeviceByMac(String mac){
    Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac);
    return getBluetoothDeviceByMac(mac, BluetoothAdapter.getDefaultAdapter());

}
public BluetoothDevice getBluetoothDeviceByMac(String mac, BluetoothAdapter adapter) {
    Log.v(TAG, "getBluetoothDeviceByMac(mac=" + mac + ", BluetoothAdapter=" + (adapter == null ? "null" : adapter.getName()));
    return adapter.getRemoteDevice(mac);

}

public ArrayList<KeyValueModel> getPairedDevices(){
    return getPairedDevices(BluetoothAdapter.getDefaultAdapter());
}
public ArrayList<KeyValueModel> getPairedDevices(BluetoothAdapter adapter){
    ArrayList<KeyValueModel> bondedDevices = new ArrayList<KeyValueModel>();

    Set<BluetoothDevice> pairedDevices = adapter.getBondedDevices();
    Log.v(TAG, "getPairedDevices Found " + pairedDevices.size() + " number of paired devices");

    // If there are paired devices
    if (pairedDevices.size() > 0) {
        // Loop through paired devices
        for (BluetoothDevice device : pairedDevices) {
            // Add the name and address to an array adapter to show in a ListView
            bondedDevices.add(new KeyValueModel(device.getAddress(), device.getName()));

        }
    }

    return bondedDevices;
}
public static void unpairDevice(BluetoothDevice device){
    Log.v(TAG, "unpairDevice");
    try{
        Method method = device.getClass().getMethod("removeBond", (Class[]) null);
        method.invoke(device, (Object[]) null);

    }catch (Exception ex){
        Log.e(TAG, "Error Unpairing Device: " + ex.getMessage());

    }
}
public boolean sendDataToConnectedDevice(byte[] data){
    Log.v(TAG, "sendDataToConnectedDevice");
    synchronized (ManageConnectionLock){
        mManageConnectionThread.write(data);
        return true;

    }

}
public void setBluetoothDataListener(IBluetoothDataListener listener){
    mBluetoothDataListener = listener;
}
public boolean getIsConnected(){
    synchronized (ManageConnectionLock) {
        return mManageConnectionThread != null && mManageConnectionThread.isAlive();

    }
}

private void startManageConnectionThread(BluetoothSocket socket){
    Log.v(TAG, "startManageConnectionThread for Socket: " + (socket == null ? "null" : socket.getClass().getSimpleName()));
    synchronized (ManageConnectionLock) {
        mManageConnectionThread = new ManageConnectionThread(socket);
        mManageConnectionThread.start();

    }

}
private void handleDataReceivedFromConnectedDevice(final byte[] bytes){
    Log.v(TAG, "handleDataReceivedFromConnectedDevice");
    Log.v(TAG, "bytes to Listener: " + new String(bytes));

    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if (mBluetoothDataListener != null) {
                    mBluetoothDataListener.onReceivedPayloadFromConnectedDevice(bytes);

                }

            }

        });

    }else{
        Log.v(TAG, "UIHandler was null so skipped sending payload to listener");

    }

}
private void handleConnected(){
    Log.e(TAG, "handleConnected");
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onConnectedToTargetDevice();

                }

            }

        });

    }else{
        Log.v(TAG, "UIHandler was null so skipped sending payload to listener");

    }

}
private void handleDisconnected(){
    Log.e(TAG, "handleDisconnected");
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onDisconnectedFromTargetDevice();

                }
            }
        });

    }else{
        Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");

    }
}
private void handleFailedToConnectAsServer(final Exception ex){
    Log.e(TAG, "handleFailedToConnectAsServer ex:  " + ex.getMessage());
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onFailedToReceiveConnectionFromTargetDevice(ex);

                }
            }
        });

    }else{
        Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");

    }

}
private void handleFailedToConnectAsClient(final Exception ex){
    Log.e(TAG, "handleFailedToConnectAsClient ex:  " + ex.getMessage());
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onFailedToConnectToTargetDevice(ex);

                }
            }
        });

    }else{
        Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");

    }
}
private void handleErrorInRetrievingData(final Exception ex){
    Log.e(TAG, "handleErrorInRetrievingData ex:  " + ex.getMessage());
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onErrorReceivingPayloadFromConnectedDevice(ex);

                }

            }
        });

    }else{
        Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");

    }

}
private void handleFailedToSendDataToConnectedDevice(final Exception ex){
    Log.e(TAG, "handleFailedToSendDataToConnectedDevice ex:  " + ex.getMessage());
    if(mUIHandler != null && mBluetoothDataListener != null){
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                if(mBluetoothDataListener != null){
                    mBluetoothDataListener.onFailedToSendDataToConnectedDevice(ex);

                }

            }
        });

    }else{
        Log.v(TAG, "UIHandler or Listener was null so skipped sending payload to listener");

    }

}
private void toastMessage(final String value){
    if(!mIsToastEnabled || mUIHandler == null) {
        return;
    }

    mUIHandler.post(new Runnable() {
        @Override
        public void run() {
            try{
                Toast.makeText(mContext, value, Toast.LENGTH_SHORT).show();

            }catch(Exception ex){
                Log.v(TAG, "Error Toasting, possibly bad handler, or context: " + ex.getMessage());

            }
        }
    });
}


private class ServerSocketThread extends Thread{

    private final String TAG = Globals.SEARCH_STRING + ServerSocketThread.class.getSimpleName();
    private final BluetoothServerSocket mServerSocket;

    public ServerSocketThread(UUID commonKey, BluetoothAdapter adapter) {
        Log.v(TAG, "ServerSocketThread Constructor");
        BluetoothServerSocket tmp = null;

        try {
            Log.v(TAG, "listening for RFComas Server: " + DEFAULT_SERVER_NAME_FOR_APP + ", and commonKey: " + String.valueOf(commonKey));
            // MY_UUID is the app's UUID string, also used by the client code
            tmp = adapter.listenUsingRfcommWithServiceRecord(DEFAULT_SERVER_NAME_FOR_APP, commonKey);
            toastMessage("Listening for RFComm As Server on UUID: " + String.valueOf(commonKey));

        } catch (IOException e) {
            Log.e(TAG, "Error creating ServerSocket: " + e.getMessage());
            toastMessage("Error Creating ServerSocket: " + e.getMessage());

        }

        mServerSocket = tmp;

    }

    public void run() {
        Log.v(TAG, "ServerSocket run");
        BluetoothSocket socket = null;
        // Keep listening until exception occurs or a socket is returned
        while (mServerSocket != null) {
            try {
                Log.v(TAG, "ServerSocket.accept()");
                toastMessage("ServerSocket.accept()");
                //Waits for Client Connection to pass Socket, then we close down
                socket = mServerSocket.accept();

            } catch (IOException e) {
                Log.e(TAG, "ServerSocket.accept() Error: " + e.getMessage());
                toastMessage("ServerSocket.accept() Error: " + e.getMessage());
                handleFailedToConnectAsServer(e);
                break;

            }

            // If a connection was accepted we don't need to keep server listening, so close unless multiple client/server connections is desired
            if (socket != null) {
                try{
                    Log.v(TAG, "ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
                    toastMessage("ServerSocket Accepted Client Socket, Begin Listening Connect Thread");
                    // Do work to manage the connection (in a separate thread)
                    startManageConnectionThread(socket);
                    //mServerSocket.close();

                }catch(Exception ex){
                    Log.e(TAG, "Exception closing Server Socket");

                }

                //break; //Add in Break if you want to shut down listening for connections
            }else{
                Log.v(TAG, "Socket wasn't accepted");
                toastMessage("Socket wasn't accepted");
                handleFailedToConnectAsServer(new Exception("Socket is Null"));

            }
        }

        Log.v(TAG, "Exiting Server Accept Thread");
    }
    public void cancel() {
        try {
            Log.v(TAG, "ServerSocketThread Canceled");
            mServerSocket.close();

        } catch (IOException e) {
            Log.e(TAG, "ServerSocketThread Error: " + e.getMessage());

        }
    }

}
private class ClientSocketThread extends Thread{

    private BluetoothSocket mSocket;
    private final BluetoothDevice mDevice;

    public ClientSocketThread(BluetoothDevice device, UUID commonKey) {
        Log.v(TAG, "ClientSocketThread Constructor");
        // Use a temporary object that is later assigned to mmSocket,
        // because mmSocket is final
        BluetoothSocket tmp = null;
        mDevice = device;

        // Get a BluetoothSocket to connect with the given BluetoothDevice
        try {
            Log.v(TAG, "Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
            toastMessage("Client creating RFComm Socket to Server with UUID: " + String.valueOf(commonKey));
            // MY_UUID is the app's UUID string, also used by the server code
            tmp = device.createRfcommSocketToServiceRecord(commonKey);

        } catch (IOException e) {
            Log.e(TAG, "Error creating Client Socket: " + e.getMessage());
            toastMessage("Creating Socket Exception: " + e.getMessage());
            handleFailedToConnectAsClient(e);

        }

        mSocket = tmp;

    }

    public void run() {
        try {
            if(mSocket == null){
                Log.e(TAG, "Error Client Socket is Null, Canceling Client Thread");
                return;

            }

            Log.v(TAG, "Client Connecting");
            // Connect to the server, or timeout eventually
            toastMessage("Client Connecting");
            mSocket.connect();

        } catch (IOException connectException) {
            // Unable to connect; close the socket and try the fallback method of reflection with port to connect
            try {
                Log.e("", "trying fallback...");
                toastMessage("Client Connection Failed Exception: " + connectException.getMessage());

                mSocket = (BluetoothSocket) mDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class}).invoke(mDevice, 1);
                toastMessage("Client Connect Again Attempt 2, but with fall back Reflection and port");
                Log.v(TAG, "Client Connect Again Attempt 2, but with fall back Reflection and port");
                mSocket.connect();

                Log.e("", "Connected");
                toastMessage("Client Connected");

            } catch (Exception ex) {
                Log.e("", "Couldn't establish Bluetooth connection!");
                toastMessage("Client Couldn't Establish Connection to Server: " + ex.getMessage());
                handleFailedToConnectAsClient(ex);
                return;

            }
        }

        // Do work to manage the connection (in a separate thread)
        startManageConnectionThread(mSocket);
    }
    public void cancel() {
        try {
            Log.v(TAG, "Client Socket cancel");
            mSocket.close();

        } catch (IOException e) {
            Log.e(TAG, "Error Closing Socket");

        }
    }

}
private class ManageConnectionThread extends Thread {

    /////////////
    // MEMBERS //
    /////////////
    private final String TAG = Globals.SEARCH_STRING + ManageConnectionThread.class.getSimpleName();
    private final BluetoothSocket mSocket;
    private final InputStream mInStream;
    private final OutputStream mOutStream;


    //////////////////
    //  CONSTRUCTOR //
    //////////////////
    public ManageConnectionThread(BluetoothSocket socket) {
        mSocket = socket;

        handleConnected();
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the input and output streams, using temp objects because
        try {
            Log.v(TAG, "ManageConnectionThread Constructor");
            Log.v(TAG, "Connected to Socket = " + String.valueOf(socket.isConnected()));
            toastMessage("Listening for input or output Stream");
            Log.v(TAG, "Get InputStream");
            tmpIn = socket.getInputStream();
            Log.v(TAG, "Get OutputStream");
            tmpOut = socket.getOutputStream();

        } catch (IOException e) {
            Log.e(TAG, "Error getting Socket Streams: " + e.getMessage());
            toastMessage("Connect Thread: Error: " + e.getMessage());
            handleErrorInRetrievingData(e);

        }

        mInStream = tmpIn;
        mOutStream = tmpOut;
    }


    ///////////////
    // OVERRIDES //
    ///////////////
    public void run() {
        // Keep listening to the InputStream until an exception occurs
        while (true) {
            try {
                // Read from the InputStream
                byte[] data = new byte[16384];
                int nRead;
                ByteArrayOutputStream buffer = new ByteArrayOutputStream();

                while ((nRead = mInStream.read(data, 0, data.length)) != -1) {
                    //Log.v(TAG, "bytes Read: " + String.valueOf(nRead));
                    buffer.write(data, 0, nRead);

                    //TODO Find better way to find End Of Message rather than looking for }
                    String temp = new String(buffer.toByteArray());
                    //Log.v(TAG, "current Data: " + temp);
                    if(temp.contains("}")){
                        Log.v(TAG, "bytes reading complete");
                        handleDataReceivedFromConnectedDevice(buffer.toByteArray());
                        buffer.flush();
                        buffer = new ByteArrayOutputStream();

                    }else{
                        Log.v(TAG, "More bytes Available");

                    }

                }

            } catch (IOException e) {
                Log.e(TAG, "Error reading inputStream");
                handleErrorInRetrievingData(e);
                break;

            }

        }

        Log.v(TAG, "Exiting Managed Connection Thread");
        handleDisconnected();

    }


    /////////////
    // METHODS //
    /////////////
    public void write(byte[] bytes) {
        try {
            Log.v(TAG, "ManageConnectionThread write(bytes)");
            mOutStream.write(bytes);

        } catch (IOException e) {
            Log.e(TAG, "Error Writing Stream: " + e.getMessage());
            handleFailedToSendDataToConnectedDevice(e);

        }
    }
    public void cancel() {
        try {
            Log.v(TAG, "ManageConnectionThread cancel");
            handleDisconnected();
            mSocket.close();

        } catch (IOException e) {
            Log.e(TAG, "Error Closing BluetoothSocket: " + e.getMessage());

        }
    }

}


public interface IBluetoothDataListener{

    //////////////////////
    // OVERRIDE METHODS //
    //////////////////////
    void onReceivedPayloadFromConnectedDevice(byte[] payload);
    void onErrorReceivingPayloadFromConnectedDevice(Exception ex);
    void onFailedToConnectToTargetDevice(Exception ex);
    void onFailedToReceiveConnectionFromTargetDevice(Exception ex);
    void onFailedToSendDataToConnectedDevice(Exception ex);
    void onConnectedToTargetDevice();
    void onDisconnectedFromTargetDevice();

}

}

Then of course you will want to make sure you have your broadcast receivers setup:

 <receiver
        android:name=".receivers.BluetoothChangedReceiver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="android.bluetooth.adapter.action.STATE_CHANGED" />
            <action android:name="android.bluetooth.adapter.action.SCAN_MODE_CHANGED" />
            <action android:name="android.bluetooth.adapter.action.DISCOVERY_STARTED" />
            <action android:name="android.bluetooth.adapter.action.DISCOVERY_FINISHED" />
            <action android:name="android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED" />
            <action android:name="android.bluetooth.device.action.FOUND" />
            <action android:name="android.bluetooth.device.action.DISAPPEARED" />
        </intent-filter>
    </receiver>

    <receiver
        android:name=".receivers.BluetoothDeviceReceiver"
        android:enabled="true" >
        <intent-filter>
            <action android:name="android.bluetooth.device.action.FOUND" />
            <action android:name="android.bluetooth.device.action.DISAPPEARED" />
            <action android:name="android.bluetooth.device.action.ACL_CONNECTED" />
            <action android:name="android.bluetooth.device.action.ACL_DISCONNECTED" />
            <action android:name="android.bluetooth.device.action.ACTION_ACL_DISCONNECT_REQUESTED" />
            <action android:name="android.bluetooth.device.action.BOND_STATE_CHANGED" />
            <action android:name="android.bluetooth.device.action.UUID" />
        </intent-filter>
    </receiver>

这篇关于BluetoothSocket 未连接到目标设备的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 19:52