Android 蓝牙

Android手机和电脑bluetooth(蓝牙)通信问题:

1.两边的UUID必须是一样的,这是一个服务的唯一标识,而且这个UUID的值必须是  

00001101-0000-1000-8000-00805F9B34FB,为什么呢?因为android的API上面说明:这是用于普通蓝牙适配器和android手机蓝牙模块连接的,请大家自己看一下android有关bluetooth的API。

2.在连接的时候,如果电脑作为server(一直监听是否有服务连接),android手机作为client(主动和电脑建立连接),则需要在手机端调用这样一行代码:mmSocket.connect(); 
其中mmSocket是一个BluetoothSocket类,在这句话之前请确定你已经把手机和电脑进行了配对,而且那些乱七八糟的设置都搞定了。

 

 

一. 什么是蓝牙(Bluetooth)?

1.1  BuleTooth是目前使用最广泛的无线通信协议

1.2  主要针对短距离设备通讯(10m)

1.3  常用于连接耳机,鼠标和移动通讯设备等.

二. 与蓝牙相关的API

2.1 BluetoothAdapter:

代表了本地的蓝牙适配器

2.2 BluetoothDevice

代表了一个远程的Bluetooth设备

三. 扫描已经配对的蓝牙设备(1)

注:必须部署在真实手机上,模拟器无法实现

首先需要在AndroidManifest.xml 声明蓝牙权限

<user-permission android:name="android.permission.BLUETOOTH" />

配对蓝牙需要手动操作:

1. 打开设置--> 无线网络 --> 蓝牙 勾选开启

2. 打开蓝牙设置  扫描周围已经开启的蓝牙设备(可以与自己的笔记本电脑进行配对),点击进行配对

 电脑上会弹出提示窗口添加设备

 显示计算与设备之间的配对码,要求确认是否配对

 手机上也会显示类似的提示

四. 扫描已经配对的蓝牙设备(2)

4.1 获得BluetoothAdapter对象

4.2 判断当前移动设备中是否拥有蓝牙

4.3 判断当前移动设备中蓝牙是否已经打开

4.4 得到所有已经配对的蓝牙设备对象



实现代码如下:

MainActivity:

 

  1. import java.util.Iterator;  
  2. import java.util.Set;  
  3.   
  4. import android.app.Activity;  
  5. import android.bluetooth.BluetoothAdapter;  
  6. import android.bluetooth.BluetoothDevice;  
  7. import android.content.Intent;  
  8. import android.os.Bundle;  
  9. import android.view.View;  
  10. import android.view.View.OnClickListener;  
  11. import android.widget.Button;  
  12.   
  13. public class MainActivity extends Activity {  
  14.     private Button button = null;  
  15.     /** Called when the activity is first created. */  
  16.     @Override  
  17.     public void onCreate(Bundle savedInstanceState) {  
  18.         super.onCreate(savedInstanceState);  
  19.         setContentView(R.layout.main);  
  20.           
  21.         button = (Button)findViewById(R.id.buttonId);  
  22.         button.setOnClickListener(new OnClickListener(){  
  23.   
  24.             @Override  
  25.             public void onClick(View v) {  
  26.                 //获得BluetoothAdapter对象,该API是android 2.0开始支持的  
  27.                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();  
  28.                 //adapter不等于null,说明本机有蓝牙设备  
  29.                 if(adapter != null){  
  30.                     System.out.println("本机有蓝牙设备!");  
  31.                     //如果蓝牙设备未开启  
  32.                     if(!adapter.isEnabled()){  
  33.                         Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);  
  34.                         //请求开启蓝牙设备  
  35.                         startActivity(intent);  
  36.                     }  
  37.                     //获得已配对的远程蓝牙设备的集合  
  38.                     Set<BluetoothDevice> devices = adapter.getBondedDevices();  
  39.                     if(devices.size()>0){  
  40.                         for(Iterator<BluetoothDevice> it = devices.iterator();it.hasNext();){  
  41.                             BluetoothDevice device = (BluetoothDevice)it.next();  
  42.                             //打印出远程蓝牙设备的物理地址  
  43.                             System.out.println(device.getAddress());  
  44.                         }  
  45.                     }else{  
  46.                         System.out.println("还没有已配对的远程蓝牙设备!");  
  47.                     }  
  48.                 }else{  
  49.                     System.out.println("本机没有蓝牙设备!");  
  50.                 }  
  51.             }  
  52.         });  
  53.     }  
  54. }  

 

1.     概述

Bluetooth 是几乎现在每部手机标准配备的功能,多用于耳机 mic 等设备与手机的连接,除此之外,还可以多部手机之间建立 bluetooth 通信,本文就通过 SDK 中带的一个聊天室的例程,来介绍一下 android 上的 Bluetooth 的开发。
在 Android1.x 的时候,相关 API 非常不完善,还不能简单的使用 Bluetooth 开发,有一个开源项目可以帮助程序员使用、开发蓝牙,支持直接方法bluetooth 协议栈。在 Android2 以后,框架提供了一些官方 API 来进行蓝牙的通信,但目前的程序也比较不完善。本文主要讨论 Android2 后的Bluetooth 通信的 API 使用方法。
首先看聊天室的效果图:
 

2.     Bluetooth 通信 API 介绍2.1. Bluetooth 通信过程

 

 

2.2. Bluetooth API 的主要方法

BluetoothAdapter 类
BluetoothAdapter.getDefaultAdapter() :得到本地默认的 BluetoothAdapter ,若返回为 null 则表示本地不支持蓝牙;
isDiscovering() :返回设备是否正在发现周围蓝牙设备;
cancelDiscovery() :取消正在发现远程蓝牙设备的过程;
startDiscovery() :开始发现过程;
getScanMode() :得到本地蓝牙设备的 Scan Mode ;
getBondedDevices() :得到已配对的设备;
isEnabled() :蓝牙功能是否启用。
当发现蓝牙功能未启用时,如下调用设置启用蓝牙:
if  (!   mBluetoothAdapter .isEnabled()) { Intent enableIntent =   new Intent(BluetoothAdapter. ACTION_REQUEST_ENABLE ); startActivityForResult(enableIntent, REQUEST_ENABLE_BT ); }
如果发现当前设备没有打开对外可见模式,则传递 Intent 来调用打开可发现模式,代码如下:
Intent discoverableIntent =   new   Intent(BluetoothAdapter. ACTION_REQUEST_DISCOVERABLE ); discoverableIntent.putExtra(BluetoothAdapter. EXTRA_DISCOVERABLE_DURATION , 300   ); startActivity(discoverableIntent);

 

BluetoothDevice 类,此为对应的远程蓝牙 Device
       createRfcommSocketToServiceRecord() :创建该 Device 的 socket 。
BluetoothSocket 类
       connect() :请求连接蓝牙。
getInputStream() :得到输入流,用于接收远程方信息。
getOutputStream() :得到输出流,发送给远程方的信息。
close() :关闭蓝牙连接。
InputStream 类:
       read(byte[]) :以阻塞方式读取输入流。
OutputStream 类:
       write(byte[]) :将信息写入该输出流,发送给远程。
3.     BluetoothChat 例程分析
Google 提供的关于 Bluetooth 开发的例程为 Bluetoothchat ,使用截图可见本文一开始。除去配置及 ui 定义等文件,主程序文件共三个:BluetoothChat.java 、 BluetoothChatService.java 以及 DeviceListActivity.java ,详细功能可见下面的描述。
3.1. 整体调用关系序列图

 

3.2. BluetoothChat.java
例程的主 Activity 。 onCreate() 得到本地 BluetoothAdapter 设备,检查是否支持。 onStart() 中检查是否启用蓝牙,并请求启用,然后执行 setupChat()。 setupChat() 中先对界面中的控件进行初始化增加点击监听器等,然创建 BluetoothChatService 对象,该对象在整个应用过程中存在,并执行蓝牙连接建立、消息发送接受等实际的行为。
3.3. BluetoothChatService.java
public synchronized void start() :
开启 mAcceptThread 线程,由于样例程序是仅 2 人的聊天过程,故之前先检测 mConnectThread 和 mConnectedThread 是否运行,运行则先退出这些线程。
public synchronized void connect(BluetoothDevice device) :
取消 CONNECTING 和 CONNECTED 状态下的相关线程,然后运行新的 mConnectThread 线程。
public synchronized void connected(BluetoothSocket socket, BluetoothDevice device)
开启一个 ConnectedThread 来管理对应的当前连接。之前先取消任意现存的 mConnectThread 、 mConnectedThread 、 mAcceptThread 线程,然后开启新 mConnectedThread ,传入当前刚刚接受的 socket 连接。最后通过 Handler 来通知 UI 连接 OK 。
public synchronized void stop() :
停止所有相关线程,设当前状态为 NONE 。
public void write(byte[] out) :
在 STATE_CONNECTED 状态下,调用 mConnectedThread 里的 write 方法,写入 byte 。
private void connectionFailed() :
连接失败的时候处理,通知 ui ,并设为 STATE_LISTEN 状态。
private void connectionLost() :
当连接失去的时候,设为 STATE_LISTEN 状态并通知 ui 。
内部类:
private class AcceptThread extends Thread :
创建监听线程,准备接受新连接。使用阻塞方式,调用 BluetoothServerSocket.accept() 。提供 cancel 方法关闭 socket 。
private class ConnectThread extends Thread :
这是定义的连接线程,专门用来对外发出连接对方蓝牙的请求和处理流程。构造函数里通过 BluetoothDevice.createRfcommSocketToServiceRecord(),从待连接的 device 产生 BluetoothSocket. 然后在 run 方法中 connect ,成功后调用 BluetoothChatSevice 的 connected() 方法。定义 cancel() 在关闭线程时能够关闭相关 socket 。
private class ConnectedThread extends Thread :
这个是双方蓝牙连接后一直运行的线程。构造函数中设置输入输出流。 Run 方法中使用阻塞模式的 InputStream.read() 循环读取输入流, 然后 post 到UI 线程中更新聊天消息。也提供了 write() 将聊天消息写入输出流传输至对方,传输成功后回写入 UI 线程。最后 cancel() 关闭连接的 socket 。
3.4. DeviceListActivity.java
该类包含 UI 和操作的 Activity 类,作用是得到系统默认蓝牙设备的已配对设备列表,以及搜索出的未配对的新设备的列表。然后提供点击后发出连接设备请求的功能。
 
除了 RFCOMM 通信外, Android 上关于 Bluetooth 的还有 SDP 、 GAP 、耳机设备连接等内容,本文还未涉及,将会随着蓝牙相关 API 在新版本中的进一步完善来学习使用。

 

 

 上次介绍了Android利用麦克风采集并显示模拟信号,这种采集手段适用于无IO控制、单纯读取信号的情况。如果传感器本身需要包含控制电路(例如采集血氧信号需要红外和红外线交替发射),那么传感器本身就需要带一片主控IC,片内采集并输出数字信号了。Android手机如何在不改硬件电路的前提下与这类数字传感器交互呢?可选的通信方式就有USB和蓝牙,两种方式各有好处:USB方式可以给传感器供电,蓝牙方式要自备电源;USB接口标准不一,蓝牙普遍支持SPP协议。本文选择蓝牙方式做介绍,介绍Android的蓝牙API以及蓝牙客户端的用法。
      在Android 2.0,官方终于发布了蓝牙API(2.0以下系统的非官方的蓝牙API可以参考这里:http://code.google.com/p/android-bluetooth/)。Android手机一般以客户端的角色主动连接SPP协议设备(接上蓝牙模块的数字传感器),连接流程是:
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()来读写蓝牙设备。

 

先来看看本文程序运行的效果图,所选的SPP协议设备是一款单导联心电采集表:

本文的代码较多,可以到这里下载:http://www.pudn.com/downloads305/sourcecode/comm/android/detail1359043.html

本文程序包含两个Activity(testBlueTooth和WaveDiagram),testBlueTooth是搜索建立蓝牙连接。BluetoothAdapter、BluetoothDevice和BluetoothSocket的使用很简单,除了前三者提供的功能外,还可以通过给系统发送消息来控制、获取蓝牙信息,例如:

注册BroadcastReceiver:

 

  1. IntentFilter intent = new IntentFilter();  
  2. intent.addAction(BluetoothDevice.ACTION_FOUND);// 用BroadcastReceiver来取得搜索结果  
  3. intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);  
  4. intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);  
  5. intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);  
  6. registerReceiver(searchDevices, intent);  

 

在BroadcastReceiver的onReceive()枚举所有消息的内容:

 

  1. String action = intent.getAction();  
  2.             Bundle b = intent.getExtras();  
  3.             Object[] lstName = b.keySet().toArray();  
  4.   
  5.             // 显示所有收到的消息及其细节  
  6.             for (int i = 0; i < lstName.length; i++) {  
  7.                 String keyName = lstName[i].toString();  
  8.                 Log.e(keyName, String.valueOf(b.get(keyName)));  
  9.             }  

 

在DDMS里面可以看到BluetoothDevice.ACTION_FOUND返回的消息:

 

程序另外一个Activity~~~WaveDiagram用于读取蓝牙数据并绘制波形图,这里要注意一下JAVA的byte的取值范围是跟C/C++不一样的,Android接收到的byte数据要做"& 0xFF"处理,转为C/C++等值的数据。


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值