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专栏链接

部分内容如下:

作者:帅得不敢出门

相关推荐
java资料站33 分钟前
五、Spring AI Alibaba · Memory · Saver(短期会话)
java·spring·microsoft
浪潮IT馆1 小时前
Android Studio 非最新版本下载安装教程
android·ide·android studio
夜之眷属2 小时前
Core dump 崩溃排查:JVM 宕机后,那份 core 文件怎么用 gdb 还原现场
java·运维·服务器·jvm
波加曼大王2 小时前
# vLLM不要迷信PagedAttention神话,聊聊线上藏着的内部碎片陷阱
java·架构
SL_staff2 小时前
目标健康度自检清单:开发者视角下的目标-计划-任务链路断点诊断
java·开源·github
for_ever_love__2 小时前
MySQL 高频面试题 30 问:索引、事务、锁、日志、主从与分库分表(MySQL 8.0 版)
java·数据库·spring boot·mysql·spring cloud·面试·总结
神仙别闹2 小时前
基于C++实现的贪吃蛇游戏平台
java·c++·游戏
布吉岛的石头2 小时前
Java 程序员第 49 阶段11:Java 接 BERT:用 ONNX Runtime 做句向量推理
java·人工智能·python·深度学习·bert·transformer
niucloud-admin2 小时前
JAVA V6 多商户商城 开发文档——JAVA服务端
java·开发语言
alexlifexyz2 小时前
写了个 Claude Code 插件:AI 写的 Java 违反阿里规约,就写不进文件
java