Android Framework不弹窗设置默认sim卡

文章目录

需求

当安卓手机插入多张卡时,会弹出窗口提示用户对默认卡进行选择,这里的需求是不弹出窗口,默认选择其中一张卡为默认的卡。

原生弹窗源码分析

在 Android 系统里,SimSelectNotification.java 这个类主要负责处理与 SIM 卡选择相关的通知,而 startSimSelectDialogIfNeeded 方法的用途是在有必要时启动 SIM 卡选择对话框。当设备存在多张 SIM 卡,并且系统需要用户选择使用哪张 SIM 卡来执行某些操作(如拨打电话、发送短信、使用数据流量等)时,这个方法就会发挥作用。

复制代码
packages/apps/Settings/src/com/android/settings/sim/SimSelectNotification.java

MTK可能会定制,存放在

复制代码
vendor/mediatek/proprietary/packages/apps/MtkSettings/src/com/android/settings/sim/SimSelectNotification.java

startSimSelectDialogIfNeeded函数用于启动SIM卡选择对话框

java 复制代码
/**
 * 该方法用于在必要时启动 SIM 卡选择对话框。
 * 它会根据传入的 Intent 中的信息判断是否需要弹出对话框,以及弹出何种类型的对话框。
 *
 * @param context 上下文对象,用于启动活动、发送通知等操作。
 * @param intent  包含 SIM 卡选择相关信息的 Intent 对象。
 */
private void startSimSelectDialogIfNeeded(Context context, Intent intent) {
    // 从 Intent 中获取默认 SIM 卡选择类型,若未找到则使用默认值 EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE
    int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
            EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE);

    // 如果对话框类型为 EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE,表示不需要进行任何选择操作,直接返回
    if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE) {
        return;
    }

    // 取消之前可能存在的 SIM 卡选择通知
    // 这一步是为了避免多个通知同时显示造成混淆
    cancelSimSelectNotification(context);

    // 创建一个通知,告知用户某些默认设置缺失
    // 当需要用户进行 SIM 卡选择时,先通过通知提醒用户
    createSimSelectNotification(context);

    // 如果对话框类型是 EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL,即需要选择所有默认设置
    if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
        // 从 Intent 中获取订阅 ID,若未找到则使用默认值 SubscriptionManager.DEFAULT_SUBSCRIPTION_ID
        int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_ID,
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
        // 根据订阅 ID 获取对应的 SIM 卡槽索引
        int slotIndex = SubscriptionManager.getSlotIndex(subId);
        // 如果设备中只有一个 SIM 卡订阅,询问用户是否希望将其用于所有操作
        // 创建一个新的 Intent,用于启动 SimDialogActivity 活动
        Intent newIntent = new Intent(context, SimDialogActivity.class);
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // 向 Intent 中添加对话框类型信息,这里设置为 SimDialogActivity.PREFERRED_PICK,表示选择首选 SIM 卡
        newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY,
                SimDialogActivity.PREFERRED_PICK);
        // 向 Intent 中添加首选 SIM 卡的卡槽索引
        newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, slotIndex);
        // 使用传入的上下文启动 SimDialogActivity 活动
        context.startActivity(newIntent);
    } 
    // 如果对话框类型是 EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA,即需要选择默认数据 SIM 卡
    else if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) {
        // 如果设备中有多个 SIM 卡订阅,确保用户选择默认的数据 SIM 卡
        // 创建一个新的 Intent,用于启动 SimDialogActivity 活动
        Intent newIntent = new Intent(context, SimDialogActivity.class);
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        // 向 Intent 中添加对话框类型信息,这里设置为 SimDialogActivity.DATA_PICK,表示选择数据 SIM 卡
        newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.DATA_PICK);
        // 使用传入的上下文启动 SimDialogActivity 活动
        context.startActivity(newIntent);
    }
}

修改代码实现

如果要设置默认的SIM卡,可以修改startSimSelectDialogIfNeeded实现。假设要屏蔽掉数据卡的选择弹窗,直接默认选择SIM卡2,核心思路是:删除 / 注释掉启动弹窗的代码,替换为 "直接设置 SIM 卡 2 为默认数据卡" 的逻辑,改成如下这样:

java 复制代码
import java.util.List;

private void startSimSelectDialogIfNeeded(Context context, Intent intent) {
    int dialogType = intent.getIntExtra(EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE,
            EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE);

    if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_NONE) {
        return;
    }

    cancelSimSelectNotification(context);
    createSimSelectNotification(context);

    if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_ALL) {
        int subId = intent.getIntExtra(EXTRA_SUBSCRIPTION_ID,
                SubscriptionManager.DEFAULT_SUBSCRIPTION_ID);
        int slotIndex = SubscriptionManager.getSlotIndex(subId);
        Intent newIntent = new Intent(context, SimDialogActivity.class);
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY,
                SimDialogActivity.PREFERRED_PICK);
        newIntent.putExtra(SimDialogActivity.PREFERRED_SIM, slotIndex);
        context.startActivity(newIntent);
    } 
    else if (dialogType == EXTRA_DEFAULT_SUBSCRIPTION_SELECT_TYPE_DATA) {
        /*
        Intent newIntent = new Intent(context, SimDialogActivity.class);
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        newIntent.putExtra(SimDialogActivity.DIALOG_TYPE_KEY, SimDialogActivity.DATA_PICK);
        context.startActivity(newIntent);
        */
// 1. 获取SubscriptionManager(SIM卡管理核心类)
    SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
    // 2. 获取所有激活的SIM卡信息
    List<SubscriptionInfo> activeSubs = subscriptionManager.getActiveSubscriptionInfoList();
    if (activeSubs != null && activeSubs.size() >= 2) {
        // 3. 定位SIM卡2(卡槽索引1,AOSP卡槽索引从0开始:0=卡1,1=卡2)
        SubscriptionInfo sim2Info = subscriptionManager.getActiveSubscriptionInfoForSimSlotIndex(1);
        if (sim2Info != null) {
            // 4. 强制设置SIM卡2为默认数据卡
            subscriptionManager.setDefaultDataSubId(sim2Info.getSubscriptionId());
            // 可选:标记数据卡已设置,避免系统重复触发弹窗
            Settings.Secure.putInt(context.getContentResolver(), "def_preferred_network_mode", sim2Info.getSubscriptionId());
        }
    }
}

验证效果

  1. 重新编译 Settings 模块:
bash 复制代码
mmm packages/apps/Settings/
  1. 刷入编译后的Settings.apk到设备(或全编译系统镜像);
  2. 重启设备,插入双 SIM 卡后:
    3.1 不再弹出 "选择默认数据卡" 的弹窗;
    3.2 进入 "设置 - 移动网络/蜂窝网络 - 默认数据卡",确认已自动选中 SIM 卡 2;
    3.3 测试数据网络,确认流量走 SIM 卡 2。


Android Framework专栏

Android Framework专栏链接

部分内容如下:

作者:帅得不敢出门

相关推荐
草莓熊Lotso15 小时前
Linux 文件描述符与重定向实战:从原理到 minishell 实现
android·linux·运维·服务器·数据库·c++·人工智能
大模型玩家七七15 小时前
基于语义切分 vs 基于结构切分的实际差异
java·开发语言·数据库·安全·batch
恋猫de小郭15 小时前
Flutter Zero 是什么?它的出现有什么意义?为什么你需要了解下?
android·前端·flutter
寻星探路20 小时前
【深度长文】万字攻克网络原理:从 HTTP 报文解构到 HTTPS 终极加密逻辑
java·开发语言·网络·python·http·ai·https
工程师老罗1 天前
如何在Android工程中配置NDK版本
android
曹牧1 天前
Spring Boot:如何测试Java Controller中的POST请求?
java·开发语言
爬山算法1 天前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
kfyty7251 天前
集成 spring-ai 2.x 实践中遇到的一些问题及解决方案
java·人工智能·spring-ai
猫头虎1 天前
如何排查并解决项目启动时报错Error encountered while processing: java.io.IOException: closed 的问题
java·开发语言·jvm·spring boot·python·开源·maven