默认电话研究

默认电话研究

背景

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;
}

你可能感兴趣的:(Android)