添加权限:
<uses-permission Android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
- 客户端
开启蓝牙:
void openBT(){ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); if (mBluetoothAdapter!= null){ if (!mBluetoothAdapter.isEnabled()){ mBluetoothAdapter.enable(); } } }
搜索蓝牙:
@OnClick(R.id.btSearch) public void startSearch(View view){ if(mBluetoothAdapter!= null &&mBluetoothAdapter.isEnabled()){ if (!mBluetoothAdapter.isDiscovering()){ mBluetoothAdapter.startDiscovery(); } } }
开启搜索是异步操作,发现设备后会发送广播,所以要定义广播接收者
在接收到广播后,获取广播里的蓝牙数据
private class BTBroadCastRev extends BroadcastReceiver{ @Override public void onReceive(Context context,Intent intent) { String strAction = intent.getAction(); if (strAction.equals(BluetoothDevice.ACTION_FOUND)){ BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); mArrDevice.add(device); mAdapter.notifyDataSetChanged(); }else if(strAction.equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)){ Log.d("qfonReceive","搜索完成"); } } }
//注册广播接收者
myReceive = new BTBroadCastRev(); IntentFilter ifFind = new IntentFilter(BluetoothDevice.ACTION_FOUND); this.registerReceiver(myReceive,ifFind); IntentFilter ifFinishFind = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); this.registerReceiver(myReceive,ifFinishFind);
连接蓝牙,并开启发送数据线程:
/** * 点击item,连接对应的蓝牙设备 */ protected void connectBT() { mLvDevice.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent,View view, int position, longid) { MyClientTask task = newMyClientTask(); task.execute(mArrDevice.get(position)); } }); } class MyClientTask extends AsyncTask<BluetoothDevice,Void,Void>{ @Override protected void doInBackground(BluetoothDevice... devices) { BluetoothDevice device = devices[0]; try { //使用安全连接,服务端也要一样使用安全连接,UUID也要跟服务器的监听UUID一致 BluetoothSocket socket = device.createRfcommSocketToServiceRecord(MY_UUID_SECURE); socket.connect(); Log.d("qfdoInBackground_client","连接成功,开始发送数据"); byte[] btMsg =new String("Hello").getBytes(); socket.getOutputStream().write(btMsg,0,btMsg.length); } catch(Exception e) { e.printStackTrace(); } return null; } }
uuid可以通过uuidgen生成,生成结果类似以下结构:
5D3D5E52-338A-47B8-9F10-27ADF89E204E
- 服务端
开启蓝牙,跟客户端一样启动服务线程
new RevTask().execute(); class RevTask extends AsyncTask<Void,Void,String>{ @Override protected void onPostExecute(String s) { super.onPostExecute(s); tvMsg.setText(s); } @Override protected String doInBackground(Void... params) { try { Log.d("qfdoInBackground","开始监听"); //要跟客户端uuid一致 BluetoothServerSocket sevSocket =mBluetoothAdapter.listenUsingRfcommWithServiceRecord("blue_service",MY_UUID_SECURE); BluetoothSocket socket = sevSocket.accept(); if(socket != null){ Log.d("qfdoInBackground","连接成功"); InputStream stream = socket.getInputStream(); byte[] btRead =new byte[1024]; int iLength = stream.read(btRead); Log.d("qfdoInBackground","读取数据成功"+iLength); String strMsg =new String(btRead,"utf-8"); Log.d("qfdoInBackground",strMsg); return strMsg; }else{ Log.d("qfdoInBackground","失败"); } } catch (IOException e) { e.printStackTrace(); Log.d("qfdoInBackground","异常"); } return null; } }
上述代码没有实现配对,对应经典蓝牙通信,最好先进行配对再连接,已经配对的蓝牙设备可以直接通过adapter获取到
//得到所有已经配对的蓝牙适配器对象
Set<BluetoothDevice> devices = adapter.getBondedDevices();
没有配对的蓝牙设备,可以在扫描设备的广播通知中判断,点击设备连接时,判断是否已经配对,如果已经配对,直接连接,如果没有配对,先配对:
if (btDev.getBondState() == BluetoothDevice.BOND_NONE) { //利用反射方法调用BluetoothDevice.createBond(BluetoothDevice remoteDevice); Method createBondMethod = BluetoothDevice.class.getMethod("createBond"); Log.d("BlueToothTestActivity", "开始配对"); returnValue = (Boolean) createBondMethod.invoke(btDev); }else if(btDev.getBondState() == BluetoothDevice.BOND_BONDED){ connect(btDev); }
配对结果也会通过广播传递结果信息:
// 注册Receiver来获取蓝牙设备相关的结果 IntentFilter intent = new IntentFilter(); intent.addAction(BluetoothDevice.ACTION_FOUND);// 用BroadcastReceiver来取得搜索结果 intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED); intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED); intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); registerReceiver(searchDevices, intent);
if(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)){ device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); switch (device.getBondState()) { case BluetoothDevice.BOND_BONDING: Log.d("BlueToothTestActivity", "正在配对......"); break; case BluetoothDevice.BOND_BONDED: Log.d("BlueToothTestActivity", "完成配对"); connect(device);//连接设备 break; case BluetoothDevice.BOND_NONE: Log.d("BlueToothTestActivity", "取消配对"); default: break; }