android 传统蓝牙开发 (附示例源码)
前:本文为QiaoJim原创,转载请附原文链接,谢谢合作!
http://blog.csdn.net/qiao_jim/article/details/73008695
----------------------------------------------------------------------------------
最近学习了android传统蓝牙,自己整理了一下思路,然后写了一个BluetoothStudy小测试程序,来运用所理解的android传统蓝牙开发技术,写下
一些心得和思路,供其他android热爱者参考,也方便日后回顾。
博客如有错误之处,欢迎留言之处,十分感谢。博客最后会附上源码,可下载借鉴。
一、整体思路和对应相关方法
1、获得BluetoothAdapter:BluetoothAdapter.getDefaultAdapter();
2、打开蓝牙:询问用户打开(推荐)或直接bluetoothAdapter.enable();
3、查询已绑定设备,发现新设备:bluetoothAdapter.getBondedDevices();bluetoothAdapter.startDiscovery();
4.1、服务端,一直监听请求,当该端主动发出请求时,关闭该端的监听,角色转为客户端:
bluetoothDevice.createRfcommSocketToServiceRecord(UUID);
4.2、客户端,点击目标设备,配对连接:
bluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, UUID);
5、通过BluetoothSocket通信:IO流读写
二、开发详解
1、声明权限,注意可能需要的运行时权限
android 6.0以上设备发现新蓝牙时,需加入运行时权限,否则无法监听ACTION_FOUND广播
if (Build.VERSION.SDK_INT >= 6.0) { ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, Params.MY_PERMISSION_REQUEST_CONSTANT); } public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case Params.MY_PERMISSION_REQUEST_CONSTANT: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // 运行时权限已授权 } return; } } }
2、打开蓝牙,推荐用对话框形式让用户打开
bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); // 蓝牙未打开,询问打开 if (!bluetoothAdapter.isEnabled()) { Intent turnOnBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); startActivityForResult(turnOnBtIntent, Params.REQUEST_ENABLE_BT); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case Params.REQUEST_ENABLE_BT: { //用户打开蓝牙 if (resultCode == RESULT_OK) { //显示已绑定蓝牙设备 showBondDevice(); } break; } case Params.REQUEST_ENABLE_VISIBILITY: { //设置该蓝牙设备可被其他设备发现,600是设置的设备可发现时间(博客最后有简单说明) if (resultCode == 600) { toast("蓝牙已设置可见"); } else if (resultCode == RESULT_CANCELED) { toast("蓝牙设置可见失败,请重试"); } break; } } }
private void showBondDevice() { deviceList.clear(); // 所有已绑定设备,一个Set集合 Set tmp = bluetoothAdapter.getBondedDevices(); for (BluetoothDevice d : tmp) { deviceList.add(d); } //更新列表 listAdapter.notifyDataSetChanged(); }
4、发现蓝牙设备,发现一个设备,会发送一条ACTION_FOUND广播,注册广播接收器,可获得对应蓝牙设备信息
bluetoothAdapter.startDiscovery(); intentFilter = new IntentFilter(); btReceiver = new MyBtReceiver(); //监听 搜索开始,搜索结束,发现新设备 3条广播 intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED); intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); intentFilter.addAction(BluetoothDevice.ACTION_FOUND); getActivity().registerReceiver(btReceiver, intentFilter);
//广播接收器 private class MyBtReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (BluetoothAdapter.ACTION_DISCOVERY_STARTED.equals(action)) { toast("开始搜索 ..."); } else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)) { toast("搜索结束"); } else if (BluetoothDevice.ACTION_FOUND.equals(action)) { //获得发现的设备 BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); if (device.getBondState() != BluetoothDevice.BOND_BONDED) { deviceList.add(device); listAdapter.notifyDataSetChanged(); } } } }
5、设备连接,服务器端开启线程一直等待连接,客户端点击某个目标设备,关闭服务器线程监听,并开启线程,发出连接请求。
注意:客户端连接前,一定cancelDiscovery()
// 蓝牙已开启 if (bluetoothAdapter.isEnabled()) { showBondDevice(); // 默认开启服务线程监听 if (serverThread != null) { serverThread.cancel(); } serverThread = new ServerThread(bluetoothAdapter, uiHandler); new Thread(serverThread).start(); } listView.setOnItemClickListener(new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { // 关闭服务器监听 if (serverThread != null) { serverThread.cancel(); serverThread=null; } BluetoothDevice device = deviceList.get(position); // 开启客户端线程,连接点击的远程设备 clientThread = new ClientThread(bluetoothAdapter, device, uiHandler); new Thread(clientThread).start(); // 通知 ui 连接的服务器端设备 Message message = new Message(); message.what = Params.MSG_CONNECT_TO_SERVER; message.obj = device; uiHandler.sendMessage(message); } });
6、建立BluetoothSocket连接以后,使用IO流数据传输,服务器和客户端读写数据类似,贴一部分代码供参考
public void writeData(String dataSend) { if (serverThread != null) { serverThread.write(dataSend); } else if (clientThread != null) { clientThread.write(dataSend); } }
//写数据 public void write(String data){ try { out.write(data.getBytes("utf-8")); } catch (IOException e) { e.printStackTrace(); } }
new Thread(new Runnable() { @Override public void run() { byte[] buffer = new byte[1024]; int len; String content; try { //读数据 while ((len=in.read(buffer)) != -1) { content=new String(buffer, 0, len); Message message = new Message(); message.what = Params.MSG_CLIENT_REV_NEW; message.obj = content; //更新 ui uiHandler.sendMessage(message); } } catch (IOException e) { e.printStackTrace(); } } }).start();
(1)新设备绑定,bluetoothDevice.createBond()
(2)设置设备可被发现的时间:
Intent enableIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE); enableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 600); startActivityForResult(enableIntent, Params.REQUEST_ENABLE_VISIBILITY);
(3)服务器获得远端设备,bluetoothSocket.getRemoteDevice()
(4)通过MAC获得蓝牙设备,bluetoothAdapter.getRemoteDevice(String address)
(5)关闭蓝牙,bluetoothAdapter.disable()
三、源码示例下载
附上源码github地址,有帮助的话别忘了加 ★ 噢。
https://github.com/QiaoJim/BluetoothStudy
感谢阅读,如有错误,请留言。如果觉得博文不错,请点赞支持。
四、效果图
更多相关文章
- Android ----蓝牙架构
- Android 设置默认桌面,默认应用,辅助功能,电池优化,设备管理器,
- Ubuntu下使用adb和USB连接的方式进行android设备调试
- 【阿里聚安全·安全周刊】500万台Android设备受感染|YouTube封杀
- android如何打开系统wifi、蓝牙等设置界面
- Android USB Gadget复合设备驱动(打印机)测试方法
- Android蓝牙开发
- 使用User Agent分辨出Android设备类型的安全做法