android 蓝牙搜索、配对连接通信总结
2015-01-31 19:20
344 查看
蓝牙协议可以实现一个蓝牙设备和6到8个蓝牙设备进行通信。
1、蓝牙搜索的实现
利用蓝牙的发现和完成动作动态注册广播接受者获得蓝牙设备。
第一步,获得蓝牙适配器
<spanstyle="white-space:pre"> </span>if(!mAdapter.isEnabled()){
<spanstyle="white-space:pre"> </span>mAdapter.enable();
第二步动态注册蓝牙搜索广播接收者
IntentFilterfilter=newIntentFilter(BluetoothDevice.ACTION_FOUND);
this.registerReceiver(mReceiver,filter);
//Registerforbroadcastswhendiscoveryhasfinished
filter=newIntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
this.registerReceiver(mReceiver,filter);
并且可以利用意图过滤器设置广播的优先级
对应的广播接收者:
//changesthetitlewhendiscoveryisfinished
privatefinalBroadcastReceivermReceiver=newBroadcastReceiver(){
@Override
publicvoidonReceive(Contextcontext,Intentintent){
Stringaction=intent.getAction();
//Whendiscoveryfindsadevice
if(BluetoothDevice.ACTION_FOUND.equals(action)){
//GettheBluetoothDeviceobjectfromtheIntent
BluetoothDevicedevice=intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//Ifit'salreadypaired,skipit,becauseit'sbeenlistedalready
if(device.getBondState()!=BluetoothDevice.BOND_BONDED){
mNewDevicesArrayAdapter.add(device.getName()+"\n"+device.getAddress());
}
//Whendiscoveryisfinished,changetheActivitytitle
}elseif(BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)){
setProgressBarIndeterminateVisibility(false);
setTitle(R.string.select_device);
if(mNewDevicesArrayAdapter.getCount()==0){
StringnoDevices=getResources().getText(R.string.none_found).toString();
mNewDevicesArrayAdapter.add(noDevices);
}
}
}
};
或者利用发现和完成动作定义两个广播接受者,在完成的动作中注销广播接收者。
关键代码如下:
****当搜索蓝牙设备完成时调用
*/
privateBroadcastReceiver_foundReceiver=newBroadcastReceiver(){
publicvoidonReceive(Contextcontext,Intentintent){
BluetoothDevicedevice=intent
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
//将结果添加到列表中
_devices.add(device);
DeviceInfoinfo=newDeviceInfo();
info.setmDeviceName(device.getName());
info.setmDeviceMacAddr(device.getAddress());
infos.add(info);
info=null;
//显示列表
showDevices();
}
};
privateBroadcastReceiver_discoveryReceiver=newBroadcastReceiver(){
@Override
publicvoidonReceive(Contextcontext,Intentintent){
//卸载注册的***
unregisterReceiver(_foundReceiver);
unregisterReceiver(this);
_discoveryFinished=true;
}
};
这样便完成蓝牙的搜索了。
2、蓝牙配对
蓝牙要想通信目前是必须要先配对才能连接的。
蓝牙配对的api是hide的。但是api19可以直接调用蓝牙设备的配对方法。
所以配对都是利用反射的方法。这里有一个强大的工具类可以直接拿来使用,如下:
publicClsUtils(){
//TODOAuto-generatedconstructorstub
}
/**
*与设备配对参考源码:platform/packages/apps/Settings.git
*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
staticpublicbooleancreateBond(Class<?extendsBluetoothDevice>btClass,BluetoothDevicebtDevice)
throwsException
{
MethodcreateBondMethod=btClass.getMethod("createBond");
BooleanreturnValue=(Boolean)createBondMethod.invoke(btDevice);
returnreturnValue.booleanValue();
}
/**
*与设备解除配对参考源码:platform/packages/apps/Settings.git
*/Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
*/
staticpublicbooleanremoveBond(Class<?extendsBluetoothDevice>btClass,BluetoothDevicebtDevice)
throwsException
{
MethodremoveBondMethod=btClass.getMethod("removeBond");
BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
returnreturnValue.booleanValue();
}
staticpublicbooleansetPin(ClassbtClass,BluetoothDevicebtDevice,
Stringstr)throwsException
{
try
{
MethodremoveBondMethod=btClass.getDeclaredMethod("setPin",
newClass[]
{byte[].class});
BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice,
newObject[]
{str.getBytes()});
Log.e("returnValue设置密码",""+returnValue.booleanValue());
returnreturnValue.booleanValue();
}
catch(SecurityExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(IllegalArgumentExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
returnfalse;
}
//取消用户输入
staticpublicbooleancancelPairingUserInput(Class<?>btClass,
BluetoothDevicedevice)
throwsException
{
MethodcreateBondMethod=btClass.getMethod("cancelPairingUserInput");
cancelBondProcess(btClass,device);
BooleanreturnValue=(Boolean)createBondMethod.invoke(device);
Log.i("取消对话框","cancelPairingUserInput"+returnValue.booleanValue());
returnreturnValue.booleanValue();
}
//取消配对
staticpublicbooleancancelBondProcess(Class<?>btClass,
BluetoothDevicedevice)
throwsException
{
MethodcreateBondMethod=btClass.getMethod("cancelBondProcess");
BooleanreturnValue=(Boolean)createBondMethod.invoke(device);
returnreturnValue.booleanValue();
}
/**
*
*@paramclsShow
*/
staticpublicvoidprintAllInform(Class<?>clsShow)
{
try
{
//取得所有方法
Method[]hideMethod=clsShow.getMethods();
inti=0;
for(;i<hideMethod.length;i++)
{
Log.e("methodname",hideMethod[i].getName()+";andtheiis:"
+i);
}
//取得所有常量
Field[]allFields=clsShow.getFields();
for(i=0;i<allFields.length;i++)
{
Log.e("Fieldname",allFields[i].getName());
}
}
catch(SecurityExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(IllegalArgumentExceptione)
{
//thrownewRuntimeException(e.getMessage());
e.printStackTrace();
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
staticpublicbooleanpair(StringstrAddr,StringstrPsw)
{
booleanresult=false;
BluetoothAdapterbluetoothAdapter=BluetoothAdapter
.getDefaultAdapter();
bluetoothAdapter.cancelDiscovery();
if(!bluetoothAdapter.isEnabled())
{
bluetoothAdapter.enable();
}
BluetoothDevicedevice=bluetoothAdapter.getRemoteDevice(strAddr);
if(device.getBondState()!=BluetoothDevice.BOND_BONDED)
{
try
{
Log.d("mylog","NOTBOND_BONDED");
booleanflag1=ClsUtils.setPin(device.getClass(),device,strPsw);//手机和蓝牙采集器配对
booleanflag2=ClsUtils.createBond(device.getClass(),device);
//remoteDevice=device;//配对完毕就把这个设备对象传给全局的remoteDevice
result=true;
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
Log.d("mylog","setPiNfailed!");
e.printStackTrace();
}//
}
else
{
Log.d("mylog","HASBOND_BONDED");
try
{
ClsUtils.removeBond(device.getClass(),device);
//ClsUtils.createBond(device.getClass(),device);
booleanflag1=ClsUtils.setPin(device.getClass(),device,strPsw);//手机和蓝牙采集器配对
booleanflag2=ClsUtils.createBond(device.getClass(),device);
//remoteDevice=device;//如果绑定成功,就直接把这个设备对象传给全局的remoteDevice
result=true;
}
catch(Exceptione)
{
//TODOAuto-generatedcatchblock
Log.d("mylog","setPiNfailed!");
e.printStackTrace();
}
}
returnresult;
}
}
蓝牙配对的关键代码:
其中device是蓝牙设备。在配对的时候会有一个配对广播,可以自定义一个广播接受者获取配对广播,然后在这个广播接收者里设置pin值,取消确定对话框,实现自动配对。关键代码如下:
IntentFilterfilter=newIntentFilter();
filter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
filter.setPriority(Integer.MAX_VALUE);
registerReceiver(mReceiver,filter);
@Override
publicvoidonReceive(Contextcontext,Intentintent){
BluetoothDevicebtDevice=mAdapter.getRemoteDevice("EC:89:F5:98:46:f9");
try{
setPin(btDevice.getClass(),btDevice,"000000");
cancelPairingUserInput(btDevice.getClass(),btDevice);
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
在我的4.2系统上是没有效果的。找了一个上午的资料;网上给出了两种解决方法:(1)修改setting系统源码,(2)模拟点击事件。
蓝牙配对完成后就可以连接通信了。
3、蓝牙通信
蓝牙同时的本质是蓝牙套接字,一个主动发起连接的的设备做客户端,一个监听连接的设备做服务端,类似sokcet网络编程,利用多线程,读取数据流就可完成蓝牙通信。
如下是蓝牙串口通信的关键代码:
*建立连接并通信
*
*@parambtDev
*@return
*/
privatebooleanconnect(BluetoothDevicebtDev){
booleanflag=false;
try{
/*if(btDev.fetchUuidsWithSdp()){
btDev.getUuids();
}*/
//建立连接
mSocket=btDev
.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
mSocket.connect();
mOutputStream=mSocket.getOutputStream();
mInputStream=mSocket.getInputStream();
mOutputStream.write("StartOnNet\n".getBytes());
mOutputStream.flush();
flag=true;
}catch(Exceptione){
}
如下蓝牙服务端关键代码:
privateInputStreammInputStream;
privateOutputStreammOutputStream;
publicServerThread(){
}
@Override
publicvoidrun(){
try{
while(true){
mBluetoothServerSocket=mAdapter
.listenUsingRfcommWithServiceRecord(
"btspp",
UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"));
Log.i("服务端线程运行","蓝牙服务端线程开始");
Log.i("服务端线程运行","蓝牙服务端线程阻塞中");
mBluetoothSocket=mBluetoothServerSocket.accept();
if(mBluetoothSocket!=null){
break;
}
}
Log.i("服务端线程运行","蓝牙服务端线程<<<<<<<<<<<<<");
mInputStream=mBluetoothSocket.getInputStream();
mOutputStream=mBluetoothSocket.getOutputStream();
byte[]data=getSocketResult(mInputStream);
StringtempString=newString(data);
Log.i("蓝牙服务端监听str",tempString);
//向客户端发送数据
if(tempString.equals("StartOnNet\n")){
mOutputStream.write("haha".getBytes());
mOutputStream.flush();
if(!isServiceRunning("com.yqq.endClient3.service.GpsInfoCollectionService",BluethoothServer.this)){
//开启GPS收集服务
gpsService=newIntent(BluethoothServer.this,
GpsInfoCollectionService.class);
Log.i("蓝牙服务端监听<<<<<<<<<<<<<<<<<<<<<<","<<<<<<<<<<<<<<<<<");
startService(gpsService);
}
}
}catch(Exceptione){
//TODO:handleexception
}finally{
if(mInputStream!=null){
try{
mInputStream.close();
mInputStream=null;
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
if(mInputStream!=null){
try{
mOutputStream.close();
mOutputStream=null;
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
if(mBluetoothSocket!=null){
try{
mBluetoothSocket.close();
mBluetoothSocket=null;
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
if(mBluetoothServerSocket!=null){
try{
mBluetoothServerSocket.close();
mBluetoothServerSocket=null;
Looper.prepare();
Messagemessage=Message.obtain();
message.what=0x123456;
mHandler.sendMessage(message);
Looper.loop();
}catch(IOExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}
}
}
}
}
相关文章推荐
- android 蓝牙搜索、配对连接通信总结
- Android 蓝牙开发之搜索、配对、连接、通信大全
- Android 蓝牙开发之搜索、配对、连接、通信大全
- Android 蓝牙开发之搜索、配对、连接、通信大全
- [置顶] Android 蓝牙开发之搜索、配对、连接、通信大全
- Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(二)
- android bluetooth——蓝牙的开启、搜索、配对与连接
- android bluetooth——蓝牙的开启、搜索、配对与连接
- android bluetooth——蓝牙的开启、搜索、配对与连接
- Android 6.0后蓝牙的开发,搜索,配对,连接发送数据等(一)
- android bluetooth——蓝牙的开启、搜索、配对与连接
- Android蓝牙设备的配对,连接,搜索
- android开发之蓝牙初步 扫描已配对蓝牙、更改蓝牙可见性、搜索外部蓝牙设备
- Android系统中蓝牙设备间连接和通信
- Android 蓝牙设备通讯的开发(配对/连接/传输数据)
- 如何实现android蓝牙开发 自动配对连接,并不弹出提示框
- android开发之蓝牙主动配对连接手机
- Android BLE与终端通信(二)——Android Bluetooth基础科普以及搜索蓝牙设备显示列表
- 如何实现android蓝牙开发 自动配对连接,并不弹出提示框
- android开发之蓝牙主动配对连接手机