一、蓝牙介绍
Android蓝牙协议栈使用的是BlueZ,支持GAP, SDP, and RFCOMM规范,是一个SIG认证的蓝牙协议栈。
Bluez 是GPL许可的,因此Android的框架内与用户空间的bluez代码通过D-BUS进程通讯进行交互,以避免专有代码。
Headset和Handsfree(v1.5)规范就在Android框架中实现的,它是跟Phone App紧密耦合的。这些规范也是SIG认证的。
Android蓝牙库结构图:
Android蓝牙进程结构图:
Android蓝牙通信结构图
Android从2.0开始,正式支持蓝牙,在此之前只能通过第三方API完成关于蓝牙的应用程序设计。另外,模拟器不支持蓝牙,只能用真机进行相关测试,当然也可以用电脑与真机配合进行测试,电脑端程序借助bluecove提供的jar包可以完成。
二、应用蓝牙完成的工作
1、扫描其他Bluetooth设备。
2、查询配对Bluetooth设备的本地Bluetooth适配器。
3、建立RFCOMM通道。
4、通过服务探索连接到其他设备。
5、与其他设备进行数据传输。
6、管理多个连接。
三、常用蓝牙API简介
四、蓝牙权限
五、蓝牙建立流程
1.使用registerReceiver注册BroadcastReceiver来获取蓝牙状态、搜索设备等消息。
2.使用BlueAdatper的搜索。
3.在BroadcastReceiver的onReceive()里取得搜索所得的蓝牙设备信息(如名称,MAC,RSSI)。
4.通过设备的MAC地址来建立一个BluetoothDevice对象。
5.由BluetoothDevice衍生出BluetoothSocket,准备SOCKET来读写设备。
6.通过BluetoothSocket的createRfcommSocketToServiceRecord()方法来选择连接的协议/服务,这里用的是SPP(UUID:00001101-0000-1000-8000-00805F9B34FB)。
7.Connect之后(如果还没配对则系统自动提示),使用BluetoothSocket的getInputStream()和getOutputStream()来读写蓝牙设备。
六、Broadcast使用Action介绍
公用Action
七、蓝牙例程分析
XML布局代码
实现关键代码
八、关于UUID的介绍
简介
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。
作用
UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。目前最广泛应用的 UUID,即是微软的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的应用,则有 Linux ext2/ext3 档案系统、LUKS 加密分割区、GNOME、KDE、Mac OS X 等等。
组成
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字
UUID由以下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
#Android蓝牙串口服务UUID
SerialPortServiceClass_UUID = ‘{00001101-0000-1000-8000-00805F9B34FB}’
附上例程代码:
TestBluetooth.zip
Android蓝牙协议栈使用的是BlueZ,支持GAP, SDP, and RFCOMM规范,是一个SIG认证的蓝牙协议栈。
Bluez 是GPL许可的,因此Android的框架内与用户空间的bluez代码通过D-BUS进程通讯进行交互,以避免专有代码。
Headset和Handsfree(v1.5)规范就在Android框架中实现的,它是跟Phone App紧密耦合的。这些规范也是SIG认证的。
Android蓝牙库结构图:
Android蓝牙进程结构图:
Android蓝牙通信结构图
Android从2.0开始,正式支持蓝牙,在此之前只能通过第三方API完成关于蓝牙的应用程序设计。另外,模拟器不支持蓝牙,只能用真机进行相关测试,当然也可以用电脑与真机配合进行测试,电脑端程序借助bluecove提供的jar包可以完成。
二、应用蓝牙完成的工作
1、扫描其他Bluetooth设备。
2、查询配对Bluetooth设备的本地Bluetooth适配器。
3、建立RFCOMM通道。
4、通过服务探索连接到其他设备。
5、与其他设备进行数据传输。
6、管理多个连接。
三、常用蓝牙API简介
四、蓝牙权限
01
02
|
<
uses-permission
android:name
=
"android.permission.BLUETOOTH_ADMIN"
/>
<
uses-permission
android:name
=
"android.permission.BLUETOOTH"
/>
|
五、蓝牙建立流程
1.使用registerReceiver注册BroadcastReceiver来获取蓝牙状态、搜索设备等消息。
2.使用BlueAdatper的搜索。
3.在BroadcastReceiver的onReceive()里取得搜索所得的蓝牙设备信息(如名称,MAC,RSSI)。
4.通过设备的MAC地址来建立一个BluetoothDevice对象。
5.由BluetoothDevice衍生出BluetoothSocket,准备SOCKET来读写设备。
6.通过BluetoothSocket的createRfcommSocketToServiceRecord()方法来选择连接的协议/服务,这里用的是SPP(UUID:00001101-0000-1000-8000-00805F9B34FB)。
7.Connect之后(如果还没配对则系统自动提示),使用BluetoothSocket的getInputStream()和getOutputStream()来读写蓝牙设备。
六、Broadcast使用Action介绍
公用Action
七、蓝牙例程分析
XML布局代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
<
LinearLayout
xmlns:android
=
"http://schemas.android.com/apk/res/android"
xmlns:tools
=
"http://schemas.android.com/tools"
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:orientation
=
"horizontal"
>
<
LinearLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:layout_weight
=
"1"
android:orientation
=
"vertical"
>
<
ListView
android:id
=
"@+id/deviceList"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
>
</
ListView
>
</
LinearLayout
>
<
LinearLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"fill_parent"
android:layout_weight
=
"2"
android:orientation
=
"vertical"
>
<
LinearLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"horizontal"
>
<
TextView
android:id
=
"@+id/stateTxt"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:text
=
"@string/state_text"
android:focusable
=
"true"
/>
<
ToggleButton
android:id
=
"@+id/stateTBtn"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:textOn
=
"@string/open"
android:textOff
=
"@string/close"
android:clickable
=
"false"
/>
</
LinearLayout
>
<
Button
android:id
=
"@+id/openBtn"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:gravity
=
"center"
android:text
=
"@string/open_text"
/>
<
Button
android:id
=
"@+id/closeBtn"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:gravity
=
"center"
android:text
=
"@string/close_text"
/>
<
Button
android:id
=
"@+id/discoverBtn"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:gravity
=
"center"
android:text
=
"@string/discover_text"
/>
<
LinearLayout
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:orientation
=
"horizontal"
>
<
EditText
android:id
=
"@+id/sendedtTxt"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:gravity
=
"center"
android:singleLine
=
"true"
android:hint
=
"@string/message"
android:textSize
=
"12sp"
/>
<
Button
android:id
=
"@+id/sendBtn"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
android:layout_weight
=
"1"
android:gravity
=
"center"
android:text
=
"@string/send_text"
android:textSize
=
"12sp"
/>
</
LinearLayout
>
<
ListView
android:id
=
"@+id/chatList"
android:layout_width
=
"fill_parent"
android:layout_height
=
"wrap_content"
>
</
ListView
>
</
LinearLayout
>
</
LinearLayout
>
|
实现关键代码
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
//客户端线程,连接蓝牙设备
private
class
clientThread
extends
Thread {
public
void
run() {
try
{
//创建一个Socket连接:只需要服务器在注册时的UUID号
device=local.getRemoteDevice(BlueToothAddress);
socket = device.createRfcommSocketToServiceRecord(UUID.fromString(
"00001101-0000-1000-8000-00805F9B34FB"
));
Message msg2 =
new
Message();
msg2.obj =
"请稍候,正在连接服务器:"
+BlueToothAddress;
msg2.what =
0
;
LinkDetectedHandler.sendMessage(msg2);
System.out.println(socket+
"|mac:"
+BlueToothAddress);
socket.connect();
Message msg =
new
Message();
msg.obj =
"已经连接上服务端!可以发送信息。"
;
msg.what =
0
;
LinkDetectedHandler.sendMessage(msg);
//启动接受数据
mreadThread =
new
readThread();
mreadThread.start();
}
catch
(IOException e)
{
System.out.println(
"异常"
);
Message msg =
new
Message();
msg.obj =
"连接服务端异常!断开连接重新试一试。"
;
msg.what =
0
;
LinkDetectedHandler.sendMessage(msg);
}
}
};
private
final
BroadcastReceiver mReceiver =
new
BroadcastReceiver() {
@Override
public
void
onReceive(Context context, Intent intent) {
String action = intent.getAction();
//处理已发现设备
if
(BluetoothDevice.ACTION_FOUND.equals(action)) {
//获取发现的设备对象
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//跳过已配对的设备
if
(device.getBondState() != BluetoothDevice.BOND_BONDED) {
delist.add(
new
SiriListItem(device.getName() +
"undefined"
+ device.getAddress(),
false
));
mAdapter.notifyDataSetChanged();
deviceList.setSelection(delist.size() -
1
);
}
}
else
if
(BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
setProgressBarIndeterminateVisibility(
false
);
if
(deviceList.getCount() ==
0
) {
delist.add(
new
SiriListItem(
"没有发现蓝牙设备"
,
false
));
mAdapter.notifyDataSetChanged();
deviceList.setSelection(list.size() -
1
);
}
discoverBtn.setText(
"重新搜索"
);
}
}
};
// 发送数据
private
void
sendMessageHandle(String msg) {
if
(socket ==
null
) {
Toast.makeText(mContext,
"没有连接"
, Toast.LENGTH_SHORT).show();
return
;
}
try
{
OutputStream os = socket.getOutputStream();
os.write(msg.getBytes());
}
catch
(IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
list.add(
new
deviceListItem(msg,
false
));
mAdapter.notifyDataSetChanged();
chatList.setSelection(list.size() -
1
);
}
//读取数据
private
class
readThread
extends
Thread {
public
void
run() {
byte
[] buffer =
new
byte
[
1024
];
int
bytes;
InputStream mmInStream =
null
;
String tmp =
null
;
try
{
mmInStream = socket.getInputStream();
}
catch
(IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
while
(
true
) {
try
{
//读取输入流中的数据
if
((bytes = mmInStream.read(buffer)) >
0
) {
for
(
int
i =
0
; i < bytes; i++) {
tmp =
""
+buffer<i>;
String st =
new
String(tmp);
tmp =
null
;
Message msg =
new
Message();
msg.obj = st;
msg.what =
1
;
LinkDetectedHandler.sendMessage(msg);
}
}
}
catch
(IOException e) {
try
{
mmInStream.close();
}
catch
(IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
break
;
}
}
}
}</i>
|
八、关于UUID的介绍
简介
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。
作用
UUID 的目的,是让分布式系统中的所有元素,都能有唯一的辨识资讯,而不需要透过中央控制端来做辨识资讯的指定。如此一来,每个人都可以建立不与其它人冲突的 UUID。在这样的情况下,就不需考虑数据库建立时的名称重复问题。目前最广泛应用的 UUID,即是微软的 Microsoft's Globally Unique Identifiers (GUIDs),而其他重要的应用,则有 Linux ext2/ext3 档案系统、LUKS 加密分割区、GNOME、KDE、Mac OS X 等等。
组成
UUID是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的。通常平台会提供生成的API。按照开放软件基金会(OSF)制定的标准计算,用到了以太网卡地址、纳秒级时间、芯片ID码和许多可能的数字
UUID由以下几部分的组合:
(1)当前日期和时间,UUID的第一个部分与时间有关,如果你在生成一个UUID之后,过几秒又生成一个UUID,则第一个部分不同,其余相同。
(2)时钟序列。
(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡MAC地址获得,没有网卡以其他方式获得。
#Android蓝牙串口服务UUID
SerialPortServiceClass_UUID = ‘{00001101-0000-1000-8000-00805F9B34FB}’
附上例程代码:
TestBluetooth.zip