【问题标题】:BluetoothProfile of Paired android device已配对安卓设备的蓝牙配置文件
【发布时间】:2015-04-27 09:04:59
【问题描述】:

有什么方法可以获取配对蓝牙设备的配置文件。 我已经能够配对蓝牙设备,并且它已配对为 INPUT_DEVICE 在 android 中,我得到了 BluetoothDevice 的对象,其中包含地址和其他内容,但如果 android 已经存储了它的配置文件,那么我们可以从哪里获得配对的设备配置文件,比如它是 HEADSET 还是 A2DP 或 INPUT_DEVICE 或其他。

我已经尝试过服务监听的方法

private BluetoothProfile.ServiceListener listener=new BluetoothProfile.ServiceListener() {

        @Override
        public void onServiceDisconnected(int profile) {
            // TODO Auto-generated method stub
            //if(profile==BluetoothProfile.HEADSET)
                headSet=null;
        }

        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            // TODO Auto-generated method stub
            switch(profile){
            case BluetoothProfile.HEADSET:
                Log.e("found","headset");
                break;
            case BluetoothProfile.A2DP:
                Log.e("found","a2dp");
                activity.onA2DPListenr((BluetoothA2dp) proxy);
                break;
            case BluetoothProfile.HEALTH:
                Log.e("found","HEALTH");
                break;
            }


            }
        }
    };

现在每当我通过它调用它时

activity.getAdapter().getProfileProxy(activity, listener,
                BluetoothProfile.HEADSET);

它会进入耳机日志,当我打电话时

activity.getAdapter().getProfileProxy(activity, listener,
                BluetoothProfile.HEALTH);

它会进入健康日志,并显示配置文件已为同一设备连接。但同一设备可以同时连接。

我的要求也与此完全不同,我不想尝试不同的场景来找出我的配对设备的实际配置文件,其中 android 已经包含,他们有什么方法可以获取实际配置文件..?

【问题讨论】:

    标签: android bluetooth


    【解决方案1】:

    与蓝牙设备关联的蓝牙配置文件或服务可以通过

    找到
        boolean hasLatestUuids=device.fetchUuidsWithSdp();
                if(hasLatestUuids){
    /*getUuids() return cached uuids so we need to make an sdp request to get refresh uuid associated with the device*/
                    ParcelUuid[] uu=device.getUuids();
                    for(ParcelUuid u:uu){
                        Log.e("found","uuid "+u.getUuid());
                    }
                }
    

    我们也可以通过反射发出请求:

    Method m=null;
            boolean hasLatestUuid=false;
            try {
                m=BluetoothDevice.class.getDeclaredMethod("fetchUuidsWithSdp", null);
                m.setAccessible(true);
                hasLatestUuid=(Boolean) m.invoke(device, null);
            } catch (NoSuchMethodException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            ParcelUuid[] uuids=null;
    if(hasLatestUuid){
        try {
            m=device.getClass().getDeclaredMethod("getUuids", null);
            m.setAccessible(true);
            uuids=(ParcelUuid[]) m.invoke(device, null);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if(uuids!=null){
            for(ParcelUuid u:uuids){
                Log.e("found","uuid "+u.describeContents());
                Log.e("found","uuid "+u.getUuid());
            }
        }
    

    这里的日志返回远程设备支持的 uuids 列表,例如在我的情况下,我需要连接到两个不同的设备,第一个带有 HID 配置文件,第二个带有串行端口或套接字,所以

    对于串口设备,我得到 uuid:00001101-0000-1000-8000-00805f9b34fb

    对于 HumanInterface,我得到 uuid:00001124-0000-1000-8000-00805f9b34fb

    它有 bas_uuid:00000000-0000-1000-8000-00805F9B34FB 对于serialPort:0x1101 对于 HID:0x1124

    所有这些信息都可以在http://bluetooth-pentest.narod.ru/doc/assigned_numbers_-_service_discovery.html找到

    我们也可以通过 BluetoothClass 进行检查,即

    public static final int PROFILE_HEADSET = 0;
    /** @hide */
    public static final int PROFILE_A2DP = 1;
    /** @hide */
    public static final int PROFILE_OPP = 2;
    /** @hide */
    public static final int PROFILE_HID = 3;
    /** @hide */
    public static final int PROFILE_PANU = 4;
    /** @hide */
    public static final int PROFILE_NAP = 5;
    
    
    BluetoothClass myClass=device.getBluetoothClass();
            int val=myClass.getDeviceClass();
            Log.e("found","class "+val);
            Log.e("found","class "+(val|bitmask));
    
            Log.e("found","PROFILE_HEADSET:"+doesclassMatch(PROFILE_HEADSET,myClass));
            Log.e("found","PROFILE_A2DP:"+doesclassMatch(PROFILE_A2DP,myClass));
            Log.e("found","PROFILE_OPP:"+doesclassMatch(PROFILE_OPP,myClass));
            Log.e("found","PROFILE_HID:"+doesclassMatch(PROFILE_HID,myClass));
            Log.e("found","PROFILE_PANU:"+doesclassMatch(PROFILE_PANU,myClass));
            Log.e("found","PROFILE_NAP:"+doesclassMatch(PROFILE_NAP,myClass));
    
    
    
    
    private boolean doesclassMatch(int profile,BluetoothClass myClass){
        Method m=null;
        try {
            m=BluetoothClass.class.getMethod("doesClassMatch", new Class[]{int.class});
            m.setAccessible(true);
            return (Boolean) m.invoke(myClass, profile);
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return false;
    
    }
    

    它将为设备包含的特定类型或服务返回 true。

    但根据蓝牙类规范:

    BluetoothClass is useful as a hint to roughly describe a device
     * (for example to show an icon in the UI), but does not reliably describe which
     * Bluetooth profiles or services are actually supported by a device. Accurate
     * service discovery is done through SDP requests, which are automatically
     * performed when creating an RFCOMM socket with 
     * BluetoothDevice#createRfcommSocketToServiceRecord} and 
     * BluetoothAdapter#listenUsingRfcommWithServiceRecord
    

    https://android.googlesource.com/platform/frameworks/base/+/4f868ed/core/java/android/bluetooth/BluetoothClass.java

    【讨论】:

    • 嗨你能告诉我你从哪里得到的值public static final int PROFILE_HEADSET = 0; /** hide */ public static final int PROFILE_A2DP = 1; /** hide */ public static final int PROFILE_OPP = 2;等? HSP、HFP 和 AVRCP 的值是多少?
    • 我正在开发一个仅连接到 A2DP、AVRCP、HFP 和 HSP 配置文件的应用程序。我如何检查找到的设备是否是任何提到的配置文件。
    猜你喜欢
    • 2015-02-14
    • 2011-07-21
    • 2012-08-11
    • 1970-01-01
    • 2015-01-18
    • 1970-01-01
    • 1970-01-01
    • 2016-09-26
    • 2015-07-30
    相关资源
    最近更新 更多