本文来自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 ?
  1. staticpublicvoidprintAllInform(ClassclsShow){
  2. try{
  3. //取得所有方法
  4. Method[]hideMethod=clsShow.getMethods();
  5. inti=0;
  6. for(;i<hideMethod.length;i++){
  7. Log.e("methodname",hideMethod[i].getName());
  8. }
  9. //取得所有常量
  10. Field[]allFields=clsShow.getFields();
  11. for(i=0;i<allFields.length;i++){
  12. Log.e("Fieldname",allFields[i].getName());
  13. }
  14. }catch(SecurityExceptione){
  15. //thrownewRuntimeException(e.getMessage());
  16. e.printStackTrace();
  17. }catch(IllegalArgumentExceptione){
  18. //thrownewRuntimeException(e.getMessage());
  19. e.printStackTrace();
  20. }catch(Exceptione){
  21. //TODOAuto-generatedcatchblock
  22. e.printStackTrace();
  23. }
  24. }

结果如下:

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 ?
  1. /**
  2. *与设备配对参考源码:platform/packages/apps/Settings.git
  3. */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  4. */
  5. staticpublicbooleancreateBond(ClassbtClass,BluetoothDevicebtDevice)throwsException{
  6. MethodcreateBondMethod=btClass.getMethod("createBond");
  7. BooleanreturnValue=(Boolean)createBondMethod.invoke(btDevice);
  8. returnreturnValue.booleanValue();
  9. }
  10. /**
  11. *与设备解除配对参考源码:platform/packages/apps/Settings.git
  12. */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  13. */
  14. staticpublicbooleanremoveBond(ClassbtClass,BluetoothDevicebtDevice)throwsException{
  15. MethodremoveBondMethod=btClass.getMethod("removeBond");
  16. BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
  17. returnreturnValue.booleanValue();
  18. }

PS:SDK之所以不给出隐藏的API肯定有其原因,也许是出于安全性或者是后续版本兼容性的考虑,因此不能保证隐藏API能在所有Android平台上很好地运行。。。

本文程序运行效果如下:

main.xml源码如下:

view plain print ?
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical"android:layout_width="fill_parent"
  4. android:layout_height="fill_parent">
  5. <LinearLayoutandroid:id="@+id/LinearLayout01"
  6. android:layout_height="wrap_content"android:layout_width="fill_parent">
  7. <Buttonandroid:layout_height="wrap_content"android:id="@+id/btnSearch"
  8. android:text="Search"android:layout_width="160dip"></Button>
  9. <Buttonandroid:layout_height="wrap_content"
  10. android:layout_width="160dip"android:text="Show"android:id="@+id/btnShow"></Button>
  11. </LinearLayout>
  12. <LinearLayoutandroid:id="@+id/LinearLayout02"
  13. android:layout_width="wrap_content"android:layout_height="wrap_content"></LinearLayout>
  14. <ListViewandroid:id="@+id/ListView01"android:layout_width="fill_parent"
  15. android:layout_height="fill_parent">
  16. </ListView>
  17. </LinearLayout>

工具类ClsUtils.java源码如下:

view plain print ?
  1. packagecom.testReflect;
  2. importjava.lang.reflect.Field;
  3. importjava.lang.reflect.Method;
  4. importandroid.bluetooth.BluetoothDevice;
  5. importandroid.util.Log;
  6. publicclassClsUtils{
  7. /**
  8. *与设备配对参考源码:platform/packages/apps/Settings.git
  9. */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  10. */
  11. staticpublicbooleancreateBond(ClassbtClass,BluetoothDevicebtDevice)throwsException{
  12. MethodcreateBondMethod=btClass.getMethod("createBond");
  13. BooleanreturnValue=(Boolean)createBondMethod.invoke(btDevice);
  14. returnreturnValue.booleanValue();
  15. }
  16. /**
  17. *与设备解除配对参考源码:platform/packages/apps/Settings.git
  18. */Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  19. */
  20. staticpublicbooleanremoveBond(ClassbtClass,BluetoothDevicebtDevice)throwsException{
  21. MethodremoveBondMethod=btClass.getMethod("removeBond");
  22. BooleanreturnValue=(Boolean)removeBondMethod.invoke(btDevice);
  23. returnreturnValue.booleanValue();
  24. }
  25. /**
  26. *
  27. *@paramclsShow
  28. */
  29. staticpublicvoidprintAllInform(ClassclsShow){
  30. try{
  31. //取得所有方法
  32. Method[]hideMethod=clsShow.getMethods();
  33. inti=0;
  34. for(;i<hideMethod.length;i++){
  35. Log.e("methodname",hideMethod[i].getName());
  36. }
  37. //取得所有常量
  38. Field[]allFields=clsShow.getFields();
  39. for(i=0;i<allFields.length;i++){
  40. Log.e("Fieldname",allFields[i].getName());
  41. }
  42. }catch(SecurityExceptione){
  43. //thrownewRuntimeException(e.getMessage());
  44. e.printStackTrace();
  45. }catch(IllegalArgumentExceptione){
  46. //thrownewRuntimeException(e.getMessage());
  47. e.printStackTrace();
  48. }catch(Exceptione){
  49. //TODOAuto-generatedcatchblock
  50. e.printStackTrace();
  51. }
  52. }
  53. }

主程序testReflect.java的源码如下:

view plain print ?
  1. packagecom.testReflect;
  2. importjava.util.ArrayList;
  3. importjava.util.List;
  4. importandroid.app.Activity;
  5. importandroid.bluetooth.BluetoothAdapter;
  6. importandroid.bluetooth.BluetoothDevice;
  7. importandroid.content.BroadcastReceiver;
  8. importandroid.content.Context;
  9. importandroid.content.Intent;
  10. importandroid.content.IntentFilter;
  11. importandroid.os.Bundle;
  12. importandroid.util.Log;
  13. importandroid.view.View;
  14. importandroid.widget.AdapterView;
  15. importandroid.widget.ArrayAdapter;
  16. importandroid.widget.Button;
  17. importandroid.widget.ListView;
  18. importandroid.widget.Toast;
  19. publicclasstestReflectextendsActivity{
  20. ButtonbtnSearch,btnShow;
  21. ListViewlvBTDevices;
  22. ArrayAdapter<String>adtDevices;
  23. List<String>lstDevices=newArrayList<String>();
  24. BluetoothDevicebtDevice;
  25. BluetoothAdapterbtAdapt;
  26. @Override
  27. publicvoidonCreate(BundlesavedInstanceState){
  28. super.onCreate(savedInstanceState);
  29. setContentView(R.layout.main);
  30. btnSearch=(Button)this.findViewById(R.id.btnSearch);
  31. btnSearch.setOnClickListener(newClickEvent());
  32. btnShow=(Button)this.findViewById(R.id.btnShow);
  33. btnShow.setOnClickListener(newClickEvent());
  34. lvBTDevices=(ListView)this.findViewById(R.id.ListView01);
  35. adtDevices=newArrayAdapter<String>(testReflect.this,
  36. android.R.layout.simple_list_item_1,lstDevices);
  37. lvBTDevices.setAdapter(adtDevices);
  38. lvBTDevices.setOnItemClickListener(newItemClickEvent());
  39. btAdapt=BluetoothAdapter.getDefaultAdapter();//初始化本机蓝牙功能
  40. if(btAdapt.getState()==BluetoothAdapter.STATE_OFF)//开蓝牙
  41. btAdapt.enable();
  42. //注册Receiver来获取蓝牙设备相关的结果
  43. IntentFilterintent=newIntentFilter();
  44. intent.addAction(BluetoothDevice.ACTION_FOUND);
  45. intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
  46. registerReceiver(searchDevices,intent);
  47. }
  48. privateBroadcastReceiversearchDevices=newBroadcastReceiver(){
  49. publicvoidonReceive(Contextcontext,Intentintent){
  50. Stringaction=intent.getAction();
  51. Bundleb=intent.getExtras();
  52. Object[]lstName=b.keySet().toArray();
  53. //显示所有收到的消息及其细节
  54. for(inti=0;i<lstName.length;i++){
  55. StringkeyName=lstName[i].toString();
  56. Log.e(keyName,String.valueOf(b.get(keyName)));
  57. }
  58. //搜索设备时,取得设备的MAC地址
  59. if(BluetoothDevice.ACTION_FOUND.equals(action)){
  60. BluetoothDevicedevice=intent
  61. .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
  62. if(device.getBondState()==BluetoothDevice.BOND_NONE){
  63. Stringstr="未配对|"+device.getName()+"|"+device.getAddress();
  64. lstDevices.add(str);//获取设备名称和mac地址
  65. adtDevices.notifyDataSetChanged();
  66. }
  67. }
  68. }
  69. };
  70. classItemClickEventimplementsAdapterView.OnItemClickListener{
  71. @Override
  72. publicvoidonItemClick(AdapterView<?>arg0,Viewarg1,intarg2,
  73. longarg3){
  74. btAdapt.cancelDiscovery();
  75. Stringstr=lstDevices.get(arg2);
  76. String[]values=str.split("//|");
  77. Stringaddress=values[2];
  78. btDevice=btAdapt.getRemoteDevice(address);
  79. try{
  80. if(values[0].equals("未配对"))
  81. {
  82. Toast.makeText(testReflect.this,"由未配对转为已配对",500).show();
  83. ClsUtils.createBond(btDevice.getClass(),btDevice);
  84. }
  85. elseif(values[0].equals("已配对"))
  86. {
  87. Toast.makeText(testReflect.this,"由已配对转为未配对",500).show();
  88. ClsUtils.removeBond(btDevice.getClass(),btDevice);
  89. }
  90. }catch(Exceptione){
  91. //TODOAuto-generatedcatchblock
  92. e.printStackTrace();
  93. }
  94. }
  95. }
  96. /**
  97. *按键处理
  98. *@authorGV
  99. *
  100. */
  101. classClickEventimplementsView.OnClickListener{
  102. @Override
  103. publicvoidonClick(Viewv){
  104. if(v==btnSearch){//搜索附近的蓝牙设备
  105. lstDevices.clear();
  106. Object[]lstDevice=btAdapt.getBondedDevices().toArray();
  107. for(inti=0;i<lstDevice.length;i++){
  108. BluetoothDevicedevice=(BluetoothDevice)lstDevice[i];
  109. Stringstr="已配对|"+device.getName()+"|"+device.getAddress();
  110. lstDevices.add(str);//获取设备名称和mac地址
  111. adtDevices.notifyDataSetChanged();
  112. }
  113. //开始搜索
  114. setTitle("本机蓝牙地址:"+btAdapt.getAddress());
  115. btAdapt.startDiscovery();
  116. }
  117. elseif(v==btnShow){//显示BluetoothDevice的所有方法和常量,包括隐藏API
  118. ClsUtils.printAllInform(btDevice.getClass());
  119. }
  120. }
  121. }
  122. }

更多相关文章

  1. Android提高十六篇之使用NDK把彩图转换灰度图
  2. 实时监控Android设备网络封包
  3. android 简单按键修改
  4. Android(安卓)各版本新特性
  5. 【Android应用开发】-(19)Android(安卓)串口编程原理和实现方式(附
  6. 如何成为 Android(安卓)开发高手?
  7. Android中关于dip和px以及转换的总结(重点推荐文章)
  8. Android(安卓)IntentService完全解析 当Service遇到Handler
  9. Xamarin发布XobotOS源码,C# 实现的Android系统 - 操作系统 - ITey

随机推荐

  1. android dumpsys
  2. ok6410 android driver(4)
  3. android全屏无标题
  4. 让Android支持透明状态栏
  5. android 自定义主题样式
  6. android笔记
  7. android例子
  8. android时间控件DigitalClock的使用
  9. Android(安卓)Desigin Library
  10. 收集android的三个小tip