Android: compruebe si el teléfono tiene doble SIM

113

Después de mucha investigación en foros, ahora sé que no hay forma de encontrar el número de serie IMSI o SIM para ambas tarjetas SIM en un teléfono con doble SIM (excepto para contactar al fabricante). Ahora mi pregunta modificada es, ¿podemos detectar que el teléfono tiene dos SIM? Creo que se puede detectar con cierta inteligencia. Algunas formas en las que puedo pensar son:

  1. Marcar un código USSD y rastrear los registros del número IMEI (probé esto con * 139 # en India. Funcionó). Esto me dará el número IMEI para la SIM desde la cual marqué el código USSD. (Se presume que el teléfono sigue las pautas de Android y tiene dos números IMEI).

  2. Almacenamiento del número de serie de la SIM y / o IMSI para la SIM. Y después de la detección de cualquier otro IMSI / número de serie, incluso si el teléfono no se reinició (es decir, se cambió la SIM) rastreando algunos registros o mediante el manejo de eventos de transmisión.

  3. Si marca * 06 # podrá ver ambos números IMEI. De alguna manera, obtén esos dos números. (Algo como captura de pantalla y análisis de imágenes para texto).

Si alguien puede pensar en otras formas, será bienvenido. Realmente agradecería cualquier tipo de ayuda con respecto a esto. Además, si alguien tiene información sobre las API de algún fabricante o enlaces para comunicarse con ellos, compártala con la gente de la comunidad.

Rajkiran
fuente
Hola Rajkiran, Finalmente obtuve la solución, funciona bien para mí. Espero que sea útil para todos los que quieran manejar Duel SIM en aplicaciones móviles. La API de control de Duel SIM no está documentada. Por favor, compruebe mi respuesta, funciona bien para mí. stackoverflow.com/questions/17618651/…
Jebasuthan
1
Gracias .. pero tu respuesta no responde a mi pregunta. Quiero todos los detalles sobre la segunda SIM e IMEI. La respuesta de @Pied Piper me ayuda a conseguir todo.
Rajkiran
¿La respuesta de @Rajkiran Pied Piper realmente te ayudó? He comprobado su código en m samsung galaxy y duos pero no funciona. ¿Me ayudaste a encontrar los números IMEI del teléfono dual sim?
Nitish Patel
@nitishpatel: Sí, definitivamente ayudó. Desafortunadamente, no tengo Y Duos para verificar. Pero creo que Samsung usa un mecanismo diferente para el manejo de SIM dual en la versión 4.0 de Android en adelante. La respuesta de Pied Pipers ayuda en dispositivos 4.0 en adelante. Por lo demás, necesitarás profundizar un poco más usando la reflexión.
Rajkiran
Hola, encuentro una solución ... por favor verifique el código stackoverflow.com/a/32304799/3131373 Se prueba en varios teléfonos
user3131373

Respuestas:

184

Actualización 23 de marzo de 2015:

La API oficial de múltiples SIM ya está disponible desde Android 5.1 en adelante

Otra posible opción:

Puede utilizar la reflexión de Java para obtener ambos números IMEI.

Con estos números IMEI puede comprobar si el teléfono es DUAL SIM o no.

Prueba la siguiente actividad:

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

Y aqui esta 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);
        }
    }
}

Editar:

Obtener acceso a métodos como "getDeviceIdGemini" para obtener detalles de otras ranuras SIM permite predecir que el método existe.

Si el nombre de ese método no coincide con uno proporcionado por el fabricante del dispositivo, no funcionará. Debe encontrar el nombre del método correspondiente para esos dispositivos.

La búsqueda de nombres de métodos para otros fabricantes se puede realizar mediante la reflexión de Java de la siguiente manera:

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

EDITAR:

Como señaló Seetha en su comentario:

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

Está funcionando para ella. Tuvo éxito al obtener dos números IMEI tanto para la SIM en el dispositivo Samsung Duos.

Añadir <uses-permission android:name="android.permission.READ_PHONE_STATE" />

EDITAR 2:

El método utilizado para recuperar datos es para Lenovo A319 y otros teléfonos de ese fabricante (Credit Maher Abuthraa ):

telephonyInfo.imeiSIM1 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 0); 
telephonyInfo.imeiSIM2 = getDeviceIdBySlot(context, "getSimSerialNumberGemini", 1); 
Vaibhav Jani
fuente
4
¡Frio! Eso funcionó para mí con "getDeviceId" en Karbonn. Buscaré métodos de Samsung y los actualizaré aquí cuando lo tenga conmigo. Gracias hombre. Prestigio.
Rajkiran
1
Si. Incluso yo hice eso. Descubrí que Samsung usa com.android.internal.telephony.RILConstants$SimCardIDinternamente. Incluso intenté crear esa clase con la misma firma de métodos y los mismos nombres de variables. Pero no hubo suerte. Intentará obtener el código fuente e intentará comprobarlo. Gracias.
Rajkiran
4
Yo uso telephonyInfo.imeiSIM1 = getDeviceIdBySlot (context, "getDeviceIdDs", 0); telephonyInfo.imeiSIM2 = getDeviceIdBySlot (context, "getDeviceIdDs", 1); Me está funcionando. Tuve éxito al obtener dos números IMEI para ambos SIM.
Seetha
1
¿Cómo puedo obtener el número de teléfono de SIM2? Obtengo el número SIM1 usando el método telephony.getLine1Number (), en la lista de métodos no puedo encontrar métodos como getLine2Number () o getLine1Number (int)
DCoder
4
deviceId es IMEI, no IMSI, ¿no?
falko
5

Tengo un dispositivo Samsung Duos con Android 4.4.4 y el método sugerido por Seetha en la respuesta aceptada (es decir, llamar a getDeviceIdDs) no me funciona, ya que el método no existe. Pude recuperar toda la información que necesitaba llamando al método "getDefault (int slotID)", como se muestra a continuación:

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

Además, reescribí el código que prueba iterativamente los métodos para recuperar esta información de modo que use una matriz de nombres de métodos en lugar de una secuencia de try / catch. Por ejemplo, para determinar si tenemos dos SIM activas podríamos hacer:

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 esta manera, si se sugiere un nuevo nombre de método para algún dispositivo, simplemente puede agregarlo a la matriz y debería funcionar.

Eduardo Javier Huerta Yero
fuente
4

Hay varias soluciones nativas que encontré mientras buscaba la forma de verificar el operador de red.

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

En AndroidManifest, agregue permiso:

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

Para obtener un operador de red, puede verificar los códigos mcc y mnc:

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

Para API> = 23. Para verificar si el teléfono es dual / triple / many sim:

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

Puedo leer ambos IMEI del teléfono 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
fuente
Es bueno que funcione en One Plus. Pero solicite que publique respuestas que funcionan para todos los teléfonos y todas las versiones de Android (probablemente)
Rajkiran
1
Este es un SDK oficial. Debería funcionar para todos los teléfonos. Lo probé en OnePlus 2
Swapnil Godambe
Entonces, la respuesta aceptada de @Swapnil dice lo mismo, ¿verdad?
Rajkiran
2

Estaba mirando los registros de llamadas y noté que además de los campos habituales en el contenido de managedCursor, tenemos una columna "simid" en los teléfonos Dual SIM (verifiqué en Xolo A500s Lite), para etiquetar cada llamada en el registro de llamadas con una SIM. Este valor es 1 o 2, probablemente 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;
}

No encontré esta columna en un solo teléfono SIM (verifiqué en Xperia L).

Entonces, aunque no creo que esta sea una forma infalible de verificar la naturaleza de la SIM dual, la estoy publicando aquí porque podría ser útil para alguien.

zafar142003
fuente
Estás leyendo un DB, ¿cuál? Por favor, aclare lo que está haciendo aquí. (¿Dónde se almacena la base de datos de "contactos"?
not2qubit
1

Consejos:

Puedes intentar usar

ctx.getSystemService("phone_msim")

en vez de

ctx.getSystemService(Context.TELEPHONY_SERVICE)

Si ya probó la respuesta de Vaibhav y telephony.getClass().getMethod()falla, lo anterior es lo que funciona para mi móvil Qualcomm .

Bruce
fuente
Siempre que la respuesta esté completa , puede publicar enlaces a páginas web en otros idiomas para obtener información adicional. meta.stackoverflow.com/questions/271060/…
Mach
Ese fue en realidad un enlace útil , no es necesario eliminarlo.
not2qubit
0

Encontré estas propiedades del sistema en Samsung S8

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

Además, según la fuente: https://android.googlesource.com/platform/frameworks/base/+/master/telephony/java/com/android/internal/telephony/TelephonyProperties.java

getprop persist.radio.multisim.configdevuelve " dsds" o " dsda" en multi SIM.

He probado esto en Samsung S8 y funciona

kakopappa
fuente
No importa. Android ya tiene API para SIM dual ahora. developer.android.com/about/versions/android-5.1.html#multisim Para todo lo demás, puede consultar la respuesta anterior de @vaibhav
Rajkiran
-1

Commonsware dice que esto no es posible. Consulte lo siguiente:

No es posible detectar Dual SIM con Android SDK.

Aquí hay más diálogo sobre el tema:

El chico del equipo de desarrollo de Google dice que no es posible detectar Dual SIM usando Android SDK.

Gonzocerebros
fuente
3
Si hombre. Yo sé eso. Pero es por eso que estoy tratando de encontrar una solución. Y tiene que haber algunos. Pruebe la aplicación USSDDualWidget de Play Store. De hecho, puede cambiar entre las dos SIM. Incluso traté de aplicar ingeniería inversa al código, pero no tuve suerte.
Rajkiran
¿Funciona en todos los dispositivos o solo en un subconjunto limitado que expone algún tipo de interfaz propietaria?
gonzobrains
2
¿Por qué esta respuesta votó negativamente? Esta es la respuesta correcta. ^
N Sharma
24
Muchas veces el software común ha dicho que no es posible, lo que ha sido posible gracias a otros desarrolladores. Entonces, no es así lo que el software común dice que siempre es correcto :-)
Lalit Poptani
1
Puede que tengas razón, pero creo que es un recurso bastante creíble para todo lo relacionado con Android. En cuanto a este problema en particular, claro, hice lo mismo y usé la reflexión para obtener datos de doble simulación, pero fue para mi dispositivo en particular. Hasta el día de hoy, todavía no creo que haya una forma genérica de hacer esto. También observe que cité a un desarrollador de Google y no solo a Commonsware.
Gonzobrains