Android: vérifiez si le téléphone est à double carte SIM

113

Après de nombreuses recherches sur les forums, je sais maintenant qu'il n'y a aucun moyen de trouver le numéro de série IMSI ou SIM pour les deux cartes SIM dans un téléphone double SIM (sauf pour contacter le fabricant). Maintenant, ma question modifiée est la suivante: pouvons-nous détecter que le téléphone a deux cartes SIM? Je pense que cela peut être détecté avec une certaine intelligence. Il y a quelques façons dont je peux penser:

  1. Composer un code USSD et tracer les journaux pour le numéro IMEI (j'ai essayé cela avec * 139 # en Inde. Cela a fonctionné.) Cela me donnera le numéro IMEI pour la carte SIM à partir de laquelle j'ai composé le code USSD. (Il est présumé que le téléphone suit les directives d'Android et possède deux numéros IMEI.)

  2. Stockage du numéro de série SIM et / ou IMSI de la carte SIM. Et après détection de tout autre numéro IMSI / série même si le téléphone n'a pas été redémarré (c'est-à-dire que la carte SIM a été commutée) en traçant certains journaux ou par une gestion des événements de diffusion.

  3. En composant le * 06 #, vous pourrez voir les deux numéros IMEI. D'une certaine manière, obtenez ces deux chiffres. (Quelque chose comme la capture d'écran et l'analyse d'image pour le texte.)

Si quelqu'un peut penser à d'autres moyens, ils sont les bienvenus. J'apprécierais vraiment toute sorte d'aide à ce sujet. De plus, si quelqu'un a des informations sur les API des fabricants ou des liens pour les contacter, veuillez les partager avec les membres de la communauté.

Rajkiran
la source
Salut Rajkiran, Enfin, j'ai eu la solution qui fonctionne très bien pour moi. J'espère que cela devrait être utile pour tous ceux qui souhaitent gérer Duel SIM dans les applications mobiles. L'API de poignée SIM duel n'est pas documentée. Veuillez vérifier ma réponse, cela fonctionne bien pour moi. stackoverflow.com/questions/17618651/…
Jebasuthan
1
Merci .. mais votre réponse ne répond pas à ma question. Je veux tous les détails sur la deuxième carte SIM et IMEI. La réponse de @Pied Piper m'aide à tout obtenir.
Rajkiran
La réponse de @Rajkiran Pied Piper vous a vraiment aidé? J'ai vérifié son code dans m samsung galaxy y duos mais cela ne fonctionne pas.
Nitish Patel
@nitishpatel: Oui, ça a vraiment aidé. Malheureusement, je n'ai pas de Y Duos à vérifier. Mais je pense que Samsung utilise un mécanisme différent pour la gestion de la double carte SIM à partir de la version Android 4.0. La réponse de Pied Pipers aide dans les appareils à partir de la version 4.0. Pour le reste, vous devrez creuser un peu plus en utilisant la réflexion.
Rajkiran
Salut, je trouve une solution ... veuillez vérifier le code stackoverflow.com/a/32304799/3131373 Il est testé sur divers téléphones
user3131373

Réponses:

184

Mise à jour du 23 mars'15:

L'API officielle de plusieurs SIM est maintenant disponible à partir d'Android 5.1

Autre option possible:

Vous pouvez utiliser la réflexion Java pour obtenir les deux numéros IMEI.

En utilisant ces numéros IMEI, vous pouvez vérifier si le téléphone est une double carte SIM ou non.

Essayez l'activité suivante:

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");
    }
}

Et voici 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);
        }
    }
}

Éditer :

L'accès à des méthodes telles que "getDeviceIdGemini" pour les détails d'un autre emplacement SIM permet de prédire l'existence de cette méthode.

Si le nom de cette méthode ne correspond pas à celui donné par le fabricant de l'appareil, cela ne fonctionnera pas. Vous devez trouver le nom de méthode correspondant à ces appareils.

La recherche de noms de méthodes pour d'autres fabricants peut être effectuée à l'aide de la réflexion Java comme suit:

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();
    }
} 

ÉDITER :

Comme Seetha l'a souligné dans son commentaire:

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

Cela fonctionne pour elle. Elle a réussi à obtenir deux numéros IMEI pour la carte SIM de l'appareil Samsung Duos.

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

MODIFIER 2:

La méthode utilisée pour récupérer les données est pour Lenovo A319 et d'autres téléphones de ce fabricant (Crédit Maher Abuthraa ):

telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 0); 
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 1); 
Vaibhav Jani
la source
4
Cool! Cela a fonctionné pour moi avec "getDeviceId" sur Karbonn. Je rechercherai les méthodes Samsung et me mettra à jour ici lorsque je les aurai avec moi. Merci mec. Gloire.
Rajkiran
1
Oui. Même moi, j'ai fait ça. Trouvé que Samsung utilise en com.android.internal.telephony.RILConstants$SimCardIDinterne. J'ai même essayé de créer cette classe avec la même signature de méthodes et les mêmes noms de variables. Mais pas de chance. Essayera d'obtenir le code source et essaiera de vérifier. Merci.
Rajkiran
4
J'utilise telephonyInfo.imeiSIM1 = getDeviceIdBySlot (contexte, "getDeviceIdDs", 0); telephonyInfo.imeiSIM2 = getDeviceIdBySlot (contexte, "getDeviceIdDs", 1); Ça marche pour moi. J'ai réussi à obtenir deux numéros IMEI pour la carte SIM.
Seetha
1
Comment puis-je obtenir le numéro de téléphone de SIM2? J'obtiens le numéro SIM1 en utilisant la méthode telephony.getLine1Number (), dans la liste des méthodes, je ne trouve pas de méthode comme getLine2Number () ou getLine1Number (int)
DCoder
4
deviceId est IMEI pas IMSI, n'est-ce pas?
falko du
5

J'ai un appareil Samsung Duos avec Android 4.4.4 et la méthode suggérée par Seetha dans la réponse acceptée (c'est-à-dire appeler getDeviceIdDs) ne fonctionne pas pour moi, car la méthode n'existe pas. J'ai pu récupérer toutes les informations dont j'avais besoin en appelant la méthode "getDefault (int slotID)", comme indiqué ci-dessous:

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();
    }   
}

En outre, j'ai réécrit le code qui teste de manière itérative des méthodes pour récupérer ces informations afin qu'il utilise un tableau de noms de méthodes au lieu d'une séquence de try / catch. Par exemple, pour déterminer si nous avons deux cartes SIM actives, nous pourrions faire:

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;
}

De cette façon, si un nouveau nom de méthode est suggéré pour un périphérique, vous pouvez simplement l'ajouter au tableau et cela devrait fonctionner.

Eduardo Javier Huerta Yero
la source
4

J'ai trouvé plusieurs solutions natives en cherchant le moyen de vérifier l'opérateur réseau.

Pour l'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();
    } 
}

Dans AndroidManifest, ajoutez l'autorisation:

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

Pour obtenir un opérateur réseau, vous pouvez vérifier les codes mcc et mnc:

Pour l'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();
}

Pour API> = 23. Pour simplement vérifier si le téléphone est double / triple / plusieurs sim:

TelephonyManager manager = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
if (manager.getPhoneCount() == 2) {
    // Dual sim
}
oxy
la source
4

Je suis capable de lire les deux IMEI à partir du téléphone OnePlus 2

 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));
            }
Swapnil Godambe
la source
Bien que cela fonctionne sur One Plus. Mais demandez-vous de publier des réponses qui fonctionnent pour tous les téléphones et toutes les versions d'Android (probablement)
Rajkiran
1
Ceci est un SDK officiel. Devrait fonctionner pour tous les téléphones. Je l'ai testé sur OnePlus 2
Swapnil Godambe
Donc, la réponse acceptée de @Swapnil dit la même chose, n'est-ce pas?
Rajkiran
2

Je regardais les journaux d'appels et j'ai remarqué qu'en dehors des champs habituels dans le contenu de managedCursor, nous avons une colonne "simid" dans les téléphones Dual SIM (j'ai vérifié sur Xolo A500s Lite), afin de marquer chaque appel dans le journal des appels avec une carte SIM. Cette valeur est 1 ou 2, indiquant très probablement SIM1 / SIM2.

managedCursor = context.getContentResolver().query(contacts, null, null, null, null);
managedCursor.moveToNext();        
for(int i=0;i<managedCursor.getColumnCount();i++)
{//for dual sim phones
    if(managedCursor.getColumnName(i).toLowerCase().equals("simid"))
        indexSIMID=i;
}

Je n'ai pas trouvé cette colonne dans un seul téléphone SIM (j'ai vérifié sur Xperia L).

Donc, même si je ne pense pas que ce soit un moyen infaillible de vérifier la nature de la double SIM, je le publie ici car cela pourrait être utile à quelqu'un.

zafar142003
la source
Vous lisez un DB, lequel? Veuillez clarifier ce que vous faites ici. (Où est stockée la base de données «contacts»?
not2qubit
1

Conseils:

Vous pouvez essayer d'utiliser

ctx.getSystemService("phone_msim")

au lieu de

ctx.getSystemService(Context.TELEPHONY_SERVICE)

Si vous avez déjà essayé la réponse de Vaibhav et que vous échouez, voici telephony.getClass().getMethod()ce qui fonctionne pour mon mobile Qualcomm .

Bruce
la source
Tant que la réponse est complète, vous pouvez publier des liens vers des pages Web dans d'autres langues pour des informations supplémentaires. meta.stackoverflow.com/questions/271060/...
mach
C'était en fait un lien utile , inutile de le supprimer.
not2qubit
0

J'ai trouvé ces propriétés système sur Samsung S8

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

Aussi, selon la source: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/com/android/internal/telephony/TelephonyProperties.java

getprop persist.radio.multisim.configrenvoie " dsds" ou " dsda" sur multi sim.

J'ai testé cela sur Samsung S8 et cela fonctionne

kakopappa
la source
Ça ne fait rien. Android a déjà des API pour la double SIM. developer.android.com/about/versions/android-5.1.html#multisim Pour tout le reste, vous pouvez vous référer à la réponse ci-dessus de @vaibhav
Rajkiran
-1

Commonsware dit que ce n'est pas possible. Veuillez consulter ce qui suit:

La détection de la double SIM à l'aide du SDK Android n'est pas possible.

Voici un dialogue supplémentaire sur le sujet:

Le responsable de l'équipe de développement de Google dit que la détection de la double SIM à l'aide du SDK Android n'est pas possible.

gonzobrains
la source
3
Oui mec. Je le sais. Mais c'est pourquoi j'essaie de trouver une solution de contournement. Et il doit y en avoir. Essayez l'application USSDDualWidget sur Play Store. Il peut en fait basculer entre les deux cartes SIM. J'ai même essayé de faire de l'ingénierie inverse du code, mais pas de chance.
Rajkiran
Cela fonctionne-t-il sur tous les appareils ou simplement sur un sous-ensemble limité qui expose une sorte d'interface propriétaire?
gonzobrains
2
Pourquoi cette réponse a-t-elle été rejetée? C'est la bonne réponse. ^
N Sharma
24
Manytimes commonsware a déclaré que ce n'était pas possible, ce qui a été rendu possible par d'autres développeurs. Donc, ce n'est pas comme ça que dit commonsware est toujours juste :-)
Lalit Poptani
1
Vous avez peut-être raison, mais je pense qu'il est une ressource assez crédible pour tout ce qui concerne Android. En ce qui concerne ce problème particulier, bien sûr, j'ai fait la même chose et utilisé la réflexion pour obtenir des données dual sim, mais c'était pour mon appareil particulier. À ce jour, je ne crois toujours pas qu'il existe un moyen générique de procéder. Notez également que j'ai également cité un développeur Google et pas seulement Commonsware.
gonzobrains