Android Bluetooth 蓝牙设备之间自动配对.docx_第1页
Android Bluetooth 蓝牙设备之间自动配对.docx_第2页
Android Bluetooth 蓝牙设备之间自动配对.docx_第3页
Android Bluetooth 蓝牙设备之间自动配对.docx_第4页
Android Bluetooth 蓝牙设备之间自动配对.docx_第5页
已阅读5页,还剩10页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

Android Bluetooth 学习(3)蓝牙设备之间自动配对0人收藏此文章,我要收藏发表于6个月前(2013-03-21 12:01) , 已有654次阅读 ,共0个评论前言(android2.3版本,4.0版本由于是随机获取pin值,没有研究过): 1、蓝牙设备之间自动配对,需要两个设备都安装进行配对的apk(网上好多自动配对的帖子都没有说明情况) 2、在自动匹配的时候想通过反射调用BluetoothDevice的setPin、createBond、cancelPairingUserInput实现设置密钥、配对请求创建、取消密钥信息输入等。 1)createBond()创建,最终会调到源码的BluetoothService的createBond(String address)方法,通过对源码浅显的了解,createBond主要是写入匹配密钥(BluetoothService的writeDockPin()以及进入jni注册回调函数onCreatePairedDeviceResult观察匹配结果比如: / Pins did not match, or remote device did not respond to pin / request in time/ We rejected pairing, or the remote side rejected pairing. This / happens if either side presses cancel at the pairing dialog./ Not sure if this happens/ Other device is not responding at all/ already bonded等,在jni中创建了进行匹配的device(CreatePairedDevice),这时bluetooth会发送一个ACTION_PAIRING_REQUEST的广播,只有当前会出现密钥框的蓝牙设备收到。写完密钥之后,发送广播给另外一个蓝牙设备接收,然后打开密钥输入框进行匹配。 2)setPin()设置密钥,通过查看setting源码,发现在确认输入密钥之后会调用setPin()(如果点取消,就会调用cancelPairingUserInput,取消密钥框),setPin具体通过D-BUS做了什么没有去深究,但是在调用setPin的时候会remove掉一个map里面的键值对(address:int),也就是我们在调用setPin之后如果再去调用onCreatePairedDeviceResult,则该方法一定返回false,并且出现下面的打印提示:cancelUserInputNative(B8:FF:FE:55:EF:D6) called but no native data available, ignoring. Maybe the PasskeyAgent Request was already cancelled by the remote or by bluez.(因为该方法也会remove掉一个键值对)3)cancelPairingUserInput()取消用户输入密钥框,个人觉得一般情况下不要和setPin(setPasskey、setPairingConfirmation、setRemoteOutOfBandData)一起用,这几个方法都会remove掉map里面的key:value(也就是互斥的)。 3、蓝牙耳机、手柄等一些无法手动配置的设备是如何完成自动配对的。 在源码里面有一个自动配对的方法,也就是把pin值自动设为“0000”1/*package*/synchronized boolean attemptAutoPair(String address) 2if(!mBondState.hasAutoPairingFailed(address) &3!mBondState.isAutoPairingBlacklisted(address) 4mBondState.attempt(address);5setPin(address, BluetoothDevice.convertPinToBytes(0000);6returntrue;78returnfalse;9该方法是在底层回调到java层的onRequestPinCode方法时被调用,首先Check if its a dock(正常输入的密钥,走正常配对方式,双方输入匹配值),然后再try 0000 once if the device looks dumb(涉及到Device.AUDIO_VIDEO相关部分如:耳机,免提等进入自动匹配模式)进行自动配对。言归正传,虽然个人觉得自动配对需要双方乃至多方蓝牙设备都需要装上实现自动配对的apk,已经失去了自动配对的意义,但有可能还是会派上用场。下面我们看看现实情况的自动配对是什么样的吧。由于BluetoothDevice配对的方法都是hide的,所以我们需要通过反射调用被隐藏的方法,现在基本都是通用的工具类型了,网上模式基本一样。ClsUtils.java001packagecn.bluetooth;002003importjava.lang.reflect.Field;004importjava.lang.reflect.Method;005importandroid.bluetooth.BluetoothAdapter;006importandroid.bluetooth.BluetoothDevice;007importandroid.util.Log;008publicclassClsUtils009010publicstaticBluetoothDevice remoteDevice=null;011/*012* 与设备配对 参考源码:platform/packages/apps/Settings.git013* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java014*/015SuppressWarnings(unchecked)016staticpublicbooleancreateBond(SuppressWarnings(rawtypes) Class btClass, BluetoothDevice btDevice)017throwsException018019Method createBondMethod = btClass.getMethod(createBond);020Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);021returnreturnValue.booleanValue();022023024/*025* 与设备解除配对 参考源码:platform/packages/apps/Settings.git026* /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java027*/028SuppressWarnings(unchecked)029staticpublicbooleanremoveBond(Class btClass, BluetoothDevice btDevice)030throwsException031032Method removeBondMethod = btClass.getMethod(removeBond);033Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);034returnreturnValue.booleanValue();035036037SuppressWarnings(unchecked)038staticpublicbooleansetPin(Class btClass, BluetoothDevice btDevice,039String str)throwsException040041try042043Method removeBondMethod = btClass.getDeclaredMethod(setPin,044newClass045byte.class);046Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice,047newObject048str.getBytes();049Log.d(returnValue,setPin is success +btDevice.getAddress()+ returnValue.booleanValue();050051catch(SecurityException e)052053/ throw new RuntimeException(e.getMessage();054e.printStackTrace();055056catch(IllegalArgumentException e)057058/ throw new RuntimeException(e.getMessage();059e.printStackTrace();060061catch(Exception e)062063/ TODO Auto-generated catch block064e.printStackTrace();065066returntrue;067068069070/ 取消用户输入071SuppressWarnings(unchecked)072staticpublicbooleancancelPairingUserInput(Class btClass,073BluetoothDevice device)074075throwsException076077Method createBondMethod = btClass.getMethod(cancelPairingUserInput);078/ cancelBondProcess()079Boolean returnValue = (Boolean) createBondMethod.invoke(device);080Log.d(returnValue,cancelPairingUserInput is success + returnValue.booleanValue();081returnreturnValue.booleanValue();082083084/ 取消配对085SuppressWarnings(unchecked)086staticpublicbooleancancelBondProcess(Class btClass,087BluetoothDevice device)088089throwsException090091Method createBondMethod = btClass.getMethod(cancelBondProcess);092Boolean returnValue = (Boolean) createBondMethod.invoke(device);093returnreturnValue.booleanValue();094095096/*097*098* param clsShow099*/100SuppressWarnings(unchecked)101staticpublicvoidprintAllInform(Class clsShow)102103try104105/ 取得所有方法106Method hideMethod = clsShow.getMethods();107inti =0;108for(; i hideMethod.length; i+)109110/Log.e(method name, hideMethod.getName() + ;and the i is:111/ + i);112113/ 取得所有常量114Field allFields = clsShow.getFields();115for(i =0; i allFields.length; i+)116117/Log.e(Field name, allFields.getName();118119120catch(SecurityException e)121122/ throw new RuntimeException(e.getMessage();123e.printStackTrace();124125catch(IllegalArgumentException e)126127/ throw new RuntimeException(e.getMessage();128e.printStackTrace();129130catch(Exception e)131132/ TODO Auto-generated catch block133e.printStackTrace();134135136Bluetooth1.java主activity,所有界面操作实现地方001packagecn.bluetooth;002importjava.io.IOException;003importjava.util.ArrayList;004importjava.util.List;005006importandroid.app.Activity;007importandroid.bluetooth.BluetoothAdapter;008importandroid.bluetooth.BluetoothDevice;009importandroid.bluetooth.BluetoothSocket;010importandroid.content.BroadcastReceiver;011importandroid.content.Context;012importandroid.content.Intent;013importandroid.content.IntentFilter;014importandroid.os.Bundle;015importandroid.util.Log;016importandroid.view.Menu;017importandroid.view.View;018importandroid.widget.AdapterView;019importandroid.widget.ArrayAdapter;020importandroid.widget.Button;021importandroid.widget.ListView;022importandroid.widget.Toast;023importandroid.widget.ToggleButton;024publicclassBluetooth1extendsActivity 025/* Called when the activity is first created. */026Button btnSearch, btnDis, btnExit;027ToggleButton tbtnSwitch;028ListView lvBTDevices;029ArrayAdapter adtDevices;030List lstDevices =newArrayList();031BluetoothAdapter btAdapt;032publicstaticBluetoothSocket btSocket;033Override034publicvoidonCreate(Bundle savedInstanceState) 035super.onCreate(savedInstanceState);036setContentView(R.layout.main);037/ Button 设置038btnSearch = (Button)this.findViewById(R.id.btnSearch);039btnSearch.setOnClickListener(newClickEvent();040btnExit = (Button)this.findViewById(R.id.btnExit);041btnExit.setOnClickListener(newClickEvent();042btnDis = (Button)this.findViewById(R.id.btnDis);043btnDis.setOnClickListener(newClickEvent();044045/ ToogleButton设置046tbtnSwitch = (ToggleButton)this.findViewById(R.id.tbtnSwitch);047tbtnSwitch.setOnClickListener(newClickEvent();048049/ ListView及其数据源 适配器050lvBTDevices = (ListView)this.findViewById(R.id.lvDevices);051adtDevices =newArrayAdapter(this,052android.R.layout.simple_list_item_1, lstDevices);053lvBTDevices.setAdapter(adtDevices);054lvBTDevices.setOnItemClickListener(newItemClickEvent();055056btAdapt = BluetoothAdapter.getDefaultAdapter();/ 初始化本机蓝牙功能057058/ =059/ modified by wiley060/*061* if (btAdapt.getState() = BluetoothAdapter.STATE_OFF)/ 读取蓝牙状态并显示062* tbtnSwitch.setChecked(false); else if (btAdapt.getState() =063* BluetoothAdapter.STATE_ON) tbtnSwitch.setChecked(true);064*/065if(btAdapt.isEnabled() 066tbtnSwitch.setChecked(false);067else068tbtnSwitch.setChecked(true);069070/ =071/ 注册Receiver来获取蓝牙设备相关的结果072IntentFilter intent =newIntentFilter();073intent.addAction(BluetoothDevice.ACTION_FOUND);/ 用BroadcastReceiver来取得搜索结果074intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);075intent.addAction(BluetoothAdapter.ACTION_SCAN_MODE_CHANGED);076intent.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);077registerReceiver(searchDevices, intent);078079080privatefinalBroadcastReceiver searchDevices =newBroadcastReceiver() 081Override082publicvoidonReceive(Context context, Intent intent) 083084String action = intent.getAction();085Bundle b = intent.getExtras();086Object lstName = b.keySet().toArray();087088/ 显示所有收到的消息及其细节089for(inti =0; i lstName.length; i+) 090String keyName = lstName.toString();091Log.e(keyName, String.valueOf(b.get(keyName);092093BluetoothDevice device =null;094/ 搜索设备时,取得设备的MAC地址095if(BluetoothDevice.ACTION_FOUND.equals(action) 096device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);097if(device.getBondState() = BluetoothDevice.BOND_NONE) 098String str = 未配对|+ device.getName() +|099+ device.getAddress();100if(lstDevices.indexOf(str) = -1)/ 防止重复添加101lstDevices.add(str);/ 获取设备名称和mac地址102adtDevices.notifyDataSetChanged();103104elseif(BluetoothDevice.ACTION_BOND_STATE_CHANGED.equals(action)105device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);106107switch(device.getBondState() 108caseBluetoothDevice.BOND_BONDING:109Log.d(BlueToothTestActivity,正在配对.);110break;111caseBluetoothDevice.BOND_BONDED:112Log.d(BlueToothTestActivity,完成配对);113/connect(device);/连接设备114break;115caseBluetoothDevice.BOND_NONE:116Log.d(BlueToothTestActivity,取消配对);117default:118break;119120121122123;124125Override126protectedvoidonDestroy() 127this.unregisterReceiver(searchDevices);128super.onDestroy();129android.os.Process.killProcess(android.os.Process.myPid();130131132classItemClickEventimplementsAdapterView.OnItemClickListener 133134Override135publicvoidonItemClick(AdapterView arg0, View arg1,intarg2,136longarg3) 137if(btAdapt.isDiscovering()btAdapt.cancelDiscovery();138String str = lstDevices.get(arg2);139String values = str.split(|);140String address = values2;141Log.e(address, values2);142BluetoothDevice btDev = btAdapt.getRemoteDevice(address);143try144Boolean returnValue =false;145if(btDev.getBondState() = BluetoothDevice.BOND_NONE) 146Toast.makeText(Bluetooth1.this,远程设备发送蓝牙配对请求,5000).show();147/这里只需要createBond就行了148ClsUtils.createBond(btDev.getClass(), btDev);149elseif(btDev.getBondState() = BluetoothDevice.BOND_BONDED)150Toast.makeText(Bluetooth1.this, btDev.getBondState()+ .正在连接.,1000).show();151152catch(Exception e) 153e.printStackTrace();154155156157classClickEventimplementsView.OnClickListener 158Override159publicvoidonClick(View v) 160if(v = btnSearch)/ 搜索蓝牙设备,在BroadcastReceiver显示结果161162if(btAdapt.getState() = BluetoothAdapter.STATE_OFF) / 如果蓝牙还没开启163Toast.makeText(Bluetooth1.this,请先打开蓝牙,1000)164.show();165return;166167if(btAdapt.isDiscovering()168btAdapt.cancelDiscovery();169lstDevices.clear();170Object lstDevice = btAdapt.getBondedDevices().toArray();171for(inti =0; i lstDevice.length; i+) 172BluetoothDevice device = (BluetoothDevice) lstDevicei;173String str = 已配对|+ device.getName() +|174+ device.getAddress();175lstDevices.add(str);/ 获取设备名称和mac地址176adtDevices.notifyDataSetChanged();177178setTitle(本机:+ btAdapt.getAddress();179btAdapt.startDiscovery();180elseif(v = tbtnSwitch) / 本机蓝牙启动/关闭181if(tbtnSwitch.isChecked() =false)182btAdapt.enable();183184elseif(tbtnSwitch.isChecked() =true)185btAdapt.disable();186187elseif(v = btnDis)/ 本机可以被搜索188189Intent discoverableIntent =newIntent(190BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);191discoverableIntent.putExtra(192BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION,300);193startActivity(discoverableIntent);194elseif(v = btnExit) 195try196if(btSocket !=null)197btSocket.close();198catch(IOException e) 199e.printStackTrace();200201Bluetooth1.this.finish();202203204205Override206publicbooleanonCreateOptionsMenu

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论