Android提高第十三篇之探秘蓝牙隐藏API
本文来自http://blog.csdn.net/hellogv/,引用必须注明出处!
上次讲解Android的蓝牙基本用法,这次讲得深入些,探讨下蓝牙方面的隐藏API。用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出,那么如何去使用这两项功能呢?本文利用JAVA的反射机制去调用这两项功能对应的函数:createBond和removeBond,具体的发掘和实现步骤如下:
1.使用Git工具下载platform/packages/apps/Settings.git,在Setting源码中查找关于建立配对和解除配对的API,知道这两个API的宿主(BluetoothDevice);
2.使用反射机制对BluetoothDevice枚举其所有方法和常量,看看是否存在:
view plain print ?
- staticpublicvoidprintAllInform(ClassclsShow){
- try{
- //取得所有方法
- Method[]hideMethod=clsShow.getMethods();
- inti=0;
- for(;i<hideMethod.length;i++){
- Log.e("methodname",hideMethod[i].getName());
- }
- //取得所有常量
- 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();
- }
- }
结果如下:
11-29 09:19:12.012: method name(452): cancelBondProcess
11-29 09:19:12.020: method name(452): cancelPairingUserInput
11-29 09:19:12.020: method name(452): createBond
11-29 09:19:12.020: method name(452): createInsecureRfcommSocket
11-29 09:19:12.027: method name(452): createRfcommSocket
11-29 09:19:12.027: method name(452): createRfcommSocketToServiceRecord
11-29 09:19:12.027: method name(452): createScoSocket
11-29 09:19:12.027: method name(452): describeContents
11-29 09:19:12.035: method name(452): equals
11-29 09:19:12.035: method name(452): fetchUuidsWithSdp
11-29 09:19:12.035: method name(452): getAddress
11-29 09:19:12.035: method name(452): getBluetoothClass
11-29 09:19:12.043: method name(452): getBondState
11-29 09:19:12.043: method name(452): getName
11-29 09:19:12.043: method name(452): getServiceChannel
11-29 09:19:12.043: method name(452): getTrustState
11-29 09:19:12.043: method name(452): getUuids
11-29 09:19:12.043: method name(452): hashCode
11-29 09:19:12.043: method name(452): isBluetoothDock
11-29 09:19:12.043: method name(452): removeBond
11-29 09:19:12.043: method name(452): setPairingConfirmation
11-29 09:19:12.043: method name(452): setPasskey
11-29 09:19:12.043: method name(452): setPin
11-29 09:19:12.043: method name(452): setTrust
11-29 09:19:12.043: method name(452): toString
11-29 09:19:12.043: method name(452): writeToParcel
11-29 09:19:12.043: method name(452): convertPinToBytes
11-29 09:19:12.043: method name(452): getClass
11-29 09:19:12.043: method name(452): notify
11-29 09:19:12.043: method name(452): notifyAll
11-29 09:19:12.043: method name(452): wait
11-29 09:19:12.051: method name(452): wait
11-29 09:19:12.051: method name(452): wait
3.如果枚举发现API存在(SDK却隐藏),则自己实现调用方法:
view plain print ?
- /**
- *与设备配对参考源码:platform/packages/apps/Settings.git
- */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
- */
- staticpublicbooleancreateBond(ClassbtClass,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(ClassbtClass,BluetoothDevicebtDevice)throwsException{
- MethodremoveBondMethod=btClass.getMethod("removeBond");
- BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
- returnreturnValue.booleanValue();
- }
PS:SDK之所以不给出隐藏的API肯定有其原因,也许是出于安全性或者是后续版本兼容性的考虑,因此不能保证隐藏API能在所有Android平台上很好地运行。。。
本文程序运行效果如下:
main.xml源码如下:
view plain print ?
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:orientation="vertical"android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- <LinearLayoutandroid:id="@+id/LinearLayout01"
- android:layout_height="wrap_content"android:layout_width="fill_parent">
- <Buttonandroid:layout_height="wrap_content"android:id="@+id/btnSearch"
- android:text="Search"android:layout_width="160dip"></Button>
- <Buttonandroid:layout_height="wrap_content"
- android:layout_width="160dip"android:text="Show"android:id="@+id/btnShow"></Button>
- </LinearLayout>
- <LinearLayoutandroid:id="@+id/LinearLayout02"
- android:layout_width="wrap_content"android:layout_height="wrap_content"></LinearLayout>
- <ListViewandroid:id="@+id/ListView01"android:layout_width="fill_parent"
- android:layout_height="fill_parent">
- </ListView>
- </LinearLayout>
工具类ClsUtils.java源码如下:
view plain print ?
- packagecom.testReflect;
- importjava.lang.reflect.Field;
- importjava.lang.reflect.Method;
- importandroid.bluetooth.BluetoothDevice;
- importandroid.util.Log;
- publicclassClsUtils{
- /**
- *与设备配对参考源码:platform/packages/apps/Settings.git
- */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
- */
- staticpublicbooleancreateBond(ClassbtClass,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(ClassbtClass,BluetoothDevicebtDevice)throwsException{
- MethodremoveBondMethod=btClass.getMethod("removeBond");
- BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
- returnreturnValue.booleanValue();
- }
- /**
- *
- *@paramclsShow
- */
- staticpublicvoidprintAllInform(ClassclsShow){
- try{
- //取得所有方法
- Method[]hideMethod=clsShow.getMethods();
- inti=0;
- for(;i<hideMethod.length;i++){
- Log.e("methodname",hideMethod[i].getName());
- }
- //取得所有常量
- 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();
- }
- }
- }
主程序testReflect.java的源码如下:
view plain print ?
- packagecom.testReflect;
- importjava.util.ArrayList;
- importjava.util.List;
- importandroid.app.Activity;
- importandroid.bluetooth.BluetoothAdapter;
- importandroid.bluetooth.BluetoothDevice;
- importandroid.content.BroadcastReceiver;
- importandroid.content.Context;
- importandroid.content.Intent;
- importandroid.content.IntentFilter;
- importandroid.os.Bundle;
- importandroid.util.Log;
- importandroid.view.View;
- importandroid.widget.AdapterView;
- importandroid.widget.ArrayAdapter;
- importandroid.widget.Button;
- importandroid.widget.ListView;
- importandroid.widget.Toast;
- publicclasstestReflectextendsActivity{
- ButtonbtnSearch,btnShow;
- ListViewlvBTDevices;
- ArrayAdapter<String>adtDevices;
- List<String>lstDevices=newArrayList<String>();
- BluetoothDevicebtDevice;
- BluetoothAdapterbtAdapt;
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- btnSearch=(Button)this.findViewById(R.id.btnSearch);
- btnSearch.setOnClickListener(newClickEvent());
- btnShow=(Button)this.findViewById(R.id.btnShow);
- btnShow.setOnClickListener(newClickEvent());
- lvBTDevices=(ListView)this.findViewById(R.id.ListView01);
- adtDevices=newArrayAdapter<String>(testReflect.this,
- android.R.layout.simple_list_item_1,lstDevices);
- lvBTDevices.setAdapter(adtDevices);
- lvBTDevices.setOnItemClickListener(newItemClickEvent());
- btAdapt=BluetoothAdapter.getDefaultAdapter();//初始化本机蓝牙功能
- if(btAdapt.getState()==BluetoothAdapter.STATE_OFF)//开蓝牙
- btAdapt.enable();
- //注册Receiver来获取蓝牙设备相关的结果
- IntentFilterintent=newIntentFilter();
- intent.addAction(BluetoothDevice.ACTION_FOUND);
- intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
- registerReceiver(searchDevices,intent);
- }
- privateBroadcastReceiversearchDevices=newBroadcastReceiver(){
- publicvoidonReceive(Contextcontext,Intentintent){
- Stringaction=intent.getAction();
- Bundleb=intent.getExtras();
- Object[]lstName=b.keySet().toArray();
- //显示所有收到的消息及其细节
- for(inti=0;i<lstName.length;i++){
- StringkeyName=lstName[i].toString();
- Log.e(keyName,String.valueOf(b.get(keyName)));
- }
- //搜索设备时,取得设备的MAC地址
- if(BluetoothDevice.ACTION_FOUND.equals(action)){
- BluetoothDevicedevice=intent
- .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
- if(device.getBondState()==BluetoothDevice.BOND_NONE){
- Stringstr="未配对|"+device.getName()+"|"+device.getAddress();
- lstDevices.add(str);//获取设备名称和mac地址
- adtDevices.notifyDataSetChanged();
- }
- }
- }
- };
- classItemClickEventimplementsAdapterView.OnItemClickListener{
- @Override
- publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,
- longarg3){
- btAdapt.cancelDiscovery();
- Stringstr=lstDevices.get(arg2);
- String[]values=str.split("//|");
- Stringaddress=values[2];
- btDevice=btAdapt.getRemoteDevice(address);
- try{
- if(values[0].equals("未配对"))
- {
- Toast.makeText(testReflect.this,"由未配对转为已配对",500).show();
- ClsUtils.createBond(btDevice.getClass(),btDevice);
- }
- elseif(values[0].equals("已配对"))
- {
- Toast.makeText(testReflect.this,"由已配对转为未配对",500).show();
- ClsUtils.removeBond(btDevice.getClass(),btDevice);
- }
- }catch(Exceptione){
- //TODOAuto-generatedcatchblock
- e.printStackTrace();
- }
- }
- }
- /**
- *按键处理
- *@authorGV
- *
- */
- classClickEventimplementsView.OnClickListener{
- @Override
- publicvoidonClick(Viewv){
- if(v==btnSearch){//搜索附近的蓝牙设备
- lstDevices.clear();
- Object[]lstDevice=btAdapt.getBondedDevices().toArray();
- for(inti=0;i<lstDevice.length;i++){
- BluetoothDevicedevice=(BluetoothDevice)lstDevice[i];
- Stringstr="已配对|"+device.getName()+"|"+device.getAddress();
- lstDevices.add(str);//获取设备名称和mac地址
- adtDevices.notifyDataSetChanged();
- }
- //开始搜索
- setTitle("本机蓝牙地址:"+btAdapt.getAddress());
- btAdapt.startDiscovery();
- }
- elseif(v==btnShow){//显示BluetoothDevice的所有方法和常量,包括隐藏API
- ClsUtils.printAllInform(btDevice.getClass());
- }
- }
- }
- }
更多相关文章
- Android提高十六篇之使用NDK把彩图转换灰度图
- 实时监控Android设备网络封包
- android 简单按键修改
- Android(安卓)各版本新特性
- 【Android应用开发】-(19)Android(安卓)串口编程原理和实现方式(附
- 如何成为 Android(安卓)开发高手?
- Android中关于dip和px以及转换的总结(重点推荐文章)
- Android(安卓)IntentService完全解析 当Service遇到Handler
- Xamarin发布XobotOS源码,C# 实现的Android系统 - 操作系统 - ITey