Android : Check whether the phone is dual SIM

前端 未结 8 1953
轻奢々
轻奢々 2020-11-22 01:38

After a lot of research on forums, now I know that there is no way to find IMSI or SIM serial number for both the SIM cards in a dual SIM phone (except for contacting the ma

相关标签:
8条回答
  • 2020-11-22 01:44

    There are several native solutions I've found while searching the way to check network operator.

    For API >=17:

    TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    
    // Get information about all radio modules on device board
    // and check what you need by calling #getCellIdentity.
    
    final List<CellInfo> allCellInfo = manager.getAllCellInfo();
    for (CellInfo cellInfo : allCellInfo) {
        if (cellInfo instanceof CellInfoGsm) {
            CellIdentityGsm cellIdentity = ((CellInfoGsm) cellInfo).getCellIdentity();
            //TODO Use cellIdentity to check MCC/MNC code, for instance.
        } else if (cellInfo instanceof CellInfoWcdma) {
            CellIdentityWcdma cellIdentity = ((CellInfoWcdma) cellInfo).getCellIdentity();
        } else if (cellInfo instanceof CellInfoLte) {
            CellIdentityLte cellIdentity = ((CellInfoLte) cellInfo).getCellIdentity();
        } else if (cellInfo instanceof CellInfoCdma) {
            CellIdentityCdma cellIdentity = ((CellInfoCdma) cellInfo).getCellIdentity();
        } 
    }
    

    In AndroidManifest add permission:

    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    </manifest>
    

    To get network operator you can check mcc and mnc codes:

    • https://en.wikipedia.org/wiki/Mobile_country_code (general information).
    • https://clients.txtnation.com/hc/en-us/articles/218719768-MCCMNC-mobile-country-code-and-mobile-network-code-list- (quite full and quite latest list of operators).

    For API >=22:

    final SubscriptionManager subscriptionManager = SubscriptionManager.from(context);
    final List<SubscriptionInfo> activeSubscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList();
    for (SubscriptionInfo subscriptionInfo : activeSubscriptionInfoList) {
        final CharSequence carrierName = subscriptionInfo.getCarrierName();
        final CharSequence displayName = subscriptionInfo.getDisplayName();
        final int mcc = subscriptionInfo.getMcc();
        final int mnc = subscriptionInfo.getMnc();
        final String subscriptionInfoNumber = subscriptionInfo.getNumber();
    }
    

    For API >=23. To just check if phone is dual/triple/many sim:

    TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
    if (manager.getPhoneCount() == 2) {
        // Dual sim
    }
    
    0 讨论(0)
  • 2020-11-22 01:45

    I have found these system properties on Samsung S8

    SystemProperties.getInt("ro.multisim.simslotcount", 1) > 1
    

    Also, according to the source: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/com/android/internal/telephony/TelephonyProperties.java

    getprop persist.radio.multisim.config returns "dsds" or "dsda" on multi sim.

    I have tested this on Samsung S8 and it works

    0 讨论(0)
  • 2020-11-22 01:46

    Update 23 March'15 :

    Official multiple SIM API is available now from Android 5.1 onwards

    Other possible option :

    You can use Java reflection to get both IMEI numbers.

    Using these IMEI numbers you can check whether the phone is a DUAL SIM or not.

    Try following activity :

    import android.app.Activity;
    import android.os.Bundle;
    import android.widget.TextView;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            TelephonyInfo telephonyInfo = TelephonyInfo.getInstance(this);
    
            String imeiSIM1 = telephonyInfo.getImsiSIM1();
            String imeiSIM2 = telephonyInfo.getImsiSIM2();
    
            boolean isSIM1Ready = telephonyInfo.isSIM1Ready();
            boolean isSIM2Ready = telephonyInfo.isSIM2Ready();
    
            boolean isDualSIM = telephonyInfo.isDualSIM();
    
            TextView tv = (TextView) findViewById(R.id.tv);
            tv.setText(" IME1 : " + imeiSIM1 + "\n" +
                    " IME2 : " + imeiSIM2 + "\n" +
                    " IS DUAL SIM : " + isDualSIM + "\n" +
                    " IS SIM1 READY : " + isSIM1Ready + "\n" +
                    " IS SIM2 READY : " + isSIM2Ready + "\n");
        }
    }
    

    And here is TelephonyInfo.java :

    import java.lang.reflect.Method;
    
    import android.content.Context;
    import android.telephony.TelephonyManager;
    
    public final class TelephonyInfo {
    
        private static TelephonyInfo telephonyInfo;
        private String imeiSIM1;
        private String imeiSIM2;
        private boolean isSIM1Ready;
        private boolean isSIM2Ready;
    
        public String getImsiSIM1() {
            return imeiSIM1;
        }
    
        /*public static void setImsiSIM1(String imeiSIM1) {
            TelephonyInfo.imeiSIM1 = imeiSIM1;
        }*/
    
        public String getImsiSIM2() {
            return imeiSIM2;
        }
    
        /*public static void setImsiSIM2(String imeiSIM2) {
            TelephonyInfo.imeiSIM2 = imeiSIM2;
        }*/
    
        public boolean isSIM1Ready() {
            return isSIM1Ready;
        }
    
        /*public static void setSIM1Ready(boolean isSIM1Ready) {
            TelephonyInfo.isSIM1Ready = isSIM1Ready;
        }*/
    
        public boolean isSIM2Ready() {
            return isSIM2Ready;
        }
    
        /*public static void setSIM2Ready(boolean isSIM2Ready) {
            TelephonyInfo.isSIM2Ready = isSIM2Ready;
        }*/
    
        public boolean isDualSIM() {
            return imeiSIM2 != null;
        }
    
        private TelephonyInfo() {
        }
    
        public static TelephonyInfo getInstance(Context context){
    
            if(telephonyInfo == null) {
    
                telephonyInfo = new TelephonyInfo();
    
                TelephonyManager telephonyManager = ((TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE));
    
                telephonyInfo.imeiSIM1 = telephonyManager.getDeviceId();;
                telephonyInfo.imeiSIM2 = null;
    
                try {
                    telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceIdGemini", 0);
                    telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceIdGemini", 1);
                } catch (GeminiMethodNotFoundException e) {
                    e.printStackTrace();
    
                    try {
                        telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceId", 0);
                        telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceId", 1);
                    } catch (GeminiMethodNotFoundException e1) {
                        //Call here for next manufacturer's predicted method name if you wish
                        e1.printStackTrace();
                    }
                }
    
                telephonyInfo.isSIM1Ready = telephonyManager.getSimState() == TelephonyManager.SIM_STATE_READY;
                telephonyInfo.isSIM2Ready = false;
    
                try {
                    telephonyInfo.isSIM1Ready = getSIMStateBySlot(context, "getSimStateGemini", 0);
                    telephonyInfo.isSIM2Ready = getSIMStateBySlot(context, "getSimStateGemini", 1);
                } catch (GeminiMethodNotFoundException e) {
    
                    e.printStackTrace();
    
                    try {
                        telephonyInfo.isSIM1Ready = getSIMStateBySlot(context, "getSimState", 0);
                        telephonyInfo.isSIM2Ready = getSIMStateBySlot(context, "getSimState", 1);
                    } catch (GeminiMethodNotFoundException e1) {
                        //Call here for next manufacturer's predicted method name if you wish
                        e1.printStackTrace();
                    }
                }
            }
    
            return telephonyInfo;
        }
    
        private static String getDeviceIdBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {
    
            String imei = null;
    
            TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    
            try{
    
                Class<?> telephonyClass = Class.forName(telephony.getClass().getName());
    
                Class<?>[] parameter = new Class[1];
                parameter[0] = int.class;
                Method getSimID = telephonyClass.getMethod(predictedMethodName, parameter);
    
                Object[] obParameter = new Object[1];
                obParameter[0] = slotID;
                Object ob_phone = getSimID.invoke(telephony, obParameter);
    
                if(ob_phone != null){
                    imei = ob_phone.toString();
    
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new GeminiMethodNotFoundException(predictedMethodName);
            }
    
            return imei;
        }
    
        private static  boolean getSIMStateBySlot(Context context, String predictedMethodName, int slotID) throws GeminiMethodNotFoundException {
    
            boolean isReady = false;
    
            TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    
            try{
    
                Class<?> telephonyClass = Class.forName(telephony.getClass().getName());
    
                Class<?>[] parameter = new Class[1];
                parameter[0] = int.class;
                Method getSimStateGemini = telephonyClass.getMethod(predictedMethodName, parameter);
    
                Object[] obParameter = new Object[1];
                obParameter[0] = slotID;
                Object ob_phone = getSimStateGemini.invoke(telephony, obParameter);
    
                if(ob_phone != null){
                    int simState = Integer.parseInt(ob_phone.toString());
                    if(simState == TelephonyManager.SIM_STATE_READY){
                        isReady = true;
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
                throw new GeminiMethodNotFoundException(predictedMethodName);
            }
    
            return isReady;
        }
    
    
        private static class GeminiMethodNotFoundException extends Exception {
    
            private static final long serialVersionUID = -996812356902545308L;
    
            public GeminiMethodNotFoundException(String info) {
                super(info);
            }
        }
    }
    

    Edit :

    Getting access of methods like "getDeviceIdGemini" for other SIM slot's detail has prediction that method exist.

    If that method's name doesn't match with one given by device manufacturer than it will not work. You have to find corresponding method name for those devices.

    Finding method names for other manufacturers can be done using Java reflection as follows :

    public static void printTelephonyManagerMethodNamesForThisDevice(Context context) {
    
        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        Class<?> telephonyClass;
        try {
            telephonyClass = Class.forName(telephony.getClass().getName());
            Method[] methods = telephonyClass.getMethods();
            for (int idx = 0; idx < methods.length; idx++) {
    
                System.out.println("\n" + methods[idx] + " declared by " + methods[idx].getDeclaringClass());
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    } 
    

    EDIT :

    As Seetha pointed out in her comment :

    telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getDeviceIdDs", 0);
    telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getDeviceIdDs", 1); 
    

    It is working for her. She was successful in getting two IMEI numbers for both the SIM in Samsung Duos device.

    Add <uses-permission android:name="android.permission.READ_PHONE_STATE" />

    EDIT 2 :

    The method used for retrieving data is for Lenovo A319 and other phones by that manufacture (Credit Maher Abuthraa):

    telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 0); 
    telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 1); 
    
    0 讨论(0)
  • 2020-11-22 01:50

    Tips:

    You can try to use

    ctx.getSystemService("phone_msim")

    instead of

    ctx.getSystemService(Context.TELEPHONY_SERVICE)

    If you have already tried Vaibhav's answer and telephony.getClass().getMethod() fails, above is what works for my Qualcomm mobile.

    0 讨论(0)
  • 2020-11-22 01:52

    I am able to read both the IMEI's from OnePlus 2 Phone

     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    TelephonyManager manager = (TelephonyManager) getActivity().getSystemService(Context.TELEPHONY_SERVICE);
                    Log.i(TAG, "Single or Dual Sim " + manager.getPhoneCount());
                    Log.i(TAG, "Default device ID " + manager.getDeviceId());
                    Log.i(TAG, "Single 1 " + manager.getDeviceId(0));
                    Log.i(TAG, "Single 2 " + manager.getDeviceId(1));
                }
    
    0 讨论(0)
  • 2020-11-22 01:55

    I have a Samsung Duos device with Android 4.4.4 and the method suggested by Seetha in the accepted answer (i.e. call getDeviceIdDs) does not work for me, as the method does not exist. I was able to recover all the information I needed by calling method "getDefault(int slotID)", as shown below:

    public static void samsungTwoSims(Context context) {
        TelephonyManager telephony = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
    
        try{
    
            Class<?> telephonyClass = Class.forName(telephony.getClass().getName());
    
            Class<?>[] parameter = new Class[1];
            parameter[0] = int.class;
            Method getFirstMethod = telephonyClass.getMethod("getDefault", parameter);
    
            Log.d(TAG, getFirstMethod.toString());
    
            Object[] obParameter = new Object[1];
            obParameter[0] = 0;
            TelephonyManager first = (TelephonyManager) getFirstMethod.invoke(null, obParameter);
    
            Log.d(TAG, "Device Id: " + first.getDeviceId() + ", device status: " + first.getSimState() + ", operator: " + first.getNetworkOperator() + "/" + first.getNetworkOperatorName());
    
            obParameter[0] = 1;
            TelephonyManager second = (TelephonyManager) getFirstMethod.invoke(null, obParameter);
    
            Log.d(TAG, "Device Id: " + second.getDeviceId() + ", device status: " + second.getSimState()+ ", operator: " + second.getNetworkOperator() + "/" + second.getNetworkOperatorName());
        } catch (Exception e) {
            e.printStackTrace();
        }   
    }
    

    Also, I rewrote the code that iteratively tests for methods to recover this information so that it uses an array of method names instead of a sequence of try/catch. For instance, to determine if we have two active SIMs we could do:

    private static String[] simStatusMethodNames = {"getSimStateGemini", "getSimState"};
    
    
    public static boolean hasTwoActiveSims(Context context) {
        boolean first = false, second = false;
    
        for (String methodName: simStatusMethodNames) {
            // try with sim 0 first
            try {
                first = getSIMStateBySlot(context, methodName, 0);
                // no exception thrown, means method exists
                second = getSIMStateBySlot(context, methodName, 1);
               return first && second;
            } catch (GeminiMethodNotFoundException e) {
                // method does not exist, nothing to do but test the next
            }
        }
        return false;
    }
    

    This way, if a new method name is suggested for some device, you can simply add it to the array and it should work.

    0 讨论(0)
提交回复
热议问题