Android 藍牙電話聯繫人同步之藍牙狀態檢測

最近做的一個語音項目,要求車機端可以利用藍牙,語音打電話給手機通訊錄裏的聯繫人。

實現這個功能需要將手機端的通訊錄上傳到語音的遠程服務器端,並且SDK要求必須把藍牙的狀態實時上報上去。

上報通訊錄其實還是很簡單的,只要監聽車機端的聯繫人provider的變化就可以進行讀取操作和上報。

mContactObserver = new ContactObserver(new Handler());
Uri uri = ContactsContract.Contacts.CONTENT_URI;
mResolver.registerContentObserver(uri, true, mContactObserver);

難點其實在於如何上報藍牙的連接狀態,這裏和電話相關的兩個藍牙協議分別是:

  • Headset: 藍牙打電話
  • Pbap:聯繫人同步

所以如果能監聽藍牙的這兩個連接狀態的變化就可以上報了,但是很不幸的是這兩個狀態在Android sdk裏沒有提供相應的顯示的廣播,這兩個廣播屬於隱藏。如果要想監聽,就必須使用“反射”大法了。

翻看源碼,先找到這兩個廣播的定義之處,然後定義它們

 private final static String REFLECTION_HEADSETCLIENT_CLASS =
            "android.bluetooth.BluetoothHeadsetClient";

private final static String REFLECTION_PBAP_CLIENT_CLASS =
            "android.bluetooth.BluetoothPbapClient";

然後就是反射它們,這裏我使用了一個反射工具類,自己寫的

public String getAttributeValueOfStringType(String classPath, String attribute) {
        String value = "";
        try {
            Class clazz = Class.forName(classPath);
            Field field= clazz.getField(attribute);
            value = (String)field.get(clazz);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return value;
    }

最後就是註冊監聽這兩個藍牙廣播

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(ReflectionUtil.getInstance().getAttributeValueOfStringType(
                REFLECTION_HEADSETCLIENT_CLASS,
                REFLECTION_CONSTANT_CONNECTION_CHANGED));
intentFilter.addAction(ReflectionUtil.getInstance().getAttributeValueOfStringType(
                REFLECTION_PBAP_CLIENT_CLASS,
                REFLECTION_CONSTANT_CONNECTION_CHANGED));
mBluetoothReceiver = new BluetoothReceiver();
if (!isRegisterBT) {
            XXApplication.getContext().registerReceiver(mBluetoothReceiver, intentFilter);
            isRegisterBT = true;
}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章