蓝牙,是一种支持设备短距离通信(一般10m内,且无阻隔媒介)的无线电技术。能在包括移动电话、PDA、无线耳机、笔记本电脑等众多设备之间进行无线信息交换。利用"蓝牙"技术,能够有效地简化移动通信终端设备之间的通信,也能够成功地简化设备与Internet之间的通信,这样数据传输变得更加迅速高效,为无线通信拓宽道路。
几个术语
在Android手机平台中,只到Android 2.0才引入蓝牙接口。在开发时,需要真机测试,如果需要数据传输,还需要两台机器,另外蓝牙需要硬件支持,但一般的智能手机上都会有这方面的支持,特别是Android系统的手机。
正式开发Android 蓝牙时,需要在Android项目中的AndroidManifest.xml中添加对应权限:
1. <uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
2. <uses-permissionandroid:name="android.permission.BLUETOOTH"/>
以下介绍android.bluetooth.*中的重要类的作用,如表10-7所示。
表10-7 android.bluetooth.*中的重要类的作用
类 名 | 作 用 |
BluetoothAdapter | 本地蓝牙设备的适配类,所有的蓝牙 操作都要通过该类完成 |
BluetoothClass | 用于描述远端设备的类型,特点等信息 |
BluetoothDevice | 蓝牙设备类,代表了蓝牙通讯过程中的远端设备 |
BluetoothServerSocket | 蓝牙服务器端,类似SlerverSocket |
BluetoothSocket | 蓝牙设备客户端,类似Socket |
BluetoothClass.Device | 蓝牙关于设备信息 |
BluetoothClass.Device.Major | 蓝牙设备管理 |
BluetoothClass.Service | 蓝牙相关服务 |
其中BluetoothAdapter是一个非常重要的适配类,它包含打开蓝牙、关闭蓝牙、蓝牙状态、搜索蓝牙等重要方法,如表10-8所示。
表10-8 BluetoothAdapter适配类包含的方法
方 法 | 作 用 |
getDefaultAdapter | 得到默认蓝牙适配器 |
getRemoteDevice | 得到指定蓝牙的BluetoothDevice |
isEnabled | 蓝牙是否开启 |
getState | 得到蓝牙状态 |
enable | 打开蓝牙 |
Disable | 关闭蓝牙 |
getAddress | 得到蓝牙适配器地址 |
getName | 得到蓝牙的名字 |
setName | 设置蓝牙的名字 |
getScanMode | 得到当前蓝牙的扫描模式 |
setScanMode | 设置当前蓝牙的设置模式 |
startDiscovery | 开始搜索蓝牙设备 |
cancelDiscovery | 取消搜索蓝牙设备 |
isDiscovering | 是否允许被搜索 |
getBondedDevices | 得到BluetoothDevice集合到本地适配器 |
listenUsingRfcommWithServiceRecord | 创建一个监听,安全记录蓝牙 RFCOMM蓝牙套接字 |
checkBluetoothAddress | 检查蓝牙地址是否正确 |
Android操作蓝牙不是很困难,主要就是打开蓝牙、关闭蓝牙、搜索蓝牙、蓝牙客户端、蓝牙服务器等。蓝牙客户端、服务器和Socket基础中讲解的差不多,但蓝牙中是用BluetoothSocket和BluetoothServerSocket两个类来操作。
关于Android在操作蓝牙过程中的几个要点和操作方式如下。
1.打开蓝牙的方式有两种
1. (1)Intent enabler= newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
2. startActivityForResult(enabler, REQUEST_ENABLE);
3. (2)BluetoothAdapter _bluetooth= BluetoothAdapter.getDefaultAdapter();
4. _bluetooth.enable();
第一种方式Android系统会弹出一个提示框,提示用户是否开启蓝牙设备。第二种方式不会提示,会直接打开蓝牙设备,在运用当中视情况而定,有些情况需要友好提示,有些情况则可直接打开使用。
2.使设备能够被搜索
基于安全性考虑,设置开启可被搜索后,Android系统就会默认给出120秒的时间,其他远程设备在这120秒内可以搜索到它:
1. Intent enabler= newIntent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
2. startActivityForResult(enabler, REQUEST_DISCOVERABLE);
3.搜索蓝牙设备
1. BluetoothAdapter _bluetooth= BluetoothAdapter.getDefaultAdapter()
2. _bluetooth.startDiscovery();
4.关闭蓝牙设备
1. BluetoothAdapter _bluetooth= BluetoothAdapter.getDefaultAdapter();
2. _bluetooth.disable ();
5.创建蓝牙客户端
1. BluetoothSocket socket= device.
createRfcommSocketToServiceRecord(UUID.fromString(UUID号)); 2. socket.connect();
6.创建蓝牙服务器
1. BluetoothServerSocket _serverSocket=_bluetooth.
listenUsingRfcommWithServiceRecord(服务器名称, UUID.fromString(UUID号)); 2. BluetoothSocket socket= _serverSocket.accept();
3. InputStream inputStream= socket.getInputStream();
看到_serverSocket.accept()大家想到前面Socket章节所讲到的ServerSocket也有这个方法,原理上它们其实是一样的,都是阻塞等待客户端的数据,如果客户端没有数据过来,它将一直阻塞在此处。
在上述几个重要步骤方法中,最重要的是蓝牙客户端和服务器,这两个操作是在商业应用中和日常使用中最频繁的,例如,利用蓝牙传递数据、游戏、聊天等。目前市场上出现很多关于利用蓝牙技术做的聊天工具和传输数据文件的应用,它们都是采用BluetoothSocket和BluetoothServerSocket技术。
另外还有一点注意,蓝牙和WiFi都是比较耗电的功能模块,所以,在不使用蓝牙的情况下,建议关闭它。
蓝牙的基本操作和代码实现
代码部分就实现打开蓝牙、关闭蓝牙、搜索蓝牙、允许搜索。目前唯一比较复杂的地方就是如何建立蓝牙客户端和蓝牙服务器。
下面看看代码是如何实现蓝牙服务器和蓝牙客户端的,代码如下,代码来源EX_10_05:
服务器端:
1. ………………………………省略部分代码…………………………..
2. setTitle("蓝牙服务端");
3. // 声明变量
4. BluetoothAdapter bluetooth= null;//本地蓝牙设备
5. BluetoothServerSocket serverSocket= null;// 蓝牙设备Socket服务端
6. BluetoothSocket socket= null;// 蓝牙设备Socket客户端
7. OutputStream os= null;// 蓝牙输出流
8. InputStream is= null;// 蓝牙输入流
9. try {
10. // 1.得到本地设备
11. bluetooth= BluetoothAdapter.getDefaultAdapter();
12. // 2.创建蓝牙Socket服务器
13. serverSocket= bluetooth.
listenUsingRfcommWithServiceRecord("btspp",
UUID.fromString("00000000-2527-eef3-ffff-ffffe3160865")); 14. // 3.阻塞等待Socket客户端请求
15. socket= serverSocket.accept();
16. if (socket != null) {
17. // 4.处理输出流
18. os= socket.getOutputStream();
19. os.write("我是服务器!".getBytes());
20. if (os != null) {
21. os.flush();
22. os.close();
23. }
24. // 5.处理输入流
25. is= socket.getInputStream();
26. byte[] bytes= newbyte[is.available()];
27. is.read(bytes);
28. System.out.println("服务器端读取客户端传输的数据时:" + new String(bytes));
29. if (is != null)
30. is.close();
31. if (socket != null)
32. socket.close();
33. if (serverSocket != null)
34. serverSocket.close();
35. }
36. } catch (Exception e) {
37. e.printStackTrace();
38. }
客户端:
1. ………………………………省略部分代码…………………………..
2. setTitle("蓝牙客户端");
3. //声明变量
4. BluetoothAdapter bluetooth= null;//本地蓝牙设备
5. BluetoothDevice device= null;//远程蓝牙设备
6. BluetoothSocket socket= null;//蓝牙Socket客户端
7. OutputStream os= null;//输出流
8. InputStream is= null;//输入流
9. try {
10. //1.得到本地蓝牙设备的默认适配器
11. bluetooth= BluetoothAdapter.getDefaultAdapter();
12. //2.通过本地蓝牙设备得到远程蓝牙设备
13. device= bluetooth.getRemoteDevice("A0:75:91:E0:88:D3");
14. //3.根据UUID 创建并返回一个BluetoothSocket
15. socket= device.createRfcommSocketToServiceRecord(UUID
16. .fromString("00000000-2527-eef3-ffff-ffffe3160865"));
17. if (socket != null) {
18. // 连接
19. socket.connect();
20. //4处理客户端输出流
21. os= socket.getOutputStream();
22. os.write("我是客户端!".getBytes());
23. os.flush();
24. os.close();
25. //5处理客户端输入流
26. is= socket.getInputStream();
27. byte[] b= newbyte[is.available()];
28. is.read(b);
29. System.out.println("客户端接收到服务器传输的数据::" + new String(b));
30. is.close();
31. socket.close();
32. }
33. } catch (Exception e) {
34. e.printStackTrace();
35. }
代码解释:
测试代码时,需要手动打开蓝牙并自行配置好蓝牙客户端和服务器,也就是蓝牙配对。代码中注意服务器端和客户端的UUID:00000000-2527-eef3-ffff-ffffe3160865,两个地方一定要一样,另外客户端代码中的bluetooth.getRemoteDevice("A0:75:91:E0:88:D3")是通过服务器端的地址获取远程蓝牙服务器。
从代码角度看其实都很简单,读者要多练并且多灵活运用。如果前期读者对Socket的学习过关的话,学习蓝牙Socket编程是非常轻松的。由于BluetoothSocket支持OutputStream和InputStream,所以,可以利用它们相互传输任何数据。