Android提高第十三篇之探秘蓝牙隐藏API

Android提高第十三篇之探秘蓝牙隐藏API

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

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

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


  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却隐藏),则自己实现调用方法:
  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.          * 与设备解除配对 参考源码:platform/packages/apps/Settings.git
  12.          * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  13.          */
  14.         static public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
  15.                 Method removeBondMethod = btClass.getMethod("removeBond");
  16.                 Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
  17.                 return returnValue.booleanValue();
  18.         }
复制代码
PS:SDK之所以不给出隐藏的API肯定有其原因,也许是出于安全性或者是后续版本兼容性的考虑,因此不能保证隐藏API能在所有Android平台上很好地运行。。。本文程序运行效果如下:    
main.xml源码如下:

  1. <linearlayout xmlns:android="http://schemas.android.com/apk/res/android" 
  2.         android:orientation="vertical" android:layout_width="fill_parent"
  3.         android:layout_height="fill_parent">
  4.         <linearlayout android:id="@+id/LinearLayout01" 
  5.                 android:layout_height="wrap_content" android:layout_width="fill_parent">
  6.                 <button android:layout_height="wrap_content" android:id="@+id/btnSearch" 
  7.                         android:text="Search" android:layout_width="160dip">
  8.                 <button android:layout_height="wrap_content" 
  9.                         android:layout_width="160dip" android:text="Show" android:id="@+id/btnShow">
  10.         
  11.         <linearlayout android:id="@+id/LinearLayout02" 
  12.                 android:layout_width="wrap_content" android:layout_height="wrap_content">
  13.         <listview android:id="@+id/ListView01" android:layout_width="fill_parent" 
  14.                 android:layout_height="fill_parent">
  15.         

复制代码
工具类ClsUtils.java源码如下:
  1. package com.testReflect;

  2. import java.lang.reflect.Field;
  3. import java.lang.reflect.Method;

  4. import android.bluetooth.BluetoothDevice;
  5. import android.util.Log;

  6. public class ClsUtils {

  7.         /**
  8.          * 与设备配对 参考源码:platform/packages/apps/Settings.git
  9.          * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  10.          */
  11.         static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {
  12.                 Method createBondMethod = btClass.getMethod("createBond");
  13.                 Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
  14.                 return returnValue.booleanValue();
  15.         }

  16.         /**
  17.          * 与设备解除配对 参考源码:platform/packages/apps/Settings.git
  18.          * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
  19.          */
  20.         static public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
  21.                 Method removeBondMethod = btClass.getMethod("removeBond");
  22.                 Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
  23.                 return returnValue.booleanValue();
  24.         }

  25.         /**
  26.          * 
  27.          * @param clsShow
  28.          */
  29.         static public void printAllInform(Class clsShow) {
  30.                 try {
  31.                         // 取得所有方法
  32.                         Method[] hideMethod = clsShow.getMethods();
  33.                         int i = 0;
  34.                         for (; i < hideMethod.length; i++) {
  35.                                 Log.e("method name", hideMethod[i].getName());
  36.                         }
  37.                         // 取得所有常量
  38.                         Field[] allFields = clsShow.getFields();
  39.                         for (i = 0; i < allFields.length; i++) {
  40.                                 Log.e("Field name", allFields[i].getName());
  41.                         }
  42.                 } catch (SecurityException e) {
  43.                         // throw new RuntimeException(e.getMessage());
  44.                         e.printStackTrace();
  45.                 } catch (IllegalArgumentException e) {
  46.                         // throw new RuntimeException(e.getMessage());
  47.                         e.printStackTrace();
  48.                 } catch (Exception e) {
  49.                         // TODO Auto-generated catch block
  50.                         e.printStackTrace();
  51.                 }
  52.         }
  53. }
复制代码
主程序testReflect.java的源码如下:
  1. package com.testReflect;

  2. import java.util.ArrayList;
  3. import java.util.List;
  4. import android.app.Activity;
  5. import android.bluetooth.BluetoothAdapter;
  6. import android.bluetooth.BluetoothDevice;
  7. import android.content.BroadcastReceiver;
  8. import android.content.Context;
  9. import android.content.Intent;
  10. import android.content.IntentFilter;
  11. import android.os.Bundle;
  12. import android.util.Log;
  13. import android.view.View;
  14. import android.widget.AdapterView;
  15. import android.widget.ArrayAdapter;
  16. import android.widget.Button;
  17. import android.widget.ListView;
  18. import android.widget.Toast;

  19. public class testReflect extends Activity {
  20.         Button btnSearch, btnShow;
  21.         ListView lvBTDevices;
  22.         ArrayAdapter adtDevices;
  23.         List lstDevices = new ArrayList();
  24.         BluetoothDevice btDevice;
  25.         BluetoothAdapter btAdapt;

  26.         @Override
  27.         public void onCreate(Bundle savedInstanceState) {
  28.                 super.onCreate(savedInstanceState);
  29.                 setContentView(R.layout.main);

  30.                 btnSearch = (Button) this.findViewById(R.id.btnSearch);
  31.                 btnSearch.setOnClickListener(new ClickEvent());
  32.                 btnShow = (Button) this.findViewById(R.id.btnShow);
  33.                 btnShow.setOnClickListener(new ClickEvent());

  34.                 lvBTDevices = (ListView) this.findViewById(R.id.ListView01);
  35.                 adtDevices = new ArrayAdapter(testReflect.this,
  36.                                 android.R.layout.simple_list_item_1, lstDevices);
  37.                 lvBTDevices.setAdapter(adtDevices);
  38.                 lvBTDevices.setOnItemClickListener(new ItemClickEvent());

  39.                 btAdapt = BluetoothAdapter.getDefaultAdapter();// 初始化本机蓝牙功能
  40.                 if (btAdapt.getState() == BluetoothAdapter.STATE_OFF)// 开蓝牙
  41.                         btAdapt.enable();

  42.                 // 注册Receiver来获取蓝牙设备相关的结果
  43.                 IntentFilter intent = new IntentFilter();
  44.                 intent.addAction(BluetoothDevice.ACTION_FOUND);
  45.                 intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
  46.                 registerReceiver(searchDevices, intent);

  47.         }

  48.         
  49.         private BroadcastReceiver searchDevices = new BroadcastReceiver() {
  50.                 public void onReceive(Context context, Intent intent) {
  51.                         String action = intent.getAction();
  52.                         Bundle b = intent.getExtras();
  53.                         Object[] lstName = b.keySet().toArray();

  54.                         // 显示所有收到的消息及其细节
  55.                         for (int i = 0; i < lstName.length; i++) {
  56.                                 String keyName = lstName[i].toString();
  57.                                 Log.e(keyName, String.valueOf(b.get(keyName)));
  58.                         }
  59.                         // 搜索设备时,取得设备的MAC地址
  60.                         if (BluetoothDevice.ACTION_FOUND.equals(action)) {
  61.                                 BluetoothDevice device = intent
  62.                                                 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);

  63.                                 if (device.getBondState() == BluetoothDevice.BOND_NONE) {
  64.                                         String str = "未配对|" + device.getName() + "|" + device.getAddress();
  65.                                         lstDevices.add(str); // 获取设备名称和mac地址
  66.                                         adtDevices.notifyDataSetChanged();
  67.                                 }
  68.                         }
  69.                 }
  70.         };

  71.         class ItemClickEvent implements AdapterView.OnItemClickListener {

  72.                 @Override
  73.                 public void onItemClick(AdapterView arg0, View arg1, int arg2,
  74.                                 long arg3) {
  75.                         btAdapt.cancelDiscovery();
  76.                         String str = lstDevices.get(arg2);
  77.                         String[] values = str.split("//|");
  78.                         String address=values[2];

  79.                         btDevice = btAdapt.getRemoteDevice(address);
  80.                         try {
  81.                                 if(values[0].equals("未配对"))
  82.                                 {        
  83.                                         Toast.makeText(testReflect.this, "由未配对转为已配对", 500).show();
  84.                                         ClsUtils.createBond(btDevice.getClass(), btDevice);
  85.                                 }
  86.                                 else if(values[0].equals("已配对"))
  87.                                 {
  88.                                         Toast.makeText(testReflect.this, "由已配对转为未配对", 500).show();
  89.                                         ClsUtils.removeBond(btDevice.getClass(), btDevice);
  90.                                 }
  91.                         } catch (Exception e) {
  92.                                 // TODO Auto-generated catch block
  93.                                 e.printStackTrace();
  94.                         }
  95.                 }
  96.                 
  97.         }
  98.         
  99.         /**
  100.          * 按键处理
  101.          * @author GV
  102.          *
  103.          */
  104.         class ClickEvent implements View.OnClickListener {

  105.                 @Override
  106.                 public void onClick(View v) {
  107.                         if (v == btnSearch) {//搜索附近的蓝牙设备
  108.                                 lstDevices.clear();
  109.                                 
  110.                                 Object[] lstDevice = btAdapt.getBondedDevices().toArray();
  111.                                 for (int i = 0; i < lstDevice.length; i++) {
  112.                                         BluetoothDevice device=(BluetoothDevice)lstDevice[i];
  113.                                         String str = "已配对|" + device.getName() + "|" + device.getAddress();
  114.                                         lstDevices.add(str); // 获取设备名称和mac地址
  115.                                         adtDevices.notifyDataSetChanged();
  116.                                 }
  117.                                 // 开始搜索
  118.                                 setTitle("本机蓝牙地址:" + btAdapt.getAddress());
  119.                                 btAdapt.startDiscovery();
  120.                         }
  121.                         else if(v==btnShow){//显示BluetoothDevice的所有方法和常量,包括隐藏API
  122.                                 ClsUtils.printAllInform(btDevice.getClass());
  123.                         }

  124.                 }

  125.         }


  126. }
复制代码


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值