安卓蓝牙开发(android开发之蓝牙配对连接的方法)
一、如何实现android蓝牙自动配对连接
之前做一个Android版的蓝牙与血压计通讯的项目,遇到最大的难题就是自动配对.
上网查资料说是用反射createBond()和setPin(),但测试时进行配对还是会出现提示,但配对是成功了
我就开始查找怎么关闭这个蓝牙配对提示框,后面还是伟大的android源码帮助了我。
在源码 BluetoothDevice类中还有两个隐藏方法
cancelBondProcess()和cancelPairingUserInput()
这两个方法一个是取消配对进程一个是取消用户输入
下面是自动配对的代码
Mainfest,xml注册
1<receiver android:name=".BluetoothConnectActivityReceiver">
2<intent-filter>
3<action android:name="android.bluetooth.device.action.PAIRING_REQUEST"/>
4</intent-filter>
5</receiver>
自己在收到广播时处理并将预先输入的密码设置进去
01 public class BluetoothConnectActivityReceiver extends BroadcastReceiver
02{
03
04 String strPsw="0";
05
06@Override
07 public void onReceive(Context context, Intent intent)
08{
09// TODO Auto-generated method stub
10 if(intent.getAction().equals(
11"android.bluetooth.device.action.PAIRING_REQUEST"))
12{
13 BluetoothDevice btDevice= intent
14.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
15
16// byte[] pinBytes= BluetoothDevice.convertPinToBytes("1234");
17// device.setPin(pinBytes);
18 Log.i("tag11111","ddd");
19 try
20{
21 ClsUtils.setPin(btDevice.getClass(), btDevice, strPsw);//手机和蓝牙采集器配对
22 ClsUtils.createBond(btDevice.getClass(), btDevice);
23 ClsUtils.cancelPairingUserInput(btDevice.getClass(), btDevice);
24}
25 catch(Exception e)
26{
27// TODO Auto-generated catch block
28 e.printStackTrace();
29}
30}
31
32
33}
34}
001<b>/************************************蓝牙配对函数***************/
002 import java.lang.reflect.Field;
003 import java.lang.reflect.Method;
004
005 import android.bluetooth.BluetoothDevice;
006 import android.util.Log;
007 public class ClsUtils
008{
009
010/**
011*与设备配对参考源码:platform/packages/apps/Settings.git
012*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
013*/
014 static public boolean createBond(Class btClass, BluetoothDevice btDevice)
015 throws Exception
016{
017 Method createBondMethod= btClass.getMethod("createBond");
018 Boolean returnValue=(Boolean) createBondMethod.invoke(btDevice);
019 return returnValue.booleanValue();
020}
021
022/**
023*与设备解除配对参考源码:platform/packages/apps/Settings.git
024*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
025*/
026 static public boolean removeBond(Class btClass, BluetoothDevice btDevice)
027 throws Exception
028{
029 Method removeBondMethod= btClass.getMethod("removeBond");
030 Boolean returnValue=(Boolean) removeBondMethod.invoke(btDevice);
031 return returnValue.booleanValue();
032}
033
034 static public boolean setPin(Class btClass, BluetoothDevice btDevice,
035 String str) throws Exception
036{
037 try
038{
039 Method removeBondMethod= btClass.getDeclaredMethod("setPin",
040 new Class[]
041{byte[].class});
042 Boolean returnValue=(Boolean) removeBondMethod.invoke(btDevice,
043 new Object[]
044{str.getBytes()});
045 Log.e("returnValue",""+ returnValue);
046}
047 catch(SecurityException e)
048{
049// throw new RuntimeException(e.getMessage());
050 e.printStackTrace();
051}
052 catch(IllegalArgumentException e)
053{
054// throw new RuntimeException(e.getMessage());
055 e.printStackTrace();
056}
057 catch(Exception e)
058{
059// TODO Auto-generated catch block
060 e.printStackTrace();
061}
062 return true;
063
064}
065
066//取消用户输入
067 static public boolean cancelPairingUserInput(Class btClass,
068 BluetoothDevice device)
069
070 throws Exception
071{
072 Method createBondMethod= btClass.getMethod("cancelPairingUserInput");
073// cancelBondProcess()
074 Boolean returnValue=(Boolean) createBondMethod.invoke(device);
075 return returnValue.booleanValue();
076}
077
078//取消配对
079 static public boolean cancelBondProcess(Class btClass,
080 BluetoothDevice device)
081
082 throws Exception
083{
084 Method createBondMethod= btClass.getMethod("cancelBondProcess");
085 Boolean returnValue=(Boolean) createBondMethod.invoke(device);
086 return returnValue.booleanValue();
087}
088
089/**
090*
091*@param clsShow
092*/
093 static public void printAllInform(Class clsShow)
094{
095 try
096{
097//取得所有方法
098 Method[] hideMethod= clsShow.getMethods();
099 int i= 0;
100 for(; i< hideMethod.length; i++)
101{
102 Log.e("method name", hideMethod[i].getName()+";and the i is:"
103+ i);
104}
105//取得所有常量
106 Field[] allFields= clsShow.getFields();
107 for(i= 0; i< allFields.length; i++)
108{
109 Log.e("Field name", allFields[i].getName());
110}
111}
112 catch(SecurityException e)
113{
114// throw new RuntimeException(e.getMessage());
115 e.printStackTrace();
116}
117 catch(IllegalArgumentException e)
118{
119// throw new RuntimeException(e.getMessage());
120 e.printStackTrace();
121}
122 catch(Exception e)
123{
124// TODO Auto-generated catch block
125 e.printStackTrace();
126}
127}
128}</b>
执行时直接使用:
view sourceprint?
01<b>public static boolean pair(String strAddr, String strPsw)
02{
03 boolean result= false;
04 BluetoothAdapter bluetoothAdapter= BluetoothAdapter
05.getDefaultAdapter();
06
07 bluetoothAdapter.cancelDiscovery();
08
09 if(!bluetoothAdapter.isEnabled())
10{
11 bluetoothAdapter.enable();
12}
13
14 if(!BluetoothAdapter.checkBluetoothAddress(strAddr))
15{//检查蓝牙地址是否有效
16
17 Log.d("mylog","devAdd un effient!");
18}
19
20 BluetoothDevice device= bluetoothAdapter.getRemoteDevice(strAddr);
21
22 if(device.getBondState()!= BluetoothDevice.BOND_BONDED)
23{
24 try
25{
26 Log.d("mylog","NOT BOND_BONDED");
27 ClsUtils.setPin(device.getClass(), device, strPsw);//手机和蓝牙采集器配对
28 ClsUtils.createBond(device.getClass(), device);
29 remoteDevice= device;//配对完毕就把这个设备对象传给全局的remoteDevice
30 result= true;
31}
32 catch(Exception e)
33{
34// TODO Auto-generated catch block
35
36 Log.d("mylog","setPiN failed!");
37 e.printStackTrace();
38}//
39
40}
41 else
42{
43 Log.d("mylog","HAS BOND_BONDED");
44 try
45{
46 ClsUtils.createBond(device.getClass(), device);
47 ClsUtils.setPin(device.getClass(), device, strPsw);//手机和蓝牙采集器配对
48 ClsUtils.createBond(device.getClass(), device);
49 remoteDevice= device;//如果绑定成功,就直接把这个设备对象传给全局的remoteDevice
50 result= true;
51}
52 catch(Exception e)
53{
54// TODO Auto-generated catch block
55 Log.d("mylog","setPiN failed!");
56 e.printStackTrace();
57}
58}
59 return result;
60}</b>
二、Android开发之蓝牙(Bluetooth)
在上一篇中有介绍了Wifi与网络连接处理
Android开发之WiFi与网络连接处理
下面,来继续说说Android中蓝牙的基本使用。
Bluetooth是目前使用的最广泛的无线通讯协议之一,主要针对短距离设备通讯(10米),常用于连接耳机、鼠标和移动通讯设备等。
值得一提的是:
android4.2新增了部分新功能,但是对于Bluetooth熟悉的人或许开始头疼了,那就是Android4.2引入了一个新的蓝牙协议栈针BLE。谷歌和Broadcom之间的合作,开发新的蓝牙协议栈,取代了基于堆栈的Bluez。因此市场上出现了老设备的兼容问题,很多蓝牙设备在android4.2手机上不能正常使用。
BluetoothAdapter简单点来说就是代表了本设备(手机、电脑等)的蓝牙适配器对象。
first:we need permission
要操作蓝牙,先要在AndroidManifest.xml里加入权限
**下面来看看如何使用蓝牙。**↓↓↓****
Demo已就绪:
返回值:如果设备具备蓝牙功能,返回BluetoothAdapter实例;否则,返回null对象。
打开蓝牙设备的方式:
1.直接调用函数enable()去打开蓝牙设备;
2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。
注意: 1.如果蓝牙已经开启,不会弹出该Activity界面。2.在目前大多数Android手机中,是不支持在飞行模式下开启蓝牙的。如果蓝牙已经开启,那么蓝牙的开关,状态会随着飞行模式的状态而发生改变。
1.搜索蓝牙设备
使用BluetoothAdapter的startDiscovery()方法来搜索蓝牙设备
startDiscovery()方法是一个异步方法,调用后会立即返回。该方法会进行对其他蓝牙设备的搜索,该过程会持续12秒。该方法调用后,搜索过程实际上是在一个System Service中进行的,所以可以调用cancelDiscovery()方法来停止搜索(该方法可以在未执行discovery请求时调用)。
系统开始搜索蓝牙设备
^(* ̄(oo) ̄) ^系统会发送以下三个广播:
2.扫描设备
3.定义广播接收器接收搜索结果
4.注册广播
获取附近的蓝牙设备
第一步建立连接:首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接,服务端BluetoothServerSocket和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接。
(这里的服务端和客户端是相对来说的)
两个蓝牙设备之间的连接,则必须实现服务端与客户端的机制。
当两个设备在同一个RFCOMM channel下分别拥有一个连接的BluetoothSocket,这两个设备才可以说是建立了连接。
服务端设备与客户端设备获取BluetoothSocket的途径是不同的。
1,服务端设备是通过accepted一个incoming connection来获取的,
2,客户端设备则是通过打开一个到服务端的RFCOMM channel来获取的。
服务端
通过调用BluetoothAdapter的listenUsingRfcommWithServiceRecord(String, UUID)方法来获取BluetoothServerSocket(UUID用于客户端与服务端之间的配对)
客户端
调用BluetoothService的createRfcommSocketToServiceRecord(UUID)方法获取BluetoothSocket(该UUID应该同于服务端的UUID)。
调用BluetoothSocket的connect()方法(该方法为block方法),如果UUID同服务端的UUID匹配,并且连接被服务端accept,则connect()方法返回。
数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式
获取流
该类就是关于远程蓝牙设备的一个描述。通过它可以和本地蓝牙设备---BluetoothAdapter连接通信。
好多东西我也不知道怎么描述,下面给出Demo:
刚好有刚学习的小伙伴问我ListView怎么用,那我就用ListView。
源码:
RairDemo
GitHub:
Coding:
三、如何使用Android蓝牙开发
转载 Android平台支持蓝牙网络协议栈,实现蓝牙设备之间数据的无线传输。本文档描述了怎样利用android平台提供的蓝牙API去实现蓝压设备之间的通信。蓝牙具有point-to-point和 multipoint两种连接功能。
使用蓝牙API,可以做到:
*搜索蓝牙设备
*从本地的Bluetooth adapter中查询已经配对的设备
*建立RFCOMM通道
*通过service discovery连接到其它设备
*在设备之间传输数据
*管理多个连接
基础知识
本文档介绍了如何使用Android的蓝牙API来完成的四个必要的主要任务,使用蓝牙进行设备通信,主要包含四个部分:蓝牙设置、搜索设备(配对的或可见的)、连接、传输数据。
所有的蓝牙API在android.bluetooth包中。实现这些功能主要需要下面这几个类和接口:
BluetoothAdapter
代表本地蓝牙适配器(蓝牙发射器),是所有蓝牙交互的入口。通过它可以搜索其它蓝牙设备,查询已经配对的设备列表,通过已知的MAC地址创建BluetoothDevice,创建BluetoothServerSocket监听来自其它设备的通信。
BluetoothDevice
代表了一个远端的蓝牙设备,使用它请求远端蓝牙设备连接或者获取远端蓝牙设备的名称、地址、种类和绑定状态。(其信息是封装在 bluetoothsocket中)。
BluetoothSocket
代表了一个蓝牙套接字的接口(类似于 tcp中的套接字),他是应用程序通过输入、输出流与其他蓝牙设备通信的连接点。
BluetoothServerSocket
代表打开服务连接来监听可能到来的连接请求(属于 server端),为了连接两个蓝牙设备必须有一个设备作为服务器打开一个服务套接字。当远端设备发起连接连接请求的时候,并且已经连接到了的时候,Blueboothserversocket类将会返回一个 bluetoothsocket。
BluetoothClass
描述了一个设备的特性(profile)或该设备上的蓝牙大致可以提供哪些服务(service),但不可信。比如,设备是一个电话、计算机或手持设备;设备可以提供audio/telephony服务等。可以用它来进行一些UI上的提示。
BluetoothProfile
BluetoothHeadset
提供手机使用蓝牙耳机的支持。这既包括蓝牙耳机和免提(V1.5)模式。
BluetoothA2dp
定义高品质的音频,可以从一个设备传输到另一个蓝牙连接。“A2DP的”代表高级音频分配模式。
BluetoothHealth
代表了医疗设备配置代理控制的蓝牙服务
BluetoothHealthCallback
一个抽象类,使用实现BluetoothHealth回调。你必须扩展这个类并实现回调方法接收更新应用程序的注册状态和蓝牙通道状态的变化。
BluetoothHealthAppConfiguration
代表一个应用程序的配置,蓝牙医疗第三方应用注册与远程蓝牙医疗设备交流。
BluetoothProfile.ServiceListener
当他们已经连接到或从服务断开时通知BluetoothProfile IPX的客户时一个接口(即运行一个特定的配置文件,内部服务)。
蓝牙权限
为了在你的应用中使用蓝牙功能,至少要在AndroidManifest.xml中声明两个权限:BLUETOOTH(任何蓝牙相关API都要使用这个权限)和 BLUETOOTH_ADMIN(设备搜索、蓝牙设置等)。
为了执行蓝牙通信,例如连接请求,接收连接和传送数据都必须有BLUETOOTH权限。
必须要求BLUETOOTH_ADMIN的权限来启动设备发现或操纵蓝牙设置。大多数应用程序都需要这个权限能力,发现当地的蓝牙设备。此权限授予其他的能力不应该使用,除非应用程序是一个“电源管理”,将根据用户要求修改的蓝牙设置
注释:要请求BLUETOOTH_ADMIN的话,必须要先有BLUETOOTH。
在你的应用manifest文件中声明蓝牙权限。例如:
<manifest...>
<uses-permission android:name="android.permission.BLUETOOTH"/>
...
</manifest>
通过查看<uses-permission>资料来声明应用权限获取更多的信息。
蓝牙设置
在你的应用通过蓝牙进行通信之前,你需要确认设备是否支持蓝牙,如果支持,确信它被打开。
如果不支持,则不能使用蓝牙功能。如果支持蓝牙,但不能够使用,你刚要在你的应用中请求使用蓝牙。这个要两步完成,使用BluetoothAdapter。
1.获取BluetoothAdapter
所有的蓝牙活动请求BluetoothAdapter,为了获取BluetoothAdapter,呼叫静态方法getDefaultAdapter()。这个会返回一个BluetoothAdapter,代表设备自己的蓝牙适配器(蓝牙无线电)。这个蓝牙适配器应用于整个系统中,你的应用可以通过这个对象进行交互。如果getDefaultAdapter()返回null,则这个设备不支持蓝牙。例如:
BluetoothAdapter mBluetoothAdapter= BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter== null){
// Device does not support Bluetooth
}
2.打开蓝牙
其次。你需要确定蓝牙能够使用。通过isEnabled()来检查蓝牙当前是否可用。如果这个方法返回false,则蓝牙不能够使用。为了请求蓝牙使用,呼叫startActivityForResult()与的ACTION_REQUEST_ENABLE动作意图。通过系统设置中启用蓝牙将发出一个请求(不停止蓝牙应用)。例如:
if(mBluetoothAdapter.isEnabled()){
Intent enableBtIntent= new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}
![]
对话框中显示请求使用蓝牙权限。如果响应"Yes",这个进程完成(或失败)后你的应用将能够使用蓝牙。
REQUEST_ENABLE_BT常量作为一个整型传到startActivityForResult()中(值必须大于0),该系统传回给你,在你onActivityResult()作为实现的requestCode参数。
如果调用蓝牙成功,你的Activity就会在onActivityResult()中收到RESULT_OK结果,如果蓝牙不能使用由于错误(或用户响应“NO”那么结果返回RESULT_CANCELED。
除了通过onActivityResult(),还可以通过监听ACTION_STATE_CHANGED这个broadcast Intent来知道蓝牙状态是否改变。这个Intent包含EXTRA_STATE,EXTRA_PREVIOUS_STATE两个字段,分别代表新旧状态。可能的值是STATE_TURNING_ON, STATE_ON, STATE_TURNING_OFF,还有STATE_OFF。
小贴: Enabling discoverability将自动启用蓝牙。如果您计划执行蓝牙活动之前,始终使设备可发现,你可以跳过上面的步骤2。参阅enabling discoverability。
搜索设备
使用BluetoothAdapter可以通过设备搜索或查询配对设备找到远程Bluetooth设备。
Device discovery(设备搜索)是一个扫描搜索本地已使能Bluetooth设备并且从搜索到的设备请求一些信息的过程(有时候会收到类似“discovering”,“inquiring”或“scanning”)。但是,搜索到的本地Bluetooth设备只有在打开被发现功能后才会响应一个discovery请求,响应的信息包括设备名,类,唯一的MAC地址。发起搜寻的设备可以使用这些信息来初始化跟被发现的设备的连接。
一旦与远程设备的第一次连接被建立,一个pairing请求就会自动提交给用户。如果设备已配对,配对设备的基本信息(名称,类,MAC地址)就被保存下来了,能够使用Bluetooth API来读取这些信息。使用已知的远程设备的MAC地址,连接可以在任何时候初始化而不必先完成搜索(当然这是假设远程设备是在可连接的空间范围内)。
需要记住,配对和连接是两个不同的概念:
配对意思是两个设备相互意识到对方的存在,共享一个用来鉴别身份的链路键(link-key),能够与对方建立一个加密的连接。
连接意思是两个设备现在共享一个RFCOMM信道,能够相互传输数据。
目前Android Bluetooth API's要求设备在建立RFCOMM信道前必须配对(配对是在使用Bluetooth API初始化一个加密连接时自动完成的)。
下面描述如何查询已配对设备,搜索新设备。
注意:Android的电源设备默认是不能被发现的。用户可以通过系统设置让它在有限的时间内可以被发现,或者可以在应用程序中要求用户使能被发现功能。
查找匹配设备
在搜索设备前,查询配对设备看需要的设备是否已经是已经存在是很值得的,可以调用getBondedDevices()来做到,该函数会返回一个描述配对设备BluetoothDevice的结果集。例如,可以使用ArrayAdapter查询所有配对设备然后显示所有设备名给用户:
Set<BluetoothDevice> pairedDevices= mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if(pairedDevices.size()> 0){
// Loop through paired devices
for(BluetoothDevice device: pairedDevices){
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName()+"n"+ device.getAddress());
}
};
BluetoothDevice对象中需要用来初始化一个连接唯一需要用到的信息就是MAC地址。