快捷开关之移动数据

概览

移动数据开关作为快捷开关的三大金刚之一,重要性不言而喻。作为日常高频使用的开关之一,承载了及其重要的功能。在Flyme6之前,4G还未普及,流量金贵,所以切换菜单中加入了2G,3G,4G的功能,而在Flyme7的过渡中,双卡用户增加,所以将切换菜单中网络模式切换更换为主副卡切换功能。后续跟随用户反馈,可能会将这两个功能同时加入

背景知识

一些需要知道的基础知识

  • mSubscriptionManager.getActiveSubscriptionInfoCount()指所有插入的卡,包含当前禁用的SIM卡,当前禁用的卡使用isRadioOn()来判断

  • mTelephonyManager.getSimCount()判断是判断当前手机是单卡还是双卡手机,而不是判断当前插入SIM卡的数量

  • mTelephonyManager.getSimState() == SIM_STATE_READY这个状态获取的是先识别到的那张卡,一般是卡1,所以需要改用mTelephonyManager.getSimState(int slotId)这个接口分别获取两张卡的状态

  • phoneId,slotId,这两个类似,对应卡槽1,卡槽2,值为0和1

  • subId,对应SIM卡,从0开始递增,每次插入一张新的SiM卡subid都会+1

  • 卡的名称需要获取卡的subid之后自己去取名称

    1
    2
    3
    4
    5
    6
    /**
    * @return the name displayed to the user that identifies this subscription
    */
    public CharSequence getDisplayName() {
    return this.mDisplayName;
    }
  • 软卡就是软件模拟的一个卡,跟真正插卡一样的软卡也会占用一个实体卡槽,启用软卡的卡槽在插卡就没有用了

正文

开关移动数据

点击设置
android自身提供了接口操作移动数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* Turns mobile data on or off.
* If this object has been created with {@link #createForSubscriptionId}, applies to the given
* subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()}
*
* <p>Requires Permission:
* {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} or that the
* calling app has carrier privileges.
*
* @param enable Whether to enable mobile data.
*
* @see #hasCarrierPrivileges
*/
@RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE)
public void setDataEnabled(boolean enable) {
setDataEnabled(getDefaultDataSubscriptionId(), enable);
}

响应
也有对应的获取移动数据状态接口,但是比较耗时,所以Flyme使用监听数据库字段的方式来响应移动数据的变化,监听路径区分单双卡手机

  • 单卡:Uri mobileDataUri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA);
  • 双卡:Uri mobileDataUri = Settings.Global.getUriFor(Settings.Global.MOBILE_DATA + mDefaultDataSubscriptionId)

双卡手机的监听会涉及到defaultDataSubscriptionId的合法性,在开机或插拔SIM卡时,如果SIM卡状态没有及时准备好,获取的defaultDataSubscriptionId可能是非法的,所以需要监听ACTION_SIM_STATE_CHANGED来多次获取确保注册的数据库路径是正确的

切换卡

切换设置

  • 设置主卡:
    SubscriptionManager.setDefaultDataSubId()

  • 获取主卡状态:
    SubscriptionManager.getDefaultDataSubscriptionId() 可以获取数据卡的subid

切换卡的业务比较复杂,需要管理的细节也比较多,我们来通过UI状态来划分这些细节
UI状态,有两种:一种是整个VIew置灰,不响应用户操作,还有一种隐藏dual图标,不响应用户切换卡,我们接下来从这两个状态细说

View置灰
由当前是否可以开关移动数据和底层的CallBackInfo状态决定

1
2
final boolean enabled = mDataController.isMobileDataSupported()
&& !cb.noSim && !cb.airplaneModeEnabled && cb.enabled;

隐藏Dual图标
是否隐藏由3个情况判断

1
2
3
4
@Override
public boolean supportsDualTargets() {
return mDataController.canConfigSubId() && mDataController.isMobileDataEnabled() && mDataController.isDualEnabled();
}
  • 移动数据开启mDataController.isMobileDataEnabled():只有移动数据开启才支持双卡切换
  • 硬件(或编译)是否支持双卡mDataController.canConfigSubId():支持双卡手机、非移动入库定制版
  • 根据当前状态动态判断是否支持双卡mDataController.isDualEnabled()
    • 当前插入卡数量(可能为空)
    • 当前是否双卡都启用(可在设置中禁用启用)
    • 是否正在通话(通话过程禁止切换卡)
    • 是否启用软卡(阮卡默认为主卡,且不支持切换)
    • 是否正在切换卡

状态获取
以上两个节讲完了切换卡可能的UI状态以及决定状态的判断条件,下面来分析一下这些状态该从哪里获取

所有的这些状态我们主要通过广播来决定刷新的时机

  • 双卡状态刷新时机

    • ACTION_SIM_STATE_CHANGED,用于监听SIM的状态变化,相当于硬件设备在开机过程中从准备到完成的状态,无法跟踪主卡的状态
    • ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED,监听这个广播, 在数据卡(也即主卡)变化时可以获取通知,这个时候就可以更新主卡ID
      注:数据库中有个Uri与这个广播是一样的功能:Settings.Global.MULTI_SIM_DATA_CALL_SUBSCRIPTION
    • ACTION_SERVICE_STATE_CHANGED,监听当前服务状态,是否驻网脱网
    • ACTION_SUBINFO_RECORD_UPDATED,可以用于监听双卡启用停用
  • 切换卡状态刷新时机

    • ACTION_MAIN_SLOT_CHANGED(高通,samsung) | ACTION_SET_RADIO_CAPABILITY_DONE(mtk),用于监听双卡切换完毕
      注:ACTION_SET_RADIO_CAPABILITY_DONE是google字段,所以三个平台都有,MAIN_SLOT可能会有平台缺少的问题
  • 电话状态刷新时机

    • ACTION_PHONE_STATE_CHANGED,用于电话状态变化的广播,只有在第一次来电话之后才会触发,注意初始化值
  • 网络制式发生变化时机(目前暂未用到)

    • ACTION_RADIO_TECHNOLOGY_CHANGED 与 ACTION_RAT_CHANGED:用于radio的类型变化 When the radio changes (ex: CDMA->GSM), refresh all options.

切换网络模式

当前已经去除,后续可能增加

注意事项

  • 解完BUG之后,记得判断处理默认状态,一定要重启去check状态是否异常

1
2
3
4
//FLYME:wanglong@CommSrv.Telephony.Bugfix#481606 {@
int SimMode = Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.MSIM_MODE_SETTING, -1);
//@}

这段代码中,MSIM_MODE_SETTINGS中,MTK在Global数据库里,三星和高通在System数据库里,使用的时候注意区分在AndroidL中,MTK也位于System数据库

作者

0xforee

发布于

2017-03-05

更新于

2017-03-07

许可协议


欢迎关注我的公众号 0xforee,第一时间获取更多有价值的思考

评论