摘要
第一篇算是个热身,这一片开始来写些硬菜了,这篇就是实际和蓝牙打交道了,所以要用到真机调试哟,这篇我会把基本上要讲的概念都通俗易懂的来一遍,这样我们脑子里先有个逻辑,我们就好操作了,先看一下我们的剖析图
下面概念相关的可去原文查看:http://www.epx.com.br/artigos/bluetooth_gatt.php
蓝牙这个名称来自于第十世纪的一位丹麦国王哈拉尔蓝牙王,Blatand 在英文里的意思就是哈拉尔蓝牙王
可以被解释为 Bluetooth( 蓝牙 )因为国王喜欢吃蓝莓,牙龈每天都是蓝色的所以叫蓝牙。
在行业协会筹备阶段,需要一个极具有表现力的名字来命名这项高新技术。行业组织人员, 在经过一夜关于欧洲历史和未来无线技术发展的讨论后,有些人认为用 Blatand 国王的名字 命名再合适不过了。Blatand 国王将挪威,瑞典和丹麦统一起来;他的口齿伶俐,善于交际,就如同这项即将面世的技术,技术将被定义为允许不同工业领域之间的协调工作,保持着各个系统领域之间的良好交流,例如计算机,手机和汽车行业之间的工作。名字于是就这么定 下来了。
蓝牙的创始人是爱立信公司,爱立信早在 1994 年就已进行研发。1997 年,爱立信与 其他设备生产商联系,并激发了他们对该项技术的浓厚兴趣。 1998 年 2 月,跨国大公司, 包括诺基亚、苹果、三星组成的一个特殊兴趣小组(SIG),他们共同的目标是建立一 个全球性的小范围无线通信技术,即蓝牙。
而蓝牙这个标志的设计:它取自 Harald Bluetooth 名字中的「H」和「B」两个字母, 用古北欧字母来表示,将这两者结合起来,就成为了蓝牙的 logo
蓝牙技术规定每一对设备之间进行蓝牙通讯时,必须一个为主角色,另一为从角色,
才能进行通信,通信时,必须由主端进行查找,发起配对,建链成功后,双方即可收发数据。 理论上,一个蓝牙主端设备,可同时与 7 个蓝牙从端设备进行通讯。一个具备蓝牙通讯功 能的设备, 可以在两个角色间切换,平时工作在从模式,等待其它主设备来连接,需要时, 转换为主模式,向其它设备发起呼叫。一个蓝牙设备以主模式发起呼叫时,需要知道对方的 蓝牙地址,配对密码等信息,配对完成后,可直接发起呼叫。
蓝牙主端设备发起呼叫,首先是查找,找出周围处于可被查找的蓝牙设备。主端设备 找到从端蓝牙设备后,与从端蓝牙设备进行配对,此时需要输入从端设备的 PIN 码,也有 设备不需要输入 PIN 码。配对完成后,从端蓝牙设备会记录主端设备的信任信息,此时主 端即可向从端设备发起呼叫,已配对的设备在下次呼叫时,不再需要重新配对。已配对的设备,做为从端的蓝牙耳机也可以发起建链请求,但做数据通讯的蓝牙模块一般不发起呼叫。链路建立成功后,主从两端之间即可进行双向的数据或语音通讯。在通信状态下,主端和从 端设备都可以发起断链,断开蓝牙链路。
蓝牙数据传输应用中,一对一串口数据通讯是最常见的应用之一,蓝牙设备在出厂前 即提前设好两个蓝牙设备之间的配对信息,主端预存有从端设备的 PIN 码、地址等,两端 设备加电即自动建链,透明串口传输,无需外围电路干预。一对一应用中从端设备可以设为两种类型,一是静默状态,即只能与指定的主端通信,不被别的蓝牙设备查找;二是开发状 态,既可被指定主端查找,也可以被别的蓝牙设备查找建链。
参考获取本地蓝牙
2.UUID
1.1 认识一下 UUID UUID 含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标 准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算 环境 (Distributed Computing Environment, DCE) 领域的一部分。
在蓝牙 3.0 及一下版本中,UUID 被用于唯一标识一个服务,比如文件传输服务,串口 服务、打印机服务等,如下:
蓝牙串口服务
SerialPortServiceClass_UUID = ‘{00001101-0000-1000-8000-00805F9B34FB}’
LANAccessUsingPPPServiceClass_UUID = ‘{00001102-0000-1000-8000-00805F9B34FB}’
拨号网络服务
DialupNetworkingServiceClass_UUID = ‘{00001103-0000-1000-8000-00805F9B34FB}’
信息同步服务
IrMCSyncServiceClass_UUID = ‘{00001104-0000-1000-8000-00805F9B34FB}’ SDP_OBEXObjectPushServiceClass_UUID = ‘{00001105-0000-1000-8000-00805F9B34FB} ’
文件传输服务
OBEXFileTransferServiceClass_UUID = ‘{00001106-0000-1000-8000-00805F9B34FB}’ IrMCSyncCommandServiceClass_UUID = ‘{00001107-0000-1000-8000-00805F9B34FB}’
蓝牙的连接有主从设备,提供服务的可以认为是从设备。主设备通过 UUID 访问从设备 提供具有相同 UUID 的服务,从而建立客服端—服务器(C/S)模式。
四.实际应用
我们新建一个Eclipse工程:BluetoothGet
我们直接看图(简单的概念)
<uses-permissionandroid:name="android.permission.BLUETOOTH"/>
<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN"/>
3.编写程序
布局很简单,就一个搜索按钮和一个textview的列表
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<Button
android:id="@+id/btnSearch"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="搜索蓝牙设备" />
<TextView
android:id="@+id/tvDevices"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
步骤分析
// 获取本地蓝牙适配器
mBluetoothAdapter=BluetoothAdapter.getDefaultAdapter();
2.判断手机是否支持蓝牙
// 判断手机是否支持蓝牙
if (mBluetoothAdapter == null) {
Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
finish();
}
3.判断蓝牙是否打开
// 判断是否打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {
// 弹出对话框提示用户是后打开
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
// 不做提示,强行打开
// mBluetoothAdapter.enable();
}
4.获取已经配对的设备// 获取已经配对的设备 SetpairedDevices = mBluetoothAdapter.getBondedDevices();
// 判断是否有配对过的设备
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// 遍历到列表中
tvDevices.append(device.getName() + ":" + device.getAddress());
Log.i("已配对设备", tvDevices.getText().toString());
}
}
5.搜索的点击事件
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
//设置进度条
setProgressBarIndeterminateVisibility(true);
setTitle("正在搜索...");
// 判断是否在搜索,如果在搜索,就取消搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 开始搜索
mBluetoothAdapter.startDiscovery();
break;
}
}
6.搜索的广播
1.注册广播
/**
* 异步搜索蓝牙设备——广播接收
*/
// 找到设备的广播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注册广播
registerReceiver(receiver, filter);
// 搜索完成的广播
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 注册广播
registerReceiver(receiver, filter);
1.广播接收器
// 广播接收器
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 收到的广播类型
String action = intent.getAction();
// 发现设备的广播
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 从intent中获取设备
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判断是否配对过
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 添加到列表
tvDevices.append(device.getName() + ":"
+ device.getAddress() + "\n");
}
// 搜索完成
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
//关闭进度条
setProgressBarIndeterminateVisibility(true);
setTitle("搜索完成!");
}
}
};
好了,到此,我们的程序算是完成了
package com.lgl.bluetoothget;
import java.util.Set;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity implements OnClickListener {
// 本地蓝牙适配器
private BluetoothAdapter mBluetoothAdapter;
// 搜索到蓝牙添加
private TextView tvDevices;
// 搜索蓝牙的按钮
private Button btnSearch;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
tvDevices = (TextView) findViewById(R.id.tvDevices);
btnSearch = (Button) findViewById(R.id.btnSearch);
btnSearch.setOnClickListener(this);
// 获取本地蓝牙适配器
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
// 判断手机是否支持蓝牙
if (mBluetoothAdapter == null) {
Toast.makeText(this, "设备不支持蓝牙", Toast.LENGTH_SHORT).show();
finish();
}
// 判断是否打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {
// 弹出对话框提示用户是后打开
Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(intent, 1);
// 不做提示,强行打开
// mBluetoothAdapter.enable();
}
// 获取已经配对的设备
SetpairedDevices = mBluetoothAdapter
.getBondedDevices();
// 判断是否有配对过的设备
if (pairedDevices.size() > 0) {
for (BluetoothDevice device : pairedDevices) {
// 遍历到列表中
tvDevices.append(device.getName() + ":" + device.getAddress());
Log.i("已配对设备", tvDevices.getText().toString());
}
}
/**
* 异步搜索蓝牙设备——广播接收
*/
// 找到设备的广播
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
// 注册广播
registerReceiver(receiver, filter);
// 搜索完成的广播
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
// 注册广播
registerReceiver(receiver, filter);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnSearch:
// 设置进度条
setProgressBarIndeterminateVisibility(true);
setTitle("正在搜索...");
// 判断是否在搜索,如果在搜索,就取消搜索
if (mBluetoothAdapter.isDiscovering()) {
mBluetoothAdapter.cancelDiscovery();
}
// 开始搜索
mBluetoothAdapter.startDiscovery();
break;
}
}
// 广播接收器
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// 收到的广播类型
String action = intent.getAction();
// 发现设备的广播
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// 从intent中获取设备
BluetoothDevice device = intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// 判断是否配对过
if (device.getBondState() != BluetoothDevice.BOND_BONDED) {
// 添加到列表
tvDevices.append(device.getName() + ":"
+ device.getAddress() + "\n");
}
// 搜索完成
} else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED
.equals(action)) {
// 关闭进度条
setProgressBarIndeterminateVisibility(true);
setTitle("搜索完成!");
}
}
};
}
我们运行一下