默認電話研究

默認電話研究

背景

Android 從6.0開始,允許用戶設置默認短信和默認電話應用,使用相應的 Intent 便可以設置默認應用

從一個框架說起

API 21 開始,谷歌添加了 TelecomManager 用於提供對電話通訊狀態的監聽

API 23 之後,又開放了 Telecom framework,這個框架允許第三方應用開發者編寫應用來替換系統默認電話應用,而其中大部分接口就添加在 android.telecom 包下

Telecom framework 其實提供了兩個方面的 API,一個是 ConnectionService 用於實現通訊(比如通過電信服務商提供的電話連接服務),另一個就是我們這次的需要用到的 InCallService,它主要負責提供 UI 來管理電話

一般系統自帶的電話應用同樣也是實現這套 API 來提供電話通信的交互界面

API 21 相關代碼

代碼位置:/frameworks/base/telecomm/java/android/telecom/TelecomManager.java

代碼概覽:TelecomManager.java

可看到這個時候,雖然有代碼狀態的監聽接口,但其屬性值設置爲 @hide 這就意味着,要麼系統軟件可以使用,要麼就使用反射調用,一般用於

API 23 相關代碼

代碼位置:/frameworks/base/telecomm/java/android/telecom/

代碼概覽:Telecom Framework

這邊的接口,主要關注一個基類 InCallService.java 這個類就是第三方電話應用需要去繼承實現的類

默認電話的實現

1. 繼承 `InCallService` 並實現需要用到的方法
2. 添加一個 Activity 用於提供用戶界面

Service 相關

InCallService 中有兩個方法,onCallAddedonCallRemoved,分別代表電話進來與斷開時會被調用,一般我們會在 onCallAdded 中註冊電話狀態監聽,並在 onCallRemoved 中解除監聽

public class PhoneCallService extends InCallService {

    private Call.Callback callback = new Call.Callback() {
        @Override
        public void onStateChanged(Call call, int state) {
            super.onStateChanged(call, state);
            switch (state) {
                case Call.STATE_ACTIVE: {
                    break; // 通話中
                }
                case Call.STATE_DISCONNECTED: {
                    break; // 通話結束
                }
            }
        }
    };

    @Override
    public void onCallAdded(Call call) {
        super.onCallAdded(call);

        call.registerCallback(callback);
    }
    
    @Override
    public void onCallRemoved(Call call) {
        super.onCallRemoved(call);

        call.unregisterCallback(callback);
    }
}

Service 的註冊,需要添加相應的 datafilter

<service
    android:name=".PhoneCallService"
    android:permission="android.permission.BIND_INCALL_SERVICE">
    <meta-data
        android:name="android.telecom.IN_CALL_SERVICE_UI"
        android:value="true" />
    <intent-filter>
        <action android:name="android.telecom.InCallService" />
    </intent-filter>
</service>

Activity 相關

在做默認電話相關界面的時候,註冊的時候也必須有相應的添加相對應

<intent-filter>
    <action android:name="android.intent.action.DIAL" />
    <data android:scheme="tel" />
</intent-filter>
<intent-filter>
    <action android:name="android.intent.action.DIAL" />
</intent-filter>

設置爲默認應用

和默認短信一樣,默認電話也有設爲默認的 Action

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
	Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
	intent.putExtra(TelecomManager.EXTRA_CHANGE_DEFAULT_DIALER_PACKAGE_NAME, 
                    getPackageName());
	startActivity(intent);
}

默認電話應用行爲

  • Permission.READ_PHONE_STATE

  • Permission.READ_CONTACTS

  • Permission.WRITE_CONTACTS

  • Permission.READ_CALL_LOG

  • Permission.WRITE_CALL_LOG

  • Permission.PROCESS_OUTGOING_CALLS

  • Permission.CALL_PHONE

  • Permission.GET_ACCOUNTS

    注意:默認電話的讀寫權限有些手機會一同授予,有些則不會

檢查默認應用

public static boolean isDefaultPhoneCallApp(Context context) {
    if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        TelecomManager manger = (TelecomManager) context.getSystemService(TELECOM_SERVICE);
        if (manger != null) {
            String name = manger.getDefaultDialerPackage();
            return name.equals(context.getPackageName());
        }
    }
    return false;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章