Beta 1.0 中国家用电器研究院旗下新媒体 | 家电数码互动评测第一平台
查看: 1216|回复: 0

【烙印教室】Android提高之探秘蓝牙隐藏API

[复制链接]

Always_Online

  • TA的每日心情
    奋斗
    2016-3-5 21:07
  • 签到天数: 503 天

    [LV.9]以坛为家II




    【烙印教室】Android提高之探秘蓝牙隐藏API [复制链接]
    1216 0
    打印 上一主题 下一主题
    2015-6-13 19:04:37
    上次讲解Android的蓝牙基本用法,这次讲得深入些,探讨下蓝牙方面的隐藏API。用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出,那么如何去使用这两项功能呢?本文利用JAVA的反射机制去调用这两项功能对应的函数:createBond和removeBond,具体的发掘和实现步骤如下:
    1.使用Git工具下载platform/packages/apps/Settings.git,在Setting源码中查找关于建立配对和解除配对的API,知道这两个API的宿主(BluetoothDevice);
    2.使用反射机制对BluetoothDevice枚举其所有方法和常量,看看是否存在:

    static public void printAllInform(Class clsShow) {
                    try {
                            // 取得所有方法
                            Method[] hideMethod = clsShow.getMethods();
                            int i = 0;
                            for (; i < hideMethod.length; i++) {
                                    Log.e("method name", hideMethod.getName());
                            }
                            // 取得所有常量
                            Field[] allFields = clsShow.getFields();
                            for (i = 0; i < allFields.length; i++) {
                                    Log.e("Field name", allFields.getName());
                            }
                    } catch (SecurityException e) {
                            // throw new RuntimeException(e.getMessage());
                            e.printStackTrace();
                    } catch (IllegalArgumentException e) {
                            // throw new RuntimeException(e.getMessage());
                            e.printStackTrace();
                    } catch (Exception e) {
                            // TODO Auto-generated catch block
                            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却隐藏),则自己实现调用方法:
    /**
             * 与设备配对 参考源码:platform/packages/apps/Settings.git
             * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
             */
            static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {
                    Method createBondMethod = btClass.getMethod("createBond");
                    Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
                    return returnValue.booleanValue();
            }

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

    00.gif
    main.xml源码如下:
    • <linearlayout xmlns:android="http://schemas.android.com/apk/res/android"
    •         androidrientation="vertical" android:layout_width="fill_parent"
    •         android:layout_height="fill_parent">
    •         <linearlayout android:id="@+id/LinearLayout01"
    •                 android:layout_height="wrap_content" android:layout_width="fill_parent">
    •                 <button android:layout_height="wrap_content" android:id="@+id/btnSearch"
    •                         android:text="Search" android:layout_width="160dip">
    •                 <button android:layout_height="wrap_content"
    •                         android:layout_width="160dip" android:text="Show" android:id="@+id/btnShow">
    •         <linearlayout android:id="@+id/LinearLayout02"
    •                 android:layout_width="wrap_content" android:layout_height="wrap_content">
    •         <listview android:id="@+id/ListView01" android:layout_width="fill_parent"
    •                 android:layout_height="fill_parent">


    复制代码

    工具类ClsUtils.java源码如下:
    • package com.testReflect;
    • import java.lang.reflect.Field;
    • import java.lang.reflect.Method;
    • import android.bluetooth.BluetoothDevice;
    • import android.util.Log;
    • public class ClsUtils {
    •         /**
    •          * 与设备配对 参考源码:platform/packages/apps/Settings.git
    •          * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
    •          */
    •         static public boolean createBond(Class btClass,BluetoothDevice btDevice) throws Exception {
    •                 Method createBondMethod = btClass.getMethod("createBond");
    •                 Boolean returnValue = (Boolean) createBondMethod.invoke(btDevice);
    •                 return returnValue.booleanValue();
    •         }
    •         /**
    •          * 与设备解除配对 参考源码:platform/packages/apps/Settings.git
    •          * /Settings/src/com/android/settings/bluetooth/CachedBluetoothDevice.java
    •          */
    •         static public boolean removeBond(Class btClass,BluetoothDevice btDevice) throws Exception {
    •                 Method removeBondMethod = btClass.getMethod("removeBond");
    •                 Boolean returnValue = (Boolean) removeBondMethod.invoke(btDevice);
    •                 return returnValue.booleanValue();
    •         }
    •         /**
    •          *
    •          * @param clsShow
    •          */
    •         static public void printAllInform(Class clsShow) {
    •                 try {
    •                         // 取得所有方法
    •                         Method[] hideMethod = clsShow.getMethods();
    •                         int i = 0;
    •                         for (; i < hideMethod.length; i++) {
    •                                 Log.e("method name", hideMethod.getName());
    •                         }
    •                         // 取得所有常量
    •                         Field[] allFields = clsShow.getFields();
    •                         for (i = 0; i < allFields.length; i++) {
    •                                 Log.e("Field name", allFields.getName());
    •                         }
    •                 } catch (SecurityException e) {
    •                         // throw new RuntimeException(e.getMessage());
    •                         e.printStackTrace();
    •                 } catch (IllegalArgumentException e) {
    •                         // throw new RuntimeException(e.getMessage());
    •                         e.printStackTrace();
    •                 } catch (Exception e) {
    •                         // TODO Auto-generated catch block
    •                         e.printStackTrace();
    •                 }
    •         }
    • }


    复制代码

    主程序testReflect.java的源码如下:
    • package com.testReflect;
    • import java.util.ArrayList;
    • import java.util.List;
    • import android.app.Activity;
    • import android.bluetooth.BluetoothAdapter;
    • import android.bluetooth.BluetoothDevice;
    • import android.content.BroadcastReceiver;
    • import android.content.Context;
    • import android.content.Intent;
    • import android.content.IntentFilter;
    • import android.os.Bundle;
    • import android.util.Log;
    • import android.view.View;
    • import android.widget.AdapterView;
    • import android.widget.ArrayAdapter;
    • import android.widget.Button;
    • import android.widget.ListView;
    • import android.widget.Toast;
    • public class testReflect extends Activity {
    •         Button btnSearch, btnShow;
    •         ListView lvBTDevices;
    •         ArrayAdapter adtDevices;
    •         List lstDevices = new ArrayList();
    •         BluetoothDevice btDevice;
    •         BluetoothAdapter btAdapt;
    •         @Override
    •         public void onCreate(Bundle savedInstanceState) {
    •                 super.onCreate(savedInstanceState);
    •                 setContentView(R.layout.main);
    •                 btnSearch = (Button) this.findViewById(R.id.btnSearch);
    •                 btnSearch.setOnClickListener(new ClickEvent());
    •                 btnShow = (Button) this.findViewById(R.id.btnShow);
    •                 btnShow.setOnClickListener(new ClickEvent());
    •                 lvBTDevices = (ListView) this.findViewById(R.id.ListView01);
    •                 adtDevices = new ArrayAdapter(testReflect.this,
    •                                 android.R.layout.simple_list_item_1, lstDevices);
    •                 lvBTDevices.setAdapter(adtDevices);
    •                 lvBTDevices.setOnItemClickListener(new ItemClickEvent());
    •                 btAdapt = BluetoothAdapter.getDefaultAdapter();// 初始化本机蓝牙功能
    •                 if (btAdapt.getState() == BluetoothAdapter.STATE_OFF)// 开蓝牙
    •                         btAdapt.enable();
    •                 // 注册Receiver来获取蓝牙设备相关的结果
    •                 IntentFilter intent = new IntentFilter();
    •                 intent.addAction(BluetoothDevice.ACTION_FOUND);
    •                 intent.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
    •                 registerReceiver(searchDevices, intent);
    •         }
    •         private BroadcastReceiver searchDevices = new BroadcastReceiver() {
    •                 public void onReceive(Context context, Intent intent) {
    •                         String action = intent.getAction();
    •                         Bundle b = intent.getExtras();
    •                         Object[] lstName = b.keySet().toArray();
    •                         // 显示所有收到的消息及其细节
    •                         for (int i = 0; i < lstName.length; i++) {
    •                                 String keyName = lstName.toString();
    •                                 Log.e(keyName, String.valueOf(b.get(keyName)));
    •                         }
    •                         // 搜索设备时,取得设备的MAC地址
    •                         if (BluetoothDevice.ACTION_FOUND.equals(action)) {
    •                                 BluetoothDevice device = intent
    •                                                 .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
    •                                 if (device.getBondState() == BluetoothDevice.BOND_NONE) {
    •                                         String str = "未配对|" + device.getName() + "|" + device.getAddress();
    •                                         lstDevices.add(str); // 获取设备名称和mac地址
    •                                         adtDevices.notifyDataSetChanged();
    •                                 }
    •                         }
    •                 }
    •         };
    •         class ItemClickEvent implements AdapterView.OnItemClickListener {
    •                 @Override
    •                 public void onItemClick(AdapterView arg0, View arg1, int arg2,
    •                                 long arg3) {
    •                         btAdapt.cancelDiscovery();
    •                         String str = lstDevices.get(arg2);
    •                         String[] values = str.split("//|");
    •                         String address=values[2];
    •                         btDevice = btAdapt.getRemoteDevice(address);
    •                         try {
    •                                 if(values[0].equals("未配对"))
    •                                 {
    •                                         Toast.makeText(testReflect.this, "由未配对转为已配对", 500).show();
    •                                         ClsUtils.createBond(btDevice.getClass(), btDevice);
    •                                 }
    •                                 else if(values[0].equals("已配对"))
    •                                 {
    •                                         Toast.makeText(testReflect.this, "由已配对转为未配对", 500).show();
    •                                         ClsUtils.removeBond(btDevice.getClass(), btDevice);
    •                                 }
    •                         } catch (Exception e) {
    •                                 // TODO Auto-generated catch block
    •                                 e.printStackTrace();
    •                         }
    •                 }
    •         }
    •         /**
    •          * 按键处理
    •          * @author GV
    •          *
    •          */
    •         class ClickEvent implements View.OnClickListener {
    •                 @Override
    •                 public void onClick(View v) {
    •                         if (v == btnSearch) {//搜索附近的蓝牙设备
    •                                 lstDevices.clear();
    •                                 Object[] lstDevice = btAdapt.getBondedDevices().toArray();
    •                                 for (int i = 0; i < lstDevice.length; i++) {
    •                                         BluetoothDevice device=(BluetoothDevice)lstDevice;
    •                                         String str = "已配对|" + device.getName() + "|" + device.getAddress();
    •                                         lstDevices.add(str); // 获取设备名称和mac地址
    •                                         adtDevices.notifyDataSetChanged();
    •                                 }
    •                                 // 开始搜索
    •                                 setTitle("本机蓝牙地址:" + btAdapt.getAddress());
    •                                 btAdapt.startDiscovery();
    •                         }
    •                         else if(v==btnShow){//显示BluetoothDevice的所有方法和常量,包括隐藏API
    •                                 ClsUtils.printAllInform(btDevice.getClass());
    •                         }
    •                 }
    •         }
    • }

    复制代码




    免责声明                                                   
    本资源来自互联网,如有侵犯您的版权,请发邮件到765673603@qq.com联系我们将其删除。
    +10
    本版积分规则
    您需要登录后才可以回帖 登录 | 注册

    关闭

    站长推荐上一条 /2 下一条

    返回顶部 返回列表