studio receive example enviar code app and android sms smsmanager

receive - sms api android example



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

Con respecto a la solución @Vibhav, aquí es cómo podría implementarla exitosamente

method = Class.forName("android.telephony.SubscriptionManager").getDeclaredMethod("getSubId", int.class); method.setAccessible(true); int simID = 1; //while simID is the slot number of your second simCard param = (int[]) method.invoke(null, new Integer(simID)); int inst = param[0]; smsMan = SmsManager.getSmsManagerForSubscriptionId(inst); smsMan.sendTextMessage(toNum, null, smsText, null, null);

Esta solución funcionó bien conmigo, pero recomendaría esta solución mucho más limpia (no se necesita reflexión, funciona para el nivel API 22+) que se encuentra aquí https://stackoverflow.com/a/51380282/3427883

Estoy usando el administrador de SMS para enviar SMS. Para una SIM simple, funciona perfectamente para enviar SMS.pero en la SIM dual, el SMS no se enviará. Para enviar SMS.Puede que alguien sepa ayudarme a resolver este problema.

Código de trabajo de una sola tarjeta SIM

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


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 el SDK 22, en realidad también funciona para Micromax Canvas 4 (Android 4.2).

Pero para algunas marcas de teléfonos como Lenevo, Asus con Android 5.0, se produce un error con

java.lang.NullPointerException: intento invocar el método virtual ''Java.lang.Class Java.Lang.Object.GetClass () '' en una referencia de objetos nula "en el código

" method = 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.


La solución de Maher es casi la correcta.

Lo probé en Motorola motog 5.1 android (simulador único), pero su solución con el content://telephony/siminfo tabla de lectura content://telephony/siminfo tuvo un pequeño error:

en mi motorola no había slot campo pero sim_id

El resto de esto estaba bien e idéntico.


Probé el método Mahers Refletion para enviar sms en teléfonos Android con doble simulación (API 19 y anteriores). 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 mucho depuración y algo más de búsqueda, el 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:


Utilizo esta forma para administrar qué simulador usar para enviar mensajes SMS, incluso largos. Está funcionando en mi teléfono dual sim Lenovo A319 (4.4.3), sin necesidad de root. está 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 solo llama a ese (sangriento) método estático como este :)

Para utilizar SIM1:

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

Para utilizar SIM2:

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

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

String textSMS; //short <160 // textSMS = "Hi ! 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); }

para que pueda pasar el cuerpo del mensaje de forma segura sin preocuparse por la longitud.

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

Para usar PendingIntent / DeliveryIntent en MultipartMessage .. simplemente cree ArrayList con el mismo contenido y páselo. Aquí hay una implementación de la creación de List of 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, simplemente use el mismo enfoque.

------------------ Extra ------------------

He visto que Android 22 es compatible con varias tarjetas SIM de Android 5.1 y aquí es cómo usarlo. Desafortunadamente, no tengo un dispositivo con esa versión para probar, así que por favor, para comentarios:

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

¿Cómo obtener subscripciónId? para revisar todos los ID de suscripción 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 está trabajando en 5.1. si intenta ejecutarlo en una versión anterior, obtendría una excepción de que el método no existe.

------------ ACTUALIZACIÓN 19.8.2015 ----------

La información sobre las SIM se encuentra 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.

Afortunadamente hay un proveedor de contenido para eso:

"content://telephony/siminfo/"

Básicamente, consulte los datos de esa tabla. Es importante mencionar que la ranura 0 representa la SIM1, y la 1 representa la SIM2, y la ranura -1 de las SIM antiguas / removidas / reemplazadas.

Esto se aplica en Lenovo A319. Supongo que eso 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,''.