Crear PDU para Android que funcione con SmsMessage.createFromPdu () (GSM 3gpp)

Objetivo: (NOTA: la respuesta seleccionada genera una PDU GSM (3gpp)) para CDMA (3gpp2) consulte aquí

Para crear una PDU que se pueda pasar a SmsMessage.createFromPdu(byte[] pdu) . Estoy “Transmitiendo un bash” a uno de mis BroadcastReciever que escucha mensajes SMS.

One BroadcastReciever

Usar android.provider.Telephony.SMS_RECEIVED para SMS “reales”

Usar una acción personalizada intent-filter para estos nuevos “SMS de aplicación” .

 @Override public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); if (bundle != null) { Object[] pdusObj = (Object[]) bundle.get("pdus"); SmsMessage[] messages = new SmsMessage[pdusObj.length]; // getting SMS information from Pdu. for (int i = 0; i < pdusObj.length; i++) { messages[i] = SmsMessage.createFromPdu((byte[]) pdusObj[i]); } for (SmsMessage currentMessage : messages) { //the currentMessage.getDisplayOriginatingAddress() //or .getDisplayMessageBody() is null if I Broadcast a fake sms Log.i("BB", "address:"+currentMessage.getDisplayOriginatingAddress()+" message:"+currentMessage.getDisplayMessageBody()); ... 

Así que quiero que mi BroadcastReciever pueda manejar ambos tipos de mensajes sin agregar código adicional

(Sí, sé que puedo tener un BroadcastReciever diferente para la acción de intent-filter diferente intent-filter pero me gustaría llevarlo a cabo porque sé que se puede hacer, soy terco)

Investigación:

He estado investigando todo el día / noche. Intenté escribir el mío aunque soy muy malo con las matemáticas y las conversiones y creo un algoritmo adecuado. He revisado los temas de stack en PDU y creo PDU Android, pero el enlace está roto en la respuesta. Incluso miré el código fuente com.google.android.mms.pdu

hasta ahora solo he podido crear una PDU sin una ” dirección de origen ” usando algún código de http://www.wrankl.de/JavaPC/SMSTools.html

PDU:

destino: 555 mensaje: helloworld

 "1100038155f50000aa0ae8329bfdbebfe56c32" 

Lo cual obviamente no es válido …

Notas secundarias:

No planeo hacer nada con la PDU además del uso local, no quiero PDU codificadas en mi código porque no estoy reutilizando la PDU.

Si hay algo que pueda agregar al código que estoy usando para agregar una “dirección de origen” , eso funcionará. ¿O alguien tiene información sobre una biblioteca de la que no tengo conocimiento?

Gracias

Actualizaciones:

intentó

 byte[] by =(byte[])(SmsMessage.getSubmitPdu("12345", "1234", "hello", false).encodedMessage); 

que me da lo siguiente (en representación hexadecimal)

 "0000100200000000000000000000000004010203040000000e000320ec400107102e8cbb366f00" 

no funcionó

Tal vez este fragmento no tenga muchos campos de detalles como quieras, pero para mi simple propósito puede invocar la notificación como otro sms.

  private static void createFakeSms(Context context, String sender, String body) { byte[] pdu = null; byte[] scBytes = PhoneNumberUtils .networkPortionToCalledPartyBCD("0000000000"); byte[] senderBytes = PhoneNumberUtils .networkPortionToCalledPartyBCD(sender); int lsmcs = scBytes.length; byte[] dateBytes = new byte[7]; Calendar calendar = new GregorianCalendar(); dateBytes[0] = reverseByte((byte) (calendar.get(Calendar.YEAR))); dateBytes[1] = reverseByte((byte) (calendar.get(Calendar.MONTH) + 1)); dateBytes[2] = reverseByte((byte) (calendar.get(Calendar.DAY_OF_MONTH))); dateBytes[3] = reverseByte((byte) (calendar.get(Calendar.HOUR_OF_DAY))); dateBytes[4] = reverseByte((byte) (calendar.get(Calendar.MINUTE))); dateBytes[5] = reverseByte((byte) (calendar.get(Calendar.SECOND))); dateBytes[6] = reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET) + calendar .get(Calendar.DST_OFFSET)) / (60 * 1000 * 15))); try { ByteArrayOutputStream bo = new ByteArrayOutputStream(); bo.write(lsmcs); bo.write(scBytes); bo.write(0x04); bo.write((byte) sender.length()); bo.write(senderBytes); bo.write(0x00); bo.write(0x00); // encoding: 0 for default 7bit bo.write(dateBytes); try { String sReflectedClassName = "com.android.internal.telephony.GsmAlphabet"; Class cReflectedNFCExtras = Class.forName(sReflectedClassName); Method stringToGsm7BitPacked = cReflectedNFCExtras.getMethod( "stringToGsm7BitPacked", new Class[] { String.class }); stringToGsm7BitPacked.setAccessible(true); byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null, body); bo.write(bodybytes); } catch (Exception e) { } pdu = bo.toByteArray(); } catch (IOException e) { } Intent intent = new Intent(); intent.setClassName("com.android.mms", "com.android.mms.transaction.SmsReceiverService"); intent.setAction("android.provider.Telephony.SMS_RECEIVED"); intent.putExtra("pdus", new Object[] { pdu }); intent.putExtra("format", "3gpp"); context.startService(intent); } private static byte reverseByte(byte b) { return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) < < 4); } 

Espero que encuentres algo útil

Actualización:

  public static final SmsMessage[] getMessagesFromIntent( Intent intent) { Object[] messages = (Object[]) intent.getSerializableExtra("pdus"); byte[][] pduObjs = new byte[messages.length][]; for (int i = 0; i < messages.length; i++) { pduObjs[i] = (byte[]) messages[i]; } byte[][] pdus = new byte[pduObjs.length][]; int pduCount = pdus.length; SmsMessage[] msgs = new SmsMessage[pduCount]; for (int i = 0; i < pduCount; i++) { pdus[i] = pduObjs[i]; msgs[i] = SmsMessage.createFromPdu(pdus[i]); } return msgs; } 

Ha pasado mucho tiempo desde que realicé cualquier disputa directa con PDU, pero cuando lo hice, me di por vencida rápidamente y utilicé SMSLib : las utilidades de la PDU funcionaron perfectamente para enviarlas a través de teléfonos Nokia (a través de un enlace en serie). Mi suposición (que puede ser incorrecta) es que también funcionarán para Android, suponiendo que la interfaz es realmente compatible con la especificación.

Verifique este código en console.c . Aquí es donde el emulador de Android crea el pdu y RIL.java donde el mensaje CMT se convierte en un SmsMessage. Puede usar SmsMessage.getPdu para obtener el pdu. Pero SmsMessage.newFromCmt parece ser una API interna. Entonces podría no ser confiable.

Además, esto es solo para Gsm, cdma tiene un flujo de código completamente diferente y dado que RIL.java y el módem son completamente específicos del fabricante, esto podría funcionar solo en el emulador.

Por lo general, el código GSM es más confiable en Android, por lo que también podría funcionar en el teléfono gsm. Pruébalo.