浅谈android蓝牙连接和兼容性问题

最近工作上接手公司APP的开发工作,蓝牙模块兼容性比较差,需要修改,自己就研究了下android蓝牙连接的问题,这里分享给大家。后面有一个蓝牙模块的demo。

蓝牙连接主要的流程如下

1,先注册一个监测蓝牙的监听器,一般来说这个蓝牙监听器注册在Activity的resume方法中,在onstop方法中注销。

private void initReceiver(){
		mBluetooth = BluetoothAdapter.getDefaultAdapter();
		
		IntentFilter filter = new IntentFilter();
		filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
		filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
		filter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
		filter.addAction(BluetoothDevice.ACTION_FOUND);
		registerReceiver(bluetoothReceiver, filter);
	}



2,在蓝牙监听器中监测到BluetoothDevice.ACTION_FOUND这个action时监测是不是自己要找的设备,如果是就连接

private BroadcastReceiver bluetoothReceiver = new BroadcastReceiver(){
		

		@Override
		public void onReceive(Context context, Intent intent) {
			
			String action = intent.getAction(); 
			
			if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
				Log.e(TAG, "ACTION_STATE_CHANGED: " + mBluetooth.getState());
				
				if (mBluetooth.getState() == BluetoothAdapter.STATE_ON) {
					mBluetooth.startDiscovery();
				}
				return;
			}
			
			if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_STARTED)) {
				Log.e(TAG, "ACTION_DISCOVERY_STARTED");
				
				
			}else if (action.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
				
				
				
				
			}else if (action.equals(BluetoothDevice.ACTION_FOUND)) {
				
				BluetoothDevice foundDevice = (BluetoothDevice)intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
				
				Log.i(TAG, "find device: " + foundDevice.getName()+" | " + foundDevice.getAddress());
				
				if (checkBlueDevice(foundDevice)) {//UCbooster检测
					mDevice = foundDevice;
					isFound = true;
					cancelDiscovery();
					new BtConnection().start();
					return;
				}
				//filter
				/*if (bondedDevices.contains(mDevice)) {
					return;
				}*/
				cancelDiscovery();
				
			}
		}
	};



3,具体的连接



androidAPI中的BluetoothDevice类里面有五个建立蓝牙连接的方法,具体如下:

public BluetoothSocket createRfcommSocketToServiceRecord(UUID uuid) throws IOException {
        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, -1,
                new ParcelUuid(uuid));
    }


public BluetoothSocket createInsecureRfcommSocketToServiceRecord(UUID uuid) throws IOException {
        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, -1,
                new ParcelUuid(uuid));
    }

public BluetoothSocket createRfcommSocket(int channel) throws IOException {
        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, true, true, this, channel,
                null);
    }


public BluetoothSocket createInsecureRfcommSocket(int port) throws IOException {
        return new BluetoothSocket(BluetoothSocket.TYPE_RFCOMM, -1, false, false, this, port,
                null);
    }


public BluetoothSocket createScoSocket() throws IOException {
        return new BluetoothSocket(BluetoothSocket.TYPE_SCO, -1, true, true, this, -1, null);
    }

后面三个方法都是隐藏的方法,需要使用java的反射机制调用。

先说说前面的两个方法,前面两个方法是通过UUID建立连接,UUID是android中连接其他android设备的方法,不同的UUID对应着android设备中不同的资源,如音频,视频等(这儿的说法可能有错误,读者最好自己查证下,我有点记不清了),其实UUID也可以用于android设备连接非android设备(我们公司的产品就是这样做的),连接的UUID是固定的一个UUID,这个在谷歌开发文档中有说道,是这个"00001101-0000-1000-8000-00805F9B34FB"

后面三个方法是隐藏的方法,这个无法直接引用(不知道谷歌为什么不放出来,可能是从安全角度考虑),第三个和第四个方法比较强大,可以不需要配对就可以连接,第五个方法是建立一个同步的连接,这个是只要传视频音频才可能用到。

第三个方法方法的使用方法如下

先写getMethod用于获取指定类的方法

private static Method getMethod(Class cls, String name, Class[] args) {
		try {
			return cls.getMethod(name, args);
		} catch (Exception ex) {
			return null;
		}
	}

然后获取BluetoothDevice类中的createInsecureRfcommSocket方法

private static final Method _createInsecureRfcommSocket = getMethod(BluetoothDevice.class, "createInsecureRfcommSocket", new Class[] { int.class });

这个Method使用如下

_createInsecureRfcommSocket.invoke(mDevice, channel);

一般channel值传1。mDevice是获得的BluetoothDevice对象

这个用反射获得的方法连接蓝牙兼容性比较差,我的华为手机就不能用这种方法,所以这个方法一般要和使用UUID连接的方法一起使用。

private boolean setupConnection() {
			//mSocket = createRfcommSocket(1);
			
			try {
				mSocket = createInsecureRfcommSocket(1);
				mSocket.connect();
				mInputStream = mSocket.getInputStream();
				mOutputStream = mSocket.getOutputStream();
				flag = 1;
				return true;
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			if(flag != 1){
		    UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"); 
		    
			try {   
	        // 连接建立之前的先配对   
	        if (mDevice.getBondState() == BluetoothDevice.BOND_NONE) {   
	        	//先尝试反射机制连接
	            Method creMethod = BluetoothDevice.class   
	                    .getMethod("createBond");   
	            Log.e("TAG", "开始配对");   
	            creMethod.invoke(mDevice);   
	        } else {   
	        }   
	    } catch (Exception e) {   
	        // TODO: handle exception   
	        //DisplayMessage("无法配对!");   
	        e.printStackTrace();   
	    }  

		    try {
				mSocket = mDevice.createRfcommSocketToServiceRecord(uuid);
				mSocket.connect();
				mInputStream = mSocket.getInputStream();
				mOutputStream = mSocket.getOutputStream();
				return true;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			}
			return false;
		}


蓝牙连接哟呵使用新线程,如果你有些操作必须要在连接之后才能完成那你就要注意线程阻塞的问题了。

demo里是一个是文章中代码的整合,实测可用,里面是连接我们公司的产品,你要连接需要重写里面的checkBlueDevice方法,检查你自己的蓝牙设备。

地址http://download.csdn.net/detail/tingfengzheshuo/8635031



你可能感兴趣的:(android)