Android: controlla se il telefono è dual SIM


113

Dopo molte ricerche sui forum, ora so che non c'è modo di trovare il numero di serie IMSI o SIM per entrambe le schede SIM in un telefono dual SIM (tranne che per contattare il produttore). Ora la mia domanda modificata è: possiamo rilevare che il telefono ha due SIM? Credo che possa essere rilevato con una certa intelligenza. Alcuni modi in cui riesco a pensare sono:

  1. Comporre un codice USSD e rintracciare i log per il numero IMEI (l'ho provato con * 139 # in India. Ha funzionato.) Questo mi darà il numero IMEI per la SIM da cui ho composto il codice USSD. (Si presume che il telefono segua le linee guida di Android e abbia due numeri IMEI.)

  2. Memorizzazione del numero di serie della SIM e / o dell'IMSI per la SIM. E dopo il rilevamento di qualsiasi altro numero IMSI / seriale anche se il telefono non è stato riavviato (cioè la SIM è stata cambiata) tracciando alcuni log o gestendo alcuni eventi di trasmissione.

  3. Componendo * 06 # vedrai entrambi i numeri IMEI. In qualche modo, prendi quei due numeri. (Qualcosa come l'acquisizione dello schermo e l'analisi delle immagini per il testo.)

Se qualcuno riesce a pensare ad altri modi, è il benvenuto. Apprezzerei davvero qualsiasi tipo di aiuto in merito. Inoltre, se qualcuno ha informazioni sulle API dei produttori o sui collegamenti per contattarlo, condividile con le persone della comunità.


Ciao Rajkiran, finalmente ho trovato la soluzione che funziona bene per me. Spero che sia utile per tutti coloro che desiderano gestire Duel SIM nelle applicazioni mobili. L'API dell'handle della SIM duello non è documentata. Per favore controlla la mia risposta che funziona bene per me. stackoverflow.com/questions/17618651/...
Jebasuthan

1
Grazie .. ma la tua risposta non risponde alla mia domanda. Voglio tutti i dettagli sulla seconda SIM e IMEI. La risposta di @Pied Piper mi aiuta a ottenere tutto.
Rajkiran

La risposta di @Rajkiran Pied Piper ti ha davvero aiutato? Ho controllato il suo codice in m samsung galaxy y duos ma non funziona Mi hai aiutato a trovare i numeri IMEI del telefono dual sim?
Nitish Patel

@ nitishpatel: Sì, sicuramente ha aiutato. Purtroppo non ho Y Duos da controllare. Ma credo che Samsung utilizzi un meccanismo diverso per la gestione della doppia SIM su Android dalla versione 4.0 in poi. La risposta di Pied Pipers aiuta nei dispositivi 4.0 in poi. Per il resto, dovrai scavare un po 'di più usando la riflessione.
Rajkiran

Ciao, trovo una soluzione ... controlla il codice stackoverflow.com/a/32304799/3131373 È testato su vari telefoni
user3131373

Risposte:


184

Aggiornamento 23 marzo '15:

L'API ufficiale per più SIM è ora disponibile da Android 5.1 in poi

Altra opzione possibile:

Puoi utilizzare la riflessione Java per ottenere entrambi i numeri IMEI.

Utilizzando questi numeri IMEI puoi verificare se il telefono è una DUAL SIM o meno.

Prova la seguente attività:

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

Ed ecco 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);
        }
    }
}

Modificare :

Ottenere l'accesso a metodi come "getDeviceIdGemini" per i dettagli di altri slot SIM prevede che il metodo esista.

Se il nome di quel metodo non corrisponde a quello fornito dal produttore del dispositivo, allora non funzionerà. Devi trovare il nome del metodo corrispondente per quei dispositivi.

La ricerca di nomi di metodi per altri produttori può essere eseguita utilizzando la riflessione Java come segue:

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

MODIFICARE :

Come ha sottolineato Seetha nel suo commento:

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

Funziona per lei. È riuscita a ottenere due numeri IMEI per entrambe le SIM nel dispositivo Samsung Duos.

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

MODIFICA 2:

Il metodo utilizzato per il recupero dei dati è per Lenovo A319 e altri telefoni di tale produttore (Credit Maher Abuthraa ):

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

4
Freddo! Questo ha funzionato per me con "getDeviceId" su Karbonn. Cercherò metodi Samsung e aggiornerò qui quando lo avrò con me. Grazie uomo. Complimenti.
Rajkiran

1
Sì. Anche io l'ho fatto. Trovato che Samsung utilizza com.android.internal.telephony.RILConstants$SimCardIDinternamente. Ho anche provato a creare quella classe con la stessa firma di metodi e gli stessi nomi di variabili. Ma senza fortuna. Proverà a ottenere il codice sorgente e proverà a controllare. Grazie.
Rajkiran

4
Uso telephonyInfo.imeiSIM1 = getDeviceIdBySlot (context, "getDeviceIdDs", 0); telephonyInfo.imeiSIM2 = getDeviceIdBySlot (context, "getDeviceIdDs", 1); Sta funzionando per me. Sono riuscito a ottenere due numeri IMEI per entrambe le SIM.
Seetha

1
Come posso ottenere il numero di telefono della SIM2? Sto ottenendo il numero SIM1 utilizzando il metodo telephony.getLine1Number (), nell'elenco dei metodi non riesco a trovare metodi come getLine2Number () o getLine1Number (int)
DCoder

4
deviceId è IMEI non IMSI, non è vero?
falko

5

Ho un dispositivo Samsung Duos con Android 4.4.4 e il metodo suggerito da Seetha nella risposta accettata (cioè chiamata getDeviceIdDs) non funziona per me, in quanto il metodo non esiste. Sono stato in grado di recuperare tutte le informazioni di cui avevo bisogno chiamando il metodo "getDefault (int slotID)", come mostrato di seguito:

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

Inoltre, ho riscritto il codice che verifica iterativamente i metodi per recuperare queste informazioni in modo che utilizzi un array di nomi di metodo invece di una sequenza di try / catch. Ad esempio, per determinare se abbiamo due SIM attive potremmo fare:

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

In questo modo, se viene suggerito un nuovo nome di metodo per qualche dispositivo, puoi semplicemente aggiungerlo all'array e dovrebbe funzionare.


4

Ci sono diverse soluzioni native che ho trovato durante la ricerca del modo per controllare l'operatore di rete.

Per 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 aggiungi autorizzazione:

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

Per ottenere l'operatore di rete puoi controllare i codici mcc e mnc:

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

Per API> = 23. Per controllare solo se il telefono è doppia / tripla / molte sim:

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

4

Sono in grado di leggere entrambi gli IMEI dal telefono 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));
            }

Bene che funzioni su One Plus. Ma ti
chiedo

1
Questo è un SDK ufficiale. Dovrebbe funzionare per tutti i telefoni. L'ho provato su OnePlus 2
Swapnil Godambe

Quindi la risposta accettata da @Swapnil dice la stessa cosa, giusto?
Rajkiran

2

Stavo dando un'occhiata ai registri delle chiamate e ho notato che a parte i soliti campi nei contenuti di managedCursor, abbiamo una colonna "simid" nei telefoni Dual SIM (ho controllato su Xolo A500s Lite), in modo da taggare ogni chiamata nel registro delle chiamate con una SIM. Questo valore è 1 o 2, molto probabilmente denota 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;
}

Non ho trovato questa colonna in un singolo telefono SIM (ho controllato su Xperia L).

Quindi, anche se non penso che questo sia un modo infallibile per verificare la natura della doppia SIM, lo sto pubblicando qui perché potrebbe essere utile a qualcuno.


Stai leggendo un DB, quale? Per favore, chiarisci cosa stai facendo qui. (Dove è memorizzato il db "contatti"?
not2qubit

1

Suggerimenti:

Puoi provare a usare

ctx.getSystemService("phone_msim")

invece di

ctx.getSystemService(Context.TELEPHONY_SERVICE)

Se hai già provato la risposta di Vaibhav e telephony.getClass().getMethod()non riesce, sopra è ciò che funziona per il mio cellulare Qualcomm .


Finché la risposta è completa, è possibile pubblicare collegamenti a pagine Web in altre lingue per informazioni supplementari. meta.stackoverflow.com/questions/271060/…
mach

Quello era effettivamente un collegamento utile , non c'era bisogno di rimuoverlo.
not2qubit

0

Ho trovato queste proprietà di sistema su Samsung S8

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

Inoltre, secondo la fonte: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/com/android/internal/telephony/TelephonyProperties.java

getprop persist.radio.multisim.configrestituisce " dsds" o " dsda" su multi sim.

L'ho testato su Samsung S8 e funziona


Non importa. Android ha già le API per la doppia SIM ora. developer.android.com/about/versions/android-5.1.html#multisim Per tutto il resto, puoi fare riferimento alla risposta sopra di @vaibhav
Rajkiran

-1

Commonsware dice che questo non è possibile. Si prega di vedere quanto segue:

Non è possibile rilevare la doppia SIM utilizzando Android SDK.

Ecco un ulteriore dialogo sull'argomento:

Il ragazzo del team di sviluppo di Google dice che non è possibile rilevare la doppia SIM utilizzando Android SDK.


3
Sì amico. Lo so. Ma è per questo che sto cercando di trovare una soluzione alternativa. E ce ne devono essere alcuni. Prova l'app USSDDualWidget dal Play Store. Può effettivamente passare tra le due SIM. Ho anche provato a decodificare il codice, ma senza fortuna.
Rajkiran

Funziona su tutti i dispositivi o solo su un sottoinsieme limitato che espone una sorta di interfaccia proprietaria?
gonzobrains

2
Perché questa risposta è stata sottovalutata? Questa è la risposta corretta. ^
N Sharma,

24
Molte volte commonsware ha detto che non è possibile, cosa che è stata resa possibile da altri sviluppatori. Quindi, non è così quello che dice il commonsware è sempre giusto :-)
Lalit Poptani

1
Potresti avere ragione, ma penso che sia una risorsa abbastanza credibile per tutto ciò che riguarda Android. Per quanto riguarda questo particolare problema, certo, ho fatto la stessa cosa e ho usato la riflessione per ottenere dati dual sim, ma era per il mio particolare dispositivo. Ad oggi, non credo ancora che ci sia un modo generico per farlo. Notare anche che ho citato anche uno sviluppatore Google e non solo Commonsware.
gonzobrains
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.