Android 8.0 PhoneAccount全面解析

转载请注明出处:https://blog.csdn.net/turtlejj/article/details/81567426,谢谢~

 

     最近由于碰到了一个CTS的问题,涉及到了PhoneAccount,然而之前并没有接触过相关的内容。因此想在网上找些资料来看,结果发现并没有特别详细介绍PhoneAccount的文章,于是萌生了自己写一篇的想法。

     废话不多说,现在就开始吧。

 

一、什么是PhoneAccount

/frameworks/base/telecom/java/android/telecom/PhoneAccount.java

/**
 * Represents a distinct method to place or receive a phone call. Apps which can place calls and
 * want those calls to be integrated into the dialer and in-call UI should build an instance of
 * this class and register it with the system using {@link TelecomManager}.
 * <p>
 * {@link TelecomManager} uses registered {@link PhoneAccount}s to present the user with
 * alternative options when placing a phone call. When building a {@link PhoneAccount}, the app
 * should supply a valid {@link PhoneAccountHandle} that references the connection service
 * implementation Telecom will use to interact with the app.
 */

    以上是Android源码中对PhoneAccount的介绍,简单来说就是,PhoneAccount是用来接打电话的,我们可以使用TelecomManager里面的方法来创建一个PhoneAccount。同时,PhoneAccount还有一个唯一的标识,叫做PhoneAccountHandle,Telecom会通过PhoneAccountHandle所提供的ConnectionService信息来与App进行通信。

      由于自己是做Android系统研发的,所以对第三方的App以及网络电话(Sip)不是特别了解,因此我们这里先以最常见的Sim卡类型的PhoneAccount来进行讲解。

 

    我们的手机之所以可以通过Sim卡来拨打电话,同样也是因为系统会为每张当前插入手机的Sim卡都创建了一个PhoneAccount。Telecom通过Sim卡的PhoneAccount就可以与Dialer以及in-call UI进行通信,并成功完成电话的拨打以及接听。

      那么下面我们就来详细介绍一下PhoneAccount以及PhoneAccountHandle。

 

二、PhoneAccountHandle详解

       刚才说到了PhoneAccountHandle这个词,它到底是个什么东西呢?我们先来看代码

       PhoneAccountHandle类有三个局部变量,分别是ComponentName,Id和UserHandle

/frameworks/base/telecomm/java/android/telecom/PhoneAccountHandle.java

public final class PhoneAccountHandle implements Parcelable {
    private final ComponentName mComponentName;
    private final String mId;
    private final UserHandle mUserHandle;

    ......

    public PhoneAccountHandle(
            @NonNull ComponentName componentName,
            @NonNull String id,
            @NonNull UserHandle userHandle) {
        checkParameters(componentName, userHandle);
        mComponentName = componentName;
        mId = id;
        mUserHandle = userHandle;
    }

    ......
}

下面我们一个一个来说:

1.ComponentName

    ComponentName类的作用是用来指定一个应用组件,可指定的类型有Activity,Service,BroadcastReceiver或者ContentProvider。

     我们知道,要想唯一地指定一个组件,需要包含这个组件的包名以及类名。同时也就是该类所包含的两个局部变量,mPackage和mClass。

     对于我们拨打和接听电话而言,我们刚刚在最开始提到过,PhoneAccountHandle需要提供一个ConnectionService来使Telecom和App进行通信。因此,这里要指定的,应该是一个Service类型的组件。

/frameworks/base/core/java/android/content/ComponentName.java

/**
 * Identifier for a specific application component
 * ({@link android.app.Activity}, {@link android.app.Service},
 * {@link android.content.BroadcastReceiver}, or
 * {@link android.content.ContentProvider}) that is available.  Two
 * pieces of information, encapsulated here, are required to identify
 * a component: the package (a String) it exists in, and the class (a String)
 * name inside of that package.
 * 
 */
public final class ComponentName implements Parcelable, Cloneable, Comparable<ComponentName> {
    private final String mPackage;
    private final String mClass;

    ......

    public ComponentName(@NonNull String pkg, @NonNull String cls) {
        if (pkg == null) throw new NullPointerException("package name is null");
        if (cls == null) throw new NullPointerException("class name is null");
        mPackage = pkg;
        mClass = cls;
    }

    ......

}

 

2.Id

     对于通过Sim卡创建的PhoneAccountHandle来说,id所存储的就是每张Sim卡的IccId,有的同学要问了,什么是IccId呢?

     通俗的来讲,IccId就相当于我们每张Sim卡的身份证,是每张Sim卡的唯一标识。一般来说,我们中国运营商的Sim卡都是以8986XX为开头的20位数字串(有些特殊的卡会包含字母)。

     其中,86代表中国(类似于打电话时,为什么中国号码前面都是+86)。而后面的XX,不同运营商对应着不同的值,其中移动卡可能为00 02 07等,联通卡可能为01 09等,电信卡可能为03 11等(每个运营商随着所发行的Sim卡数量的增多,为了保证IccId的唯一性,可能会添加号段)。

    那么,使用PhoneAccountHandle使用IccId作为自己的id,就可以很大程度上的保证自己的唯一性,从而更好的作为PhoneAccount的唯一标识。

 

3. UserHandle

     UserHandle又是什么呢?

     众所周知,我们的Linux系统是支持多用户的。那么,我们的Android系统是基于Linux开发而来的,(原生的Android系统)同样也是支持多用户的。只不过,由于一些OEM厂商对Android系统进行了深度定制,有可能在Settings中把设置多用户的入口给取消掉了,因此,我们看不到,也无法设置多用户。不过一般我们都是自己一个人使用手机,因此,这个功能对于我们来说,其实也可有可无。

     我们只需要知道,一般来说,我们的手机都会有一个userId为0的默认用户就可以了。

 

三、PhoneAccount详解

     通过以上的讲解,相信大家已经对PhoneAccountHandle有了一个初步的了解。我们接下来,就开始介绍PhoneAccount。老样子,我们来看代码。

 

     不难发现,PhoneAccount的构造方法是private类型的,也就是说,我们没办法直接调用其来构建PhoneAccount实例,那究竟该怎么创建PhoneAccount对象呢?这时,PhoneAccount的内部类Builder就派上了用场,不过,我们这里暂且先不提Builder的用法,等到后面讲解如何创建PhoneAccount时,再来细说。

/frameworks/base/telecomm/java/android/telecom/PhoneAccount.java

public final class PhoneAccount implements Parcelable {

    ......

    // PhoneAccount的唯一标识
    private final PhoneAccountHandle mAccountHandle;
    // Scheme与line1Number拼接而成的Uri
    private final Uri mAddress;
    // Scheme与从卡中获取的MSISDN(或CDMA卡的MDN)拼接而成的Uri
    private final Uri mSubscriptionAddress;
    // 该PhoneAccount的所能支持的能力,后面会详细讲解
    private final int mCapabilities;
    // 高亮显示的颜色
    private final int mHighlightColor;
    // 该PhoneAccount的标签
    private final CharSequence mLabel;
    // 该PhoneAccount的简短描述
    private final CharSequence mShortDescription;
    // 所能支持的uriScheme
    private final List<String> mSupportedUriSchemes;
    // 所支持的AudioRoute,例如EARPIECE(听筒)、SPEAKER(扬声器)、WIRED_HEADSET(带话筒的耳机)、BLUETOOTH(蓝牙)
    private final int mSupportedAudioRoutes;
    // 图标
    private final Icon mIcon;
    private final Bundle mExtras;
    // 是否可用
    private boolean mIsEnabled;
    // 组Id
    private String mGroupId;

    ......

    public static class Builder {

        private PhoneAccountHandle mAccountHandle;
        private Uri mAddress;
        private Uri mSubscriptionAddress;
        private int mCapabilities;
        private int mSupportedAudioRoutes = CallAudioState.ROUTE_ALL;
        private int mHighlightColor = NO_HIGHLIGHT_COLOR;
        private CharSequence mLabel;
        private CharSequence mShortDescription;
        private List<String> mSupportedUriSchemes = new ArrayList<String>();
        private Icon mIcon;
        private Bundle mExtras;
        private boolean mIsEnabled = false;
        private String mGroupId = "";

        ......

        /**
         * Creates an instance of the {@link PhoneAccount.Builder} from an existing
         * {@link PhoneAccount}.
         *
         * @param phoneAccount The {@link PhoneAccount} used to initialize the builder.
         */
        public Builder(PhoneAccount phoneAccount) {
            mAccountHandle = phoneAccount.getAccountHandle();
            mAddress = phoneAccount.getAddress();
            mSubscriptionAddress = phoneAccount.getSubscriptionAddress();
            mCapabilities = phoneAccount.getCapabilities();
            mHighlightColor = phoneAccount.getHighlightColor();
            mLabel = phoneAccount.getLabel();
            mShortDescription = phoneAccount.getShortDescription();
            mSupportedUriSchemes.addAll(phoneAccount.getSupportedUriSchemes());
            mIcon = phoneAccount.getIcon();
            mIsEnabled = phoneAccount.isEnabled();
            mExtras = phoneAccount.getExtras();
            mGroupId = phoneAccount.getGroupId();
            mSupportedAudioRoutes = phoneAccount.getSupportedAudioRoutes();
        }

        ......

        public PhoneAccount build() {
            // If no supported URI schemes were defined, assume "tel" is supported.
            if (mSupportedUriSchemes.isEmpty()) {
                addSupportedUriScheme(SCHEME_TEL);
            }

            return new PhoneAccount(
                    mAccountHandle,
                    mAddress,
                    mSubscriptionAddress,
                    mCapabilities,
                    mIcon,
                    mHighlightColor,
                    mLabel,
                    mShortDescription,
                    mSupportedUriSchemes,
                    mExtras,
                    mSupportedAudioRoutes,
                    mIsEnabled,
                    mGroupId);
        }
    }

    private PhoneAccount(
            PhoneAccountHandle account,
            Uri address,
            Uri subscriptionAddress,
            int capabilities,
            Icon icon,
            int highlightColor,
            CharSequence label,
            CharSequence shortDescription,
            List<String> supportedUriSchemes,
            Bundle extras,
            int supportedAudioRoutes,
            boolean isEnabled,
            String groupId) {
        mAccountHandle = account;
        mAddress = address;
        mSubscriptionAddress = subscriptionAddress;
        mCapabilities = capabilities;
        mIcon = icon;
        mHighlightColor = highlightColor;
        mLabel = label;
        mShortDescription = shortDescription;
        mSupportedUriSchemes = Collections.unmodifiab
  • 5
    点赞
  • 44
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值