默認電話研究
背景
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
中有兩個方法,onCallAdded
和 onCallRemoved
,分別代表電話進來與斷開時會被調用,一般我們會在 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
的註冊,需要添加相應的 data
和 filter
<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;
}