Android之探秘蓝牙隐藏API

news/2024/7/4 8:26:41

       上次讲解Android的蓝牙基本用法,这次讲得深入些,探讨下蓝牙方面的隐藏API。用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对解除配对,但是这两项功能的函数没有在SDK中给出,那么如何去使用这两项功能呢?本文利用JAVA的反射机制去调用这两项功能对应的函数:createBond和removeBond,具体的发掘和实现步骤如下:

1.使用Git工具下载platform/packages/apps/Settings.git,在Setting源码中查找关于建立配对解除配对的API,知道这两个API的宿主(BluetoothDevice);

2.使用反射机制对BluetoothDevice枚举其所有方法和常量,看看是否存在:

 

[java]  view plain copy print ?
  1. static public void printAllInform(Class clsShow) {  
  2.     try {  
  3.         // 取得所有方法  
  4.         Method[] hideMethod = clsShow.getMethods();  
  5.         int i = 0;  
  6.         for (; i < hideMethod.length; i++) {  
  7.             Log.e("method name", hideMethod[i].getName());  
  8.         }  
  9.         // 取得所有常量  
  10.         Field[] allFields = clsShow.getFields();  
  11.         for (i = 0; i < allFields.length; i++) {  
  12.             Log.e("Field name", allFields[i].getName());  
  13.         }  
  14.     } catch (SecurityException e) {  
  15.         // throw new RuntimeException(e.getMessage());  
  16.         e.printStackTrace();  
  17.     } catch (IllegalArgumentException e) {  
  18.         // throw new RuntimeException(e.getMessage());  
  19.         e.printStackTrace();  
  20.     } catch (Exception e) {  
  21.         // TODO Auto-generated catch block  
  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却隐藏),则自己实现调用方法:

[java]  view plain copy print ?
  1. /** 
  2.  * 与设备配对 参考源码:platform/packages/apps/Settings.git 
  3.  * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
  4.  */  
  5. static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {  
  6.     Method createBondMethod = btClass.getMethod("createBond");  
  7.     Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);  
  8.     return returnValue.booleanValue();  
  9. }  
  10.   
  11. /** 
  12.  * 与设备解除配对 参考源码:platform/packages/apps/Settings.git 
  13.  * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
  14.  */  
  15. static public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {  
  16.     Method removeBondMethod = btClass.getMethod("removeBond");  
  17.     Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);  
  18.     return returnValue.booleanValue();  
  19. }  

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

本文程序运行效果如下:

main.xml源码如下:

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

工具类ClsUtils.java源码如下:

[java]  view plain copy print ?
  1. package com.testReflect;  
  2.   
  3. import java.lang.reflect.Field;  
  4. import java.lang.reflect.Method;  
  5.   
  6. import android.bluetooth.BluetoothDevice;  
  7. import android.util.Log;  
  8.   
  9. public class ClsUtils {  
  10.   
  11.     /** 
  12.      * 与设备配对 参考源码:platform/packages/apps/Settings.git 
  13.      * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
  14.      */  
  15.     static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {  
  16.         Method createBondMethod = btClass.getMethod("createBond");  
  17.         Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);  
  18.         return returnValue.booleanValue();  
  19.     }  
  20.   
  21.     /** 
  22.      * 与设备解除配对 参考源码:platform/packages/apps/Settings.git 
  23.      * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java 
  24.      */  
  25.     static public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {  
  26.         Method removeBondMethod = btClass.getMethod("removeBond");  
  27.         Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);  
  28.         return returnValue.booleanValue();  
  29.     }  
  30.   
  31.     /** 
  32.      *  
  33.      * @param clsShow 
  34.      */  
  35.     static public void printAllInform(Class clsShow) {  
  36.         try {  
  37.             // 取得所有方法  
  38.             Method[] hideMethod = clsShow.getMethods();  
  39.             int i = 0;  
  40.             for (; i < hideMethod.length; i++) {  
  41.                 Log.e("method name", hideMethod[i].getName());  
  42.             }  
  43.             // 取得所有常量  
  44.             Field[] allFields = clsShow.getFields();  
  45.             for (i = 0; i < allFields.length; i++) {  
  46.                 Log.e("Field name", allFields[i].getName());  
  47.             }  
  48.         } catch (SecurityException e) {  
  49.             // throw new RuntimeException(e.getMessage());  
  50.             e.printStackTrace();  
  51.         } catch (IllegalArgumentException e) {  
  52.             // throw new RuntimeException(e.getMessage());  
  53.             e.printStackTrace();  
  54.         } catch (Exception e) {  
  55.             // TODO Auto-generated catch block  
  56.             e.printStackTrace();  
  57.         }  
  58.     }  
  59. }  

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

[java]  view plain copy print ?
  1. package com.testReflect;  
  2.   
  3. import java.util.ArrayList;  
  4. import java.util.List;  
  5. import android.app.Activity;  
  6. import android.bluetooth.BluetoothAdapter;  
  7. import android.bluetooth.BluetoothDevice;  
  8. import android.content.BroadcastReceiver;  
  9. import android.content.Context;  
  10. import android.content.Intent;  
  11. import android.content.IntentFilter;  
  12. import android.os.Bundle;  
  13. import android.util.Log;  
  14. import android.view.View;  
  15. import android.widget.AdapterView;  
  16. import android.widget.ArrayAdapter;  
  17. import android.widget.Button;  
  18. import android.widget.ListView;  
  19. import android.widget.Toast;  
  20.   
  21. public class testReflect extends Activity {  
  22.     Button btnSearch, btnShow;  
  23.     ListView lvBTDevices;  
  24.     ArrayAdapter<String> adtDevices;  
  25.     List<String> lstDevices = new ArrayList<String>();  
  26.     BluetoothDevice btDevice;  
  27.     BluetoothAdapter btAdapt;  
  28.   
  29.     @Override  
  30.     public void onCreate(Bundle savedInstanceState) {  
  31.         super.onCreate(savedInstanceState);  
  32.         setContentView(R.layout.main);  
  33.   
  34.         btnSearch = (Button) this.findViewById(R.id.btnSearch);  
  35.         btnSearch.setOnClickListener(new ClickEvent());  
  36.         btnShow = (Button) this.findViewById(R.id.btnShow);  
  37.         btnShow.setOnClickListener(new ClickEvent());  
  38.   
  39.         lvBTDevices = (ListView) this.findViewById(R.id.ListView01);  
  40.         adtDevices = new ArrayAdapter<String>(testReflect.this,  
  41.                 android.R.layout.simple_list_item_1, lstDevices);  
  42.         lvBTDevices.setAdapter(adtDevices);  
  43.         lvBTDevices.setOnItemClickListener(new ItemClickEvent());  
  44.   
  45.         btAdapt = BluetoothAdapter.getDefaultAdapter();// 初始化本机蓝牙功能  
  46.         if (btAdapt.getState() == BluetoothAdapter.STATE_OFF)// 开蓝牙  
  47.             btAdapt.enable();  
  48.   
  49.         // 注册Receiver来获取蓝牙设备相关的结果  
  50.         IntentFilter intent = new IntentFilter();  
  51.         intent.addAction(BluetoothDevice.ACTION_FOUND);  
  52.         intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);  
  53.         registerReceiver(searchDevices, intent);  
  54.   
  55.     }  
  56.   
  57.       
  58.     private BroadcastReceiver searchDevices = new BroadcastReceiver() {  
  59.         public void onReceive(Context context, Intent intent) {  
  60.             String action = intent.getAction();  
  61.             Bundle b = intent.getExtras();  
  62.             Object[] lstName = b.keySet().toArray();  
  63.   
  64.             // 显示所有收到的消息及其细节  
  65.             for (int i = 0; i < lstName.length; i++) {  
  66.                 String keyName = lstName[i].toString();  
  67.                 Log.e(keyName, String.valueOf(b.get(keyName)));  
  68.             }  
  69.             // 搜索设备时,取得设备的MAC地址  
  70.             if (BluetoothDevice.ACTION_FOUND.equals(action)) {  
  71.                 BluetoothDevice device = intent  
  72.                         .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);  
  73.   
  74.                 if (device.getBondState() == BluetoothDevice.BOND_NONE) {  
  75.                     String str = "未配对|" + device.getName() + "|" + device.getAddress();  
  76.                     lstDevices.add(str); // 获取设备名称和mac地址  
  77.                     adtDevices.notifyDataSetChanged();  
  78.                 }  
  79.             }  
  80.         }  
  81.     };  
  82.   
  83.     class ItemClickEvent implements AdapterView.OnItemClickListener {  
  84.   
  85.         @Override  
  86.         public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,  
  87.                 long arg3) {  
  88.             btAdapt.cancelDiscovery();  
  89.             String str = lstDevices.get(arg2);  
  90.             String[] values = str.split("//|");  
  91.             String address=values[2];  
  92.   
  93.             btDevice = btAdapt.getRemoteDevice(address);  
  94.             try {  
  95.                 if(values[0].equals("未配对"))  
  96.                 {     
  97.                     Toast.makeText(testReflect.this"由未配对转为已配对"500).show();  
  98.                     ClsUtils.createBond(btDevice.getClass(), btDevice);  
  99.                 }  
  100.                 else if(values[0].equals("已配对"))  
  101.                 {  
  102.                     Toast.makeText(testReflect.this"由已配对转为未配对"500).show();  
  103.                     ClsUtils.removeBond(btDevice.getClass(), btDevice);  
  104.                 }  
  105.             } catch (Exception e) {  
  106.                 // TODO Auto-generated catch block  
  107.                 e.printStackTrace();  
  108.             }  
  109.         }  
  110.           
  111.     }  
  112.       
  113.     /** 
  114.      * 按键处理 
  115.      * @author GV 
  116.      * 
  117.      */  
  118.     class ClickEvent implements View.OnClickListener {  
  119.   
  120.         @Override  
  121.         public void onClick(View v) {  
  122.             if (v == btnSearch) {//搜索附近的蓝牙设备  
  123.                 lstDevices.clear();  
  124.                   
  125.                 Object[] lstDevice = btAdapt.getBondedDevices().toArray();  
  126.                 for (int i = 0; i < lstDevice.length; i++) {  
  127.                     BluetoothDevice device=(BluetoothDevice)lstDevice[i];  
  128.                     String str = "已配对|" + device.getName() + "|" + device.getAddress();  
  129.                     lstDevices.add(str); // 获取设备名称和mac地址  
  130.                     adtDevices.notifyDataSetChanged();  
  131.                 }  
  132.                 // 开始搜索  
  133.                 setTitle("本机蓝牙地址:" + btAdapt.getAddress());  
  134.                 btAdapt.startDiscovery();  
  135.             }  
  136.             else if(v==btnShow){//显示BluetoothDevice的所有方法和常量,包括隐藏API  
  137.                 ClsUtils.printAllInform(btDevice.getClass());  
  138.             }  
  139.   
  140.         }  
  141.   
  142.     }  
  143.   
  144.   
  145. }  


文章出处:http://blog.csdn.net/hellogv/article/details/6042091/




http://www.niftyadmin.cn/n/3649243.html

相关文章

golang flag 包_如何在Go中使用Flag包

golang flag 包介绍 (Introduction) Command-line utilities are rarely useful out of the box without additional configuration. Good defaults are important, but useful utilities need to accept configuration from users. On most platforms, command-line utilities…

Ubuntu 装 Samba 安装详解 (已在Ubuntu11Server测试通过)

转自&#xff1a;http://wiki.ubuntu.org.cn/Samba Samba Samba是Ubuntu和Windows进行网络共享的工具&#xff0c;比如分享打印机&#xff0c;互相之间传输资料文件。 目录 [隐藏]1 安装Samba2 Kubuntu3 配置4 Ubuntu访问windows xp/2003/2000系统5 排错 5.1 乱码 6 smb用户…

golang接口的使用场景_如何在Go中使用接口

golang接口的使用场景介绍 (Introduction) Writing flexible, reusable, and modular code is vital for developing versatile programs. Working in this way ensures code is easier to maintain by avoiding the need to make the same change in multiple places. How you…

android以欺骗的方法使用隐藏API调用举例(国际化,多语言)

Android对国际化与多语言切换已经做得不错了&#xff0c;一个应用只要命名相应语系的values-[language]文件夹&#xff0c;通过“设置”→“语言&键盘”→“选择语言”即可实现应用多种语言的切换。 但如何在应用里自己实现&#xff1f;搜索过发现网上有如下的做法&…

[收藏]mvm的“公司如船”大论

mvm的&#xff1a;http://home.wangjianshuo.com/mvm/000525.htm公司如船有个企业家被问到他为什么喜欢航海。他的回答是&#xff0c;航海和经营企业有强烈的共同点&#xff1a;到了海上以后&#xff0c;就算船上有人你不喜欢&#xff0c;你也只能去适应他&#xff0c;而不可能…

关于公司系统支撑工作的建议

关于公司系统支撑工作的建议成晓旭刚来部门不久&#xff0c;对部门的整体工作情况了解不多&#xff0c;对公司的信息系统建设情况更是不敢枉自品评。对于像我们这样规模的公司&#xff0c;自己建设、实施和维护满足公司自身管理要求的管理信息系统&#xff0c;是目前部门公司对…

如何将class文件打包成jar文件

如何将class文件打包成jar文件&#xff0c;这是一个很严肃的问题&#xff0c;当你在在使用webservice的saop协议的时候&#xff0c;很多地方不免需要用到远程jar包&#xff0c;这些jar包里面&#xff0c;存放的将是你的VO或者是JavaBean 这些方法都将对外提供并暴露。好了 &…