问题(需求):

Android M的双卡手机上,当手机中插入漫游卡的时候,状态栏会弹出一个漫游警告(Title “Data roaming” ContentText “You've lost data connectivity because you left your home network with data roaming turned off”)的Notification,然后点击这个漫游警告之后跳到网络设置(MobileNetworkSetting)默认卡1的设置,不会跳到漫游卡对应的设置。现在的需求是,无论漫游卡在卡1还是卡2,点了漫游警告的Notification都要跳到漫游卡的网络设置页。

分析:

首先这不是一个bug,是系统本身就没实现这个功能。如果要实现这个功能,那么我就要在合适的地方来增加一个参数来确定漫游卡的位置。因为是卡的位置,所以用SloId来确定位置是比较好的。

需求实现:

漫游警告显示的原理

因为之前研究过漫游警告的代码,所以比较清楚这个警告弹出来的条件,代码块如下: PhoneGlobal.java

    // The "data disconnected due to roaming" notification is shown
    // if (a) you have the "data roaming" feature turned off, and
    // (b) you just lost data connectivity because you're roaming.
    boolean disconnectedDueToRoaming =
            !phone.getDataRoamingEnabled()
            && PhoneConstants.DataState.DISCONNECTED.equals(state)
            && Phone.REASON_ROAMING_ON.equals(
                intent.getStringExtra(PhoneConstants.STATE_CHANGE_REASON_KEY));
    if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) {
        mDataDisconnectedDueToRoaming = disconnectedDueToRoaming;
        mHandler.sendEmptyMessage(disconnectedDueToRoaming
                ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK);
    }

然后调用NotificationMgr.java中的方法显示漫游警告

case EVENT_DATA_ROAMING_DISCONNECTED:
                    notificationMgr.showDataDisconnectedRoaming();

可以看到方法里是没有带参数的,也就是说显示通知的时候不区分SIM卡的位置。 下面是具体的发出通知的代码,构建Notification,填充信息,notify显示Notification。 NotificationMgr.java

/**
     * Shows the "data disconnected due to roaming" notification, which
     * appears when you lose data connectivity because you're roaming and
     * you have the "data roaming" feature turned off.
     */
    /* package */ void showDataDisconnectedRoaming() {
        if (DBG) log("showDataDisconnectedRoaming()...");

        // "Mobile network settings" screen / dialog
        Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);//点击通知后跳转的目标Activity
        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent, 0);

        final CharSequence contentText = mContext.getText(R.string.roaming_reenable_message);

        final Notification.Builder builder = new Notification.Builder(mContext)
                .setSmallIcon(android.R.drawable.stat_sys_warning)
                .setContentTitle(mContext.getText(R.string.roaming))
                .setColor(mContext.getResources().getColor(R.color.dialer_theme_color))
                .setContentText(contentText);

        List<UserInfo> users = mUserManager.getUsers(true);
        for (int i = 0; i < users.size(); i++) {
            final UserInfo user = users.get(i);
            if (user.isManagedProfile()) {
                continue;
            }
            UserHandle userHandle = user.getUserHandle();
            builder.setContentIntent(userHandle.isOwner() ? contentIntent : null);
            final Notification notif =
                    new Notification.BigTextStyle(builder).bigText(contentText).build();
            mNotificationManager.notifyAsUser(
                    null /* tag */, DATA_DISCONNECTED_ROAMING_NOTIFICATION, notif, userHandle);
        }
    }

我们要做的就是在上述代码中添加一个可以区分漫游卡的变量。

功能实现的代码

首先在判断到因漫游而断开数据链接的时候把对应的SIM卡的SlotId记录下来

        if (mDataDisconnectedDueToRoaming != disconnectedDueToRoaming) {
            int defaultDataSubId = SubscriptionManager.getDefaultDataSubId();//默认数据卡的SubId
            roamingSlotId = SubscriptionManager.getSlotId(defaultDataSubId);//用数据卡的subId获得它的SlotId
            mDataDisconnectedDueToRoaming = disconnectedDueToRoaming;
            mHandler.sendEmptyMessage(disconnectedDueToRoaming
                    ? EVENT_DATA_ROAMING_DISCONNECTED : EVENT_DATA_ROAMING_OK);
        }

之后将roamingSlotId传入showDataDisconnectedRoaming()方法,然后把这个值用putExtra的方式放入目标Activity的Intent里面。

        Intent intent = new Intent(mContext, com.android.phone.MobileNetworkSettings.class);
        intent.putExtra(ROAMING_SLOT_ID, roamingSlotId);
        PendingIntent contentIntent = PendingIntent.getActivity(mContext, 0, intent,
                PendingIntent.FLAG_UPDATE_CURRENT);//注意这个flag也要一起修改

最后在目标Activity启动的时候,在onCreate()方法里取出这个值,并设置显示对应漫游卡的tab MobileNetworkSettings.java

        int roamingSlotId = getIntent().getIntExtra(ROAMING_SLOT_ID, -1);
        if (roamingSlotId != -1) {
            mTabHost.setCurrentTab(roamingSlotId);
        }

done。 已提交给CM https://review.lineageos.org/#/c/140632/