Android 教你如何写蓝牙程序1——消息传递、启动蓝牙
注意:我的这个工程的目的主要是为了连接单片机的HC-06蓝牙模块
参考资料:
蓝牙的资料:
Android 蓝牙开发(1)
Android 蓝牙开发(2)
Android 蓝牙开发(3)
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(); //创建一个LoopermHandler= 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查找已配对的设备 } } }}
这是第二篇内容:
Android 教你如何写蓝牙程序2——获取目标信息