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

部分内容如下:

作者:帅得不敢出门

相关推荐
技术摆渡人2 小时前
RK3588 边缘 AI 深度开发指南:从 Android NNAPI 源码到 LLM 大模型性能调优
android·人工智能
是一个Bug2 小时前
Java基础 -> JVM -> 并发 -> 框架 -> 分布式
java·jvm·分布式
a努力。2 小时前
小红书Java面试被问:如何设计一个分布式ID生成器
java·后端·面试
sinat_384241092 小时前
从零开始打造一个 Android 音乐播放器(Kotlin + Jetpack Compose)
android·开发语言·kotlin
cyw89982 小时前
手动安装mysql8.0.44
android
czlczl200209252 小时前
Spring Security 进阶:基于 Customizer 的分布式权限配置架构设计
java·spring boot·分布式·后端·spring
lkbhua莱克瓦242 小时前
面向编程3-UDP通信程序
java·网络·网络协议·udp
shepherd1262 小时前
从入门到实践:玩转分布式链路追踪利器SkyWalking
java·分布式·后端·skywalking
Seven972 小时前
剑指offer-54、字符流中第一个不重复的字符
java