Android: compruebe si el teléfono tiene SIM dual

Después de una gran cantidad de investigaciones en los foros, ahora sé que no hay forma de encontrar el número de serie de IMSI o SIM para ambas tarjetas SIM en un teléfono dual SIM (excepto para contactar al fabricante). Ahora mi pregunta es: ¿podemos detectar que el teléfono tiene dos SIM? Creo que se puede detectar con algo de inteligencia. Pocas maneras en que puedo pensar son:

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

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

  3. Al marcar * 06 #, podrá ver los dos números IMEI. De alguna manera, consigue esos dos números. (Algo así como captura de pantalla y análisis de imágenes para texto).

Si alguien puede pensar de otras maneras, son bienvenidos. Realmente agradecería cualquier tipo de ayuda con respecto a esto. Además, si alguien tiene información sobre API de fabricantes o enlaces para contactarlos, por favor, compártala con las personas de la comunidad.

Actualización 23 de marzo de 2015:

La SIM múltiple oficial ya está disponible desde Android 5.1 en adelante

Otra posible opción:

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

Usando estos números IMEI puede verificar si el teléfono es una SIM DUAL o no.

Intenta seguir la 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 aquí está 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 el detalle de otro slot SIM tiene predicción de que ese método existe.

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

Encontrar nombres de métodos para otros fabricantes se puede hacer utilizando 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 Seetha señaló en su comentario:

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

Está funcionando para ella. Logró obtener dos números de IMEI para la tarjeta SIM en el dispositivo Samsung Duos.

Agregar

EDICION 2:

El método utilizado para recuperar datos es para Lenovo A319 y otros teléfonos de esa fabricación (Credit Maher Abuthraa ):

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

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 funciona para mí, ya que el método no existe. Pude recuperar toda la información que necesitaba llamando al método “getDefault (int slotIDID)”, 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 de forma iterativa los métodos para recuperar esta información, de modo que utiliza 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 forma, si se sugiere un nuevo nombre de método para algún dispositivo, simplemente puede agregarlo a la matriz y debería funcionar.

Hay varias soluciones nativas que he encontrado mientras buscaba la manera 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 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, agrega permiso:

   

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 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 comprobar si el teléfono es dual / triple / muchos sim:

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

Puedo leer los IMEI desde el 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)); } 

Estaba echando un vistazo a los registros de llamadas y me di cuenta de que, aparte de los campos habituales en los contenidos de managedCursor, tenemos una columna “simid” en teléfonos Dual SIM (comprobé en Xolo A500s Lite), para etiquetar cada llamada en el registro de llamadas con una SIM. Este valor es 1 o 2, lo más probable es que denota SIM1 / SIM2.

 managedCursor = context.getContentResolver().query(contacts, null, null, null, null); managedCursor.moveToNext(); for(int i=0;i 

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

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

Consejos:

Puedes intentar usar

ctx.getSystemService("phone_msim")

en lugar de

ctx.getSystemService(Context.TELEPHONY_SERVICE)

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

Commonsware dice que esto no es posible. Por favor mira 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 con Android SDK.

He encontrado 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.config devuelve ” dsds ” o ” dsda ” en multi sim.

He probado esto en Samsung S8 y funciona