Android通过反射根据卡槽来开启关闭sim卡的漫游

前提:清单文件根标签添加

android:sharedUserId="android.uid.system"

剩下的都在代码里了

package com.example.myapplication;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.pm.PackageManager;
import android.os.Build;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.widget.Toast;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;

public class SimRoamingUtil {

    private static final String TAG = "SimRoamingUtil";

    /**
     * 方法一:无法根据卡槽索引设置漫游开关
     * @param enable
     * @return
     */
    public static boolean setMobileDataRoamingEnable(boolean enable) {
        try {
            Class<?> serviceManager = Class.forName("com.android.internal.telephony.PhoneFactory");
            Method method = serviceManager.getMethod("getDefaultPhone");
            method.setAccessible(true);


            //拿到phone的实例化对象
            Object phoneObject = method.invoke(serviceManager.newInstance());
            Class<?> phoneClass = Class.forName("com.android.internal.telephony.Phone");
            //Class phoneClass = phoneObject.getClass();

            //调用phone方法
            Method setDataRoamingEnabledMethod = phoneClass.getMethod("setDataRoamingEnabled", boolean.class);
            setDataRoamingEnabledMethod.setAccessible(true);
            setDataRoamingEnabledMethod.invoke(phoneObject, true);
        } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException |
                 IllegalAccessException | InstantiationException e) {
            throw new RuntimeException(e);
        }
        return enable;
    }

    /**
     * 方法二:根据卡槽索引设置漫游开关
     * @param context
     * @param slotIndex
     * @param enable
     */
    @SuppressLint("MissingPermission")
    public static void setMobileDataRoamingEnableBySlot(Context context, int slotIndex, boolean enable) {

        SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
        List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
        SubscriptionInfo subscriptionInfo = null;

        for (SubscriptionInfo info : subscriptionInfoList) {
            if (info.getSimSlotIndex() == slotIndex) {
                subscriptionInfo = info;
                break;
            }
        }
        if (subscriptionInfo != null) {
            int subscriptionId = subscriptionInfo.getSubscriptionId();

            try {
                Method getPhoneIdMethod = SubscriptionManager.class.getMethod("getPhoneId", int.class);
                getPhoneIdMethod.setAccessible(true);
                int phoneId = (int) getPhoneIdMethod.invoke(subscriptionManager, subscriptionId);

                Class<?> serviceManager = Class.forName("com.android.internal.telephony.PhoneFactory");
                Method getPhoneMethod = serviceManager.getMethod("getPhone", int.class);

                getPhoneMethod.setAccessible(true);
                //根据phoneId 获取phone的实例
                Object phoneObject = getPhoneMethod.invoke(serviceManager.newInstance(), phoneId);

                Class<?> phoneClass = Class.forName("com.android.internal.telephony.Phone");

                //调用phone的setDataRoamingEnabled方法
                Method setDataRoamingEnabledMethod = phoneClass.getMethod("setDataRoamingEnabled", boolean.class);
                setDataRoamingEnabledMethod.setAccessible(true);
                setDataRoamingEnabledMethod.invoke(phoneObject, enable);

            } catch (ClassNotFoundException | InvocationTargetException | NoSuchMethodException |
                     IllegalAccessException | InstantiationException e) {
                throw new RuntimeException(e);
            }
        }

    }

    /**
     * 方法三:可根据卡槽索引设置,但仅支持Android 10 以上
     * @param context
     * @param slotIndex
     * @param enable
     */
    @SuppressLint("MissingPermission")
    public static void setSimRoamingForAndroidQ(Context context, int slotIndex, boolean enable) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
            SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
            List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
            SubscriptionInfo subscriptionInfo = null;

            for (SubscriptionInfo info : subscriptionInfoList) {
                if (info.getSimSlotIndex() == slotIndex) {
                    subscriptionInfo = info;
                    break;
                }
            }

            if (subscriptionInfo != null) {
                int subscriptionId = subscriptionInfo.getSubscriptionId();
                try {
                    // Get TelephonyManager by subscription ID
                    Method getTelephonyManagerMethod = TelephonyManager.class.getDeclaredMethod("createForSubscriptionId",
                            int.class);
                    Object telephonyManagerForSlot = getTelephonyManagerMethod.invoke(telephonyManager, subscriptionId);

                    // Get method to set data roaming
                    Method setDataRoamingEnabledMethod = telephonyManager.getClass().getDeclaredMethod("setDataRoamingEnabled", boolean.class);
                    setDataRoamingEnabledMethod.invoke(telephonyManagerForSlot, enable);

                } catch (NoSuchMethodException | IllegalAccessException |
                         InvocationTargetException e) {
                    throw new RuntimeException(e);
                }

            } else {
                Toast.makeText(context, "SIM card not found in slot index", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

但是要注意,使用方法1和方法2时,还需要在清单文件相应的activity 中添加,

android:process="com.android.phone"

例:

<activity android:name=".MainActivity"
    android:process="com.android.phone">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

因为只有phone进程才能调用phone对象

猜你喜欢

转载自blog.csdn.net/qq_36162336/article/details/131393628