¿Cómo enviar un SMS usando SMSmanager en Dual SIM móvil?

Estoy usando el encargado de SMS para enviar SMS.For solo SIM sus trabajos perfectamente para enviar el SMS.but en SIM dual el SMS no enviará. ¿Es posible enviar el SMS de SIM dual, si es posible medios cómo puedo seleccionar el qué SIM Para enviar SMS.Can cualquiera sabe me ayudan a resolver este problema.

Código de trabajo SIM único

SmsManager smsManager = SmsManager.getDefault(); smsManager.sendTextMessage(ph_number, null, body, null,null); 

Utilizo esta manera de manejar qué sim usar para enviar SMS incluso mensaje largo. Su funcionamiento en mi teléfono dual del sim Lenovo A319 (4.4.3), ninguna necesidad de la raíz. Su construido sobre la reflexión.

 import android.app.PendingIntent; import android.content.Context; import android.os.Build; import android.os.IBinder; import android.util.Log; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.List; /** * Created by Apipas on 6/4/15. */ public class SimUtil { public static boolean sendSMS(Context ctx, int simID, String toNum, String centerNum, String smsText, PendingIntent sentIntent, PendingIntent deliveryIntent) { String name; try { if (simID == 0) { name = "isms"; // for model : "Philips T939" name = "isms0" } else if (simID == 1) { name = "isms2"; } else { throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values"); } Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class); method.setAccessible(true); Object param = method.invoke(null, name); method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", IBinder.class); method.setAccessible(true); Object stubObj = method.invoke(null, param); if (Build.VERSION.SDK_INT < 18) { method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, PendingIntent.class, PendingIntent.class); method.invoke(stubObj, toNum, centerNum, smsText, sentIntent, deliveryIntent); } else { method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, String.class, PendingIntent.class, PendingIntent.class); method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsText, sentIntent, deliveryIntent); } return true; } catch (ClassNotFoundException e) { Log.e("apipas", "ClassNotFoundException:" + e.getMessage()); } catch (NoSuchMethodException e) { Log.e("apipas", "NoSuchMethodException:" + e.getMessage()); } catch (InvocationTargetException e) { Log.e("apipas", "InvocationTargetException:" + e.getMessage()); } catch (IllegalAccessException e) { Log.e("apipas", "IllegalAccessException:" + e.getMessage()); } catch (Exception e) { Log.e("apipas", "Exception:" + e.getMessage()); } return false; } public static boolean sendMultipartTextSMS(Context ctx, int simID, String toNum, String centerNum, ArrayList<String> smsTextlist, ArrayList<PendingIntent> sentIntentList, ArrayList<PendingIntent> deliveryIntentList) { String name; try { if (simID == 0) { name = "isms"; // for model : "Philips T939" name = "isms0" } else if (simID == 1) { name = "isms2"; } else { throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values"); } Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", String.class); method.setAccessible(true); Object param = method.invoke(null, name); method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", IBinder.class); method.setAccessible(true); Object stubObj = method.invoke(null, param); if (Build.VERSION.SDK_INT < 18) { method = stubObj.getClass().getMethod("sendMultipartText", String.class, String.class, List.class, List.class, List.class); method.invoke(stubObj, toNum, centerNum, smsTextlist, sentIntentList, deliveryIntentList); } else { method = stubObj.getClass().getMethod("sendMultipartText", String.class, String.class, String.class, List.class, List.class, List.class); method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsTextlist, sentIntentList, deliveryIntentList); } return true; } catch (ClassNotFoundException e) { Log.e("apipas", "ClassNotFoundException:" + e.getMessage()); } catch (NoSuchMethodException e) { Log.e("apipas", "NoSuchMethodException:" + e.getMessage()); } catch (InvocationTargetException e) { Log.e("apipas", "InvocationTargetException:" + e.getMessage()); } catch (IllegalAccessException e) { Log.e("apipas", "IllegalAccessException:" + e.getMessage()); } catch (Exception e) { Log.e("apipas", "Exception:" + e.getMessage()); } return false; } } 

Añadir permiso:

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

Entonces simplemente llame a eso (sangrienta) método estático como este 🙂

Para utilizar SIM1:

 SimUtil.sendSMS(this,0,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim1",null,null); 

Para utilizar SIM2:

 SimUtil.sendSMS(this,1,"00970XXXXXXXXX",null,"Hi Stackoverflow! its me Maher. Sent by sim2",null,null); 

Pero espera … que no funcionará si el mensaje es más de 160 caracteres .. así que mejor manera:

 String textSMS; //short <160 // textSMS = "Hi Stackoverflow! its me Maher."; //long >160 textSMS = "Hi Jerusalem, hi Cairo, Hi Prague, hi Baghdad, hi Riyadh, hi Jeddah, hi Dammam, hi Aleppo, hi Casablanca, hi Damascus, hi Alexandria, hi Algiers, hi Mosul, hi Basra, hi Arabia, hi Tripoli, hi Amman, hi Kuwait, hi Beirut, hi Abu Dhabi"; int simID = 0;//0:sim_1, 1:sim_2 ArrayList<String> messageList = SmsManager.getDefault().divideMessage(textSMS); if (messageList.size() > 1) { SimUtil.sendMultipartTextSMS(this, simID, "00972XXXXXXXXX", null, messageList, null, null); } else { SimUtil.sendSMS(this, simID, "00972XXXXXXXXX", null, textSMS, null, null); } 

Así que usted puede pasar seguro el cuerpo del mensaje sin la preocupación sobre longitud.

———— ACTUALIZACIÓN 09.10.2016 ———-

Para utilizar PendingIntent / DeliveryIntent en MultipartMessage .. sólo cree ArrayList con el mismo contenido y pasarlo. Esta es una implementación de la creación de Lista de PendingIntent:

 final static String sSMSManagerIntentSENT = "package.DeliveryReport.SMS_SENT"; int numParts = parts.size(); ArrayList<PendingIntent> pendingIntents = new ArrayList<PendingIntent>(); for (int i = 0; i < numParts; i++) { Intent pendingIntent = new Intent(sSMSManagerIntentSENT); //optional if you want to keep info about what action has been done for feedback or analysis later when message is sent pendingIntent.putExtra("package.DeliveryReport.phoneNumber", phoneNo); // receiver phoneNo pendingIntent.putExtra("package.DeliveryReport.textSMS", msg);// msg body pendingIntent.putExtra("SIM", simID); // which sim is sending this message pendingIntents.add(PendingIntent.getBroadcast(getActivity(), 0, pendingIntent,PendingIntent.FLAG_ONE_SHOT)); } 

Para entregar, sólo use el mismo enfoque.

—————— Extra ——————

He visto que el androide 22 apoya tarjetas multi del sim de Android 5.1 y aquí es cómo utilizarlo. Desafortunadamente no tengo dispositivo con esa versión para probar, satisface tan para la regeneración:

 SmsManager.getSmsManagerForSubscriptionId(int subscriptionId).sendTextMessage(String destinationAddress, String scAddress, String text,PendingIntent sentIntent, PendingIntent deliveryIntent); 

¿Cómo obtener subscriptionId? Para revisar todos los subscriptionID disponibles que pertenecen a la tarjeta SIM:

 SubscriptionManager subscriptionManager = SubscriptionManager.from(getApplicationContext()); List<SubscriptionInfo> subscriptionInfoList = subscriptionManager.getActiveSubscriptionInfoList(); for (SubscriptionInfo subscriptionInfo : subscriptionInfoList) { int subscriptionId = subscriptionInfo.getSubscriptionId(); Log.d("apipas","subscriptionId:"+subscriptionId); } 

** Tenga en cuenta que este código funciona en 5.1. Si intenta ejecutarlo en una versión anterior obtendría una excepción de que ese método no existe.

———— UPDATE 19.8.2015 ———-

Información sobre SIMs, se encuentran en DB: telephony.db (por defecto: /data/data/com.android.providers.telephony/databases/telephony.db) en la tabla siminfo. Ver captura de pantalla en la tabla siminfo en DB en dispositivo real.

Introduzca aquí la descripción de la imagen

Afortunadamente hay un proveedor de contenido para eso:

 "content://telephony/siminfo/" 

Por lo tanto, básicamente sólo los datos de consulta de esa tabla. Es importante mencionar que la ranura 0 representa SIM1, y 1 representa SIM2, y la ranura -1 de SIMs antiguo / eliminado / reemplazado.

Esto se aplica a Lenovo A319. Supongo que puede funcionar en otros dispositivos. Aquí está el método util que utilizo:

 public static List<SimInfo> getSIMInfo(Context context) { List<SimInfo> simInfoList = new ArrayList<>(); Uri URI_TELEPHONY = Uri.parse("content://telephony/siminfo/"); Cursor c = context.getContentResolver().query(URI_TELEPHONY, null, null, null, null); if (c.moveToFirst()) { do { int id = c.getInt(c.getColumnIndex("_id")); int slot = c.getInt(c.getColumnIndex("slot")); String display_name = c.getString(c.getColumnIndex("display_name")); String icc_id = c.getString(c.getColumnIndex("icc_id")); SimInfo simInfo = new SimInfo(id, display_name, icc_id, slot); Log.d("apipas_sim_info", simInfo.toString()); simInfoList.add(simInfo); } while (c.moveToNext()); } c.close(); return simInfoList; } 

Y aquí está la clase de entidad SimInfo:

 public class SimInfo { private int id_; private String display_name; private String icc_id; private int slot; public SimInfo(int id_, String display_name, String icc_id, int slot) { this.id_ = id_; this.display_name = display_name; this.icc_id = icc_id; this.slot = slot; } public int getId_() { return id_; } public String getDisplay_name() { return display_name; } public String getIcc_id() { return icc_id; } public int getSlot() { return slot; } @Override public String toString() { return "SimInfo{" + "id_=" + id_ + ", display_name='" + display_name + '\'' + ", icc_id='" + icc_id + '\'' + ", slot=" + slot + '}'; } } 

Buena suerte,'.

La solución basada en la reflexión de Maher funciona para el emulador Android SDK 10, 17, 18, 19,20,21 y como se mencionó la solución basada en SubscriptionId funciona para SDK 22 que realmente funciona para Micromax Canvas 4 (Android 4.2) también.

Pero para algunas marcas de teléfonos como Lenevo, las marcas de Asus con Android 5.0 errores con

Java.lang.NullPointerException: Intenta invocar Virtual Method 'Java.lang.Class Java.Lang.Object.GetClass () ' en una referencia a objetos nulos "en el código

" Método = stubObj.getClass (). GetMethod (" sendText ", String.class, String.class, String.class, String.class, PendingIntent.class, PendingIntent.class);

Lo que significa que no es capaz de obtener el stubObj adecuado.

He intentado Mahers Refletion método para enviar sms en el teléfono dual sim android (API 19 y siguientes). El chipset en el teléfono inteligente era de Spreadtrum . Encontré excepciones con el código de Maher, primero fue la excepción Null Pointer, en el nombre = isms2. Para mí, sim1 era isms0 y sim2 era isms1, recuperé esta información en los dumpsys. Con mucha depuración y un poco más de búsqueda siguiente código funcionó para mí:

 public class SimUtil { public static boolean sendSMS(Context ctx, int simID, String toNum, String centerNum, String smsText, PendingIntent sentIntent, PendingIntent deliveryIntent) { String name; try { if (simID == 0) { name = "isms0"; } else if (simID == 1) { name = "isms1"; } else { throw new Exception("can not get service which for sim '" + simID + "', only 0,1 accepted as values"); } try { Method method = Class.forName("android.os.ServiceManager").getDeclaredMethod("getService", new Class[]{String.class}); method.setAccessible(true); Object param = method.invoke(null, new Object[]{name}); if (param == null) { throw new RuntimeException("can not get service which is named '" + name + "'"); } method = Class.forName("com.android.internal.telephony.ISms$Stub").getDeclaredMethod("asInterface", new Class[]{IBinder.class}); method.setAccessible(true); Object stubObj = method.invoke(null, new Object[]{param}); method = stubObj.getClass().getMethod("sendText", String.class, String.class, String.class, String.class, PendingIntent.class, PendingIntent.class); method.invoke(stubObj, ctx.getPackageName(), toNum, centerNum, smsText, sentIntent, deliveryIntent); } catch (ClassNotFoundException e) { throw new RuntimeException(e); } catch (NoSuchMethodException e) { throw new RuntimeException(e); } catch (InvocationTargetException e) { throw new RuntimeException(e); } catch (IllegalAccessException e) { throw new RuntimeException(e); } return true; } catch (ClassNotFoundException e) { Log.e("Exception", "ClassNotFoundException:" + e.getMessage()); } catch (NoSuchMethodException e) { Log.e("Exception", "NoSuchMethodException:" + e.getMessage()); } catch (InvocationTargetException e) { Log.e("Exception", "InvocationTargetException:" + e.getMessage()); } catch (IllegalAccessException e) { Log.e("Exception", "IllegalAccessException:" + e.getMessage()); } catch (Exception e) { Log.e("Exception", "Exception:" + e); } return false; } 

}

Los siguientes enlaces pueden ser útiles:

La solución de Maher es casi correcta.

Lo probé en Motorola motog 5.1 android (single sim), pero su solución con el content://telephony/siminfo tabla de lectura content://telephony/siminfo tenía un pequeño error:

En mi motorola no había slot campo sino sim_id

Resto de esto estaba bien e idéntico.

  • Android: SMSManager - Intento de obtener longitud de matriz nula
  • SMS no recibidos ... sólo en ciertos casos ... Carrier / Country?
  • Enviar SMS hasta que tenga éxito
  • SMSManager no funciona en Samsung Galaxy S3 LTE
  • Abortar SMS Intent en Android KitKat
  • Enviar SMS usando SmsManager en android falla en algún dispositivo
  • Android - cómo hacer que mi app sms aplicación por defecto programatically
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.