注意:我的这个工程的目的主要是为了连接单片机的HC-06蓝牙模块
参考资料:
1 消息传递
我打算把讲解分成这三个部分,这三个部分是相对独立的,你最好一块一块学,我之前一口气学了之后,感觉非常难理解。这三个部分是:启动蓝牙功能、获取目标蓝牙设备的信息、与蓝牙设备建立连接。
在讲蓝牙之前,你需要先知道两个关于Android信息传递的重要知识点,这两个知识点在其他地方也是用的到的。
1.1 广播监听
Android广播事件,这个其实很好理解,你可以发送广播消息,你也可以接收广播消息。广播消息可能来自你自己,也可能来自系统。主要用于监听某些事件的变化,假设该事件为actionA,当actionA发生变化的时候,你可以利用广播监听进入对应的函数当中,执行你的命令。
这部分知识不难,网上教程很多,我就不自己写了。
你需要学会如下内容:
如何写广播监听函数?如何注册广播监听函数? 如何发送广播?
1.2 Handler、Message、Looper
这三个比较麻烦需要花时间消化一下
Android的消息机制(一)Android的消息机制(二) 你要知道以下内容:
如何在主线程中创建一个Handler类的实例,来实现信息接收的功能?
如何在其他地方用Message类包装数据,用主线程的handler实例来向主线程发送信息?
如何在子线程中利用Looper和Handler创建一个子线程的信息接收器?
这个网上也有很多教程,不过我还是再说几句。
假设消息传递者 A 打算传递消息给 B,分为两种情况:B 是主线程,或 B 是子线程。为什么区分这两种情况。原因在于,利用Handle转递消息时会进入由循环程序中,该循环程序是在Looper 中实现的,而每个线程只能有一个Looper。主线程默认是有一个 Looper 的,子线程的Looper需要自己创建。 在该循环程序中,会持续判断是否有消息传过来,有就处理,没有就继续循环。消息处理的机制是由MessageQueue实现的,它的本质是队列,就是先到的消息先处理,后到的消息后处理。
1.2.1 消息接收者 B 如果是主线程
由于默认有一个Looper,所以直接创建一个 Handler 类的成员就好了
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
//消息传递是由Message类进行封装的。
switch (msg.what)
{
//写入判断+处理程序
}
}
};
1.2.2 消息接收者 B 如果是主线程
至于为什么下列语句就可以使得 mHandler 与该线程的 Looper 绑定,大家可以去网上查查,是由静态实现的。
//在子线程中
void run(){
Looper.prepare(); //创建一个Looper
mHandler= new Handler() { //通过该语句处理消息
public void handleMessage(Message msg) {
int what = msg.what;
Object obj = msg.obj;
switch (what) {
//此处写入对应的消息处理程序
}
}
};
Looper.loop(); //打开消息泵
}
1.2.3 发送消息
//用Message类进行封装
Message msg = new Message();
msg.what = 1;//该参数指定消息类型
msg.arg1 = 1;//该参数看你的需求
msg.arg2 = 1;//该参数看你的需求
msg.obj = "这里可以存储任意类型的数据,不过接收后,记得强转";//这里存放消息
handler.sendMessage(msg);//发送消息
//注意,handler必须是目标的handler,你可以使得主线程创建的handler传进这里来
2 启动蓝牙
先讲讲最简单的部分,启动蓝牙。
2.1 蓝牙权限
在 AndroidManifest.xml 文件中添加权限
在 manifest 属性中,application 属性上面添加下面内容
<uses-permission android:name="android.permission.BLUETOOTH" />
<!--允许启动蓝牙功能-->
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!--允许程序进行发现和配对新的蓝牙设备-->
2.2 启动蓝牙功能
我现在只要实现使手机启动蓝牙这个功能。
1)获取蓝牙适配器,后面要用到
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
2)尝试开启蓝牙功能
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBtIntent);
//我这里是另外写了一个类,所以需要传入主类的 Context 类实例
//如果是在主类中写,只需要写 startActivity(enableBtIntent);
3)广播监听蓝牙开启状态
其实由2)就可以实现开启蓝牙的功能了,但是如果你想检测蓝牙什么时候开启,然后再自动运行指定程序的话,就需要利用广播监听。
先建立广播监听的接收类
private class BluetoothStateBroadcastReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();//取出动作的字符串
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (action) {//判断来自哪一个动作
//动作来自蓝牙功能变化
case BluetoothAdapter.ACTION_STATE_CHANGED:
int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);//检测当前蓝牙状态
if (blueState == BluetoothAdapter.STATE_ON) {
try {
//蓝牙已经启动,可以注销该广播监听了
context.unregisterReceiver(bluetoothStateBroadcastReceive);
} catch (Exception e) {
Log.d("蓝牙状态", "注销监听失败,监听实例不存在");
}
}
//这里可以执行下一步
}
}
}
4)注册广播监听函数
//创建监听函数的实例,该变量最后是类中的成员变量,因为注销的时候需要用该实例
BluetoothStateBroadcastReceive bluetoothStateBroadcastReceive = new BluetoothStateBroadcastReceive();
//指定监听动作
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
//绑定监听动作和监听接收的函数
context.registerReceiver(bluetoothStateBroadcastReceive,filter);
最后附上启动蓝牙部分的完整代码
public class BlueToothTool {
//建立成员变量
//来自布局的信息
BluetoothAdapter mBluetoothAdapter;//蓝牙适配器
Context context;
Handler handlerToMain;
//构造函数
private BlueToothTool(){
super();
}
public BlueToothTool(BluetoothAdapter mBluetoothAdapter, Context context, Handler handler){
this.mBluetoothAdapter = mBluetoothAdapter;
this.context = context;
this.handlerToMain = handler;
//打开蓝牙功能
BlueToothFuctionStart();
}
/**
* 1.尝试打开蓝牙功能
*/
private void BlueToothFuctionStart(){
mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter!=null){
//检测是否开启了蓝牙功能,注意startActivity会开启子线程,无法在此语句后面直接判断蓝牙功能是否被开启
if(!mBluetoothAdapter.isEnabled()) {
//尝试开启蓝牙功能
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
context.startActivity(enableBtIntent);
//注册对蓝牙状态功能的监听事件
//实例化IntentFilter对象
IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); //可以用构造方法添加Action
context.registerReceiver(bluetoothStateBroadcastReceive,filter);
}else{
//直接执行下一步
//获取过去配对过的信息
//2.1查找已配对的设备
}
}else{
Toast.makeText(context,"您的设备不支持蓝牙系统",Toast.LENGTH_SHORT).show();
}
}
/**
* 1.1通过广播对蓝牙状态进行监听
*/
private BluetoothStateBroadcastReceive bluetoothStateBroadcastReceive = new BluetoothStateBroadcastReceive();
private class BluetoothStateBroadcastReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
switch (action) {
case BluetoothAdapter.ACTION_STATE_CHANGED:
int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
if (blueState == BluetoothAdapter.STATE_ON) {
try {
//注销对象
context.unregisterReceiver(bluetoothStateBroadcastReceive);
} catch (Exception e) {
Log.d("蓝牙状态", "注销监听失败,监听对象不存在");
}
}
//执行下一步
//获取过去配对过的信息
//2.1查找已配对的设备
}
}
}
}