Recibe mensajes MMS en Android KitKat
Por lo que este video Android 4.4 SMS API de #DevBytes explica los cambios recientes en las API de SMS en KitKat. También proporcionan un vínculo con un proyecto de ejemplo. Http://goo.gl/uQ3Nih
Sugieren que usted maneja la recepción de un MMS en un servicio. Que todo parece bien, excepto que se olvidan de mencionar la pieza más indocumentada. Cómo manejar un MMS entrante.
- En la aplicación de facturación V3 Service nullpointer Android
- ¿Por qué un servicio Android no es singleton cuando se prueba?
- Ayúdame a usar correctamente los Servicios y los Hilos
- Uso de GoogleApiClient en un servicio
- Cómo detener el servicio de su propia notificación de primer plano
Aquí está la muestra del proyecto https://gist.github.com/lawloretienne/8970938
He tratado de "manejar el MMS"
Https://gist.github.com/lawloretienne/8971050
Puedo obtener los extras de la intención, pero la única cosa significativa que puedo extraer es el número desde el que se envió el MMS.
¿Puede alguien señalarme en la dirección correcta acerca de cómo hacer esto?
Me di cuenta de que un WAP_PUSH_MESSAGE contiene algunas cosas, un FROM, SUBJECT y CONTENT_LOCATION.
La ubicación del contenido parece ser la url donde está contenido el contenido del MMS. ¿Cómo puedo acceder a esto?
Aquí hay un ejemplo de esa URL
https://atl1mmsget.msg.eng.t-mobile.com/mms/wapenc?location=XXXXXXXXXXX_14zbwk&rid=027
Donde la X es un dígito en el número de teléfono del dispositivo en el que estoy probando.
Parece que el MMSC (Multimedia Messaging Service Center) para T-Mobile en los Estados Unidos es http://mms.msg.eng.t-mobile.com/mms/wapenc
De acuerdo con esta lista: http://www.activexperts.com/xmstoolkit/mmsclist/
- Async tarea no funciona correctamente (doInBackground no se ejecuta) cuando el servicio se ejecuta en segundo plano, Android
- No se puede iniciar el temporizador en un servicio en android
- Android: NullPointerException en android.app.ActivityThread $ PackageInfo $ ServiceDispatcher.doConnected (ActivityThread.java:1012)
- Android: Multithreading-Bluetooth SPP / RFCOMM-Cómo mantener activo mi BluetoothSocket y OutputStream al cambiar Actividades
- Clear Aplicaciones recientes limpiar la memoria de aplicaciones y mi receptor dejó de funcionar
- No se puede iniciar el servicio Intent {cmp = com.marie.mainactivity / .BackgroundService}: no encontrado
- Android Actualizaciones periódicas de la ubicación GPS con AlarmManager dentro de un servicio
- Bluetooth -> fallo en el descubrimiento del servicio
Hay cero documentación así que aquí hay algo de información para ayudar.
1) com.google.android.mms.pdu desde el origen. Usted necesita el Pdu utils.
2) Recibe el impulso de notificación de la matriz de bytes extra de la transmisión de mms entrante (intention.getByteArrayExtra ("datos")).
3) Analizar el empuje de notificación en un GenericPdu (nuevo PduParser (rawPdu) .parse ()).
4) Necesitará TransactionSettings para comunicarse con el servidor wap del transportista. Recibo los ajustes de transacción después de # 5 a continuación. Yo suelo:
TransactionSettings transactionSettings = new TransactionSettings(mContext, mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS).getExtraInfo());
5) Forzar el comm de la red sobre wifi. Yo uso lo siguiente.
private boolean beginMmsConnectivity() { try { int result = mConnMgr.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE, Phone.FEATURE_ENABLE_MMS); NetworkInfo info = mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS); boolean isAvailable = info != null && info.isConnected() && result == Phone.APN_ALREADY_ACTIVE && !Phone.REASON_VOICE_CALL_ENDED.equals(info.getReason()); return isAvailable; } catch(Exception e) { return false; } }
6) A continuación, debe garantizar una ruta hacia el host.
private static void ensureRouteToHost(ConnectivityManager cm, String url, TransactionSettings settings) throws IOException { int inetAddr; if (settings.isProxySet()) { String proxyAddr = settings.getProxyAddress(); inetAddr = lookupHost(proxyAddr); if (inetAddr == -1) { throw new IOException("Cannot establish route for " + url + ": Unknown host"); } else { if (!cm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_MMS, inetAddr)) throw new IOException("Cannot establish route to proxy " + inetAddr); } } else { Uri uri = Uri.parse(url); inetAddr = lookupHost(uri.getHost()); if (inetAddr == -1) { throw new IOException("Cannot establish route for " + url + ": Unknown host"); } else { if (!cm.requestRouteToHost(ConnectivityManager.TYPE_MOBILE_MMS, inetAddr)) throw new IOException("Cannot establish route to " + inetAddr + " for " + url); } } }
Aquí está el método lookupHost:
private static int lookupHost(String hostname) { InetAddress inetAddress; try { inetAddress = InetAddress.getByName(hostname); } catch (UnknownHostException e) { return -1; } byte[] addrBytes; int addr; addrBytes = inetAddress.getAddress(); addr = ((addrBytes[3] & 0xff) << 24) | ((addrBytes[2] & 0xff) << 16) | ((addrBytes[1] & 0xff) << 8) | (addrBytes[0] & 0xff); return addr; }
También me gusta usar un método basado en la reflexión para mejorar la funcionalidad de asegurarRouteToHost:
private static void ensureRouteToHostFancy(ConnectivityManager cm, String url, TransactionSettings settings) throws IOException, NoSuchMethodException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { Method m = cm.getClass().getMethod("requestRouteToHostAddress", new Class[] { int.class, InetAddress.class }); InetAddress inetAddr; if (settings.isProxySet()) { String proxyAddr = settings.getProxyAddress(); try { inetAddr = InetAddress.getByName(proxyAddr); } catch (UnknownHostException e) { throw new IOException("Cannot establish route for " + url + ": Unknown proxy " + proxyAddr); } if (!(Boolean) m.invoke(cm, new Object[] { ConnectivityManager.TYPE_MOBILE_MMS, inetAddr })) throw new IOException("Cannot establish route to proxy " + inetAddr); } else { Uri uri = Uri.parse(url); try { inetAddr = InetAddress.getByName(uri.getHost()); } catch (UnknownHostException e) { throw new IOException("Cannot establish route for " + url + ": Unknown host"); } if (!(Boolean) m.invoke(cm, new Object[] { ConnectivityManager.TYPE_MOBILE_MMS, inetAddr })) throw new IOException("Cannot establish route to " + inetAddr + " for " + url); } }
7) Después de asegurar una ruta al anfitrión usted puede entonces necesitar HttpUtls del origen. He modificado considerablemente mi implementación usando OkHttp para mejorar las comunicaciones.
byte[] rawPdu = HttpUtils.httpConnection(mContext, mContentLocation, null, HttpUtils.HTTP_GET_METHOD, mTransactionSettings.isProxySet(), mTransactionSettings.getProxyAddress(), mTransactionSettings.getProxyPort());
8) De la matriz de bytes resultante utilice el PduParser para separar el GenericPdu. Entonces usted puede extraer el cuerpo y echar a un MultimediaMessagePdu.
9) A continuación, puede iterar las partes de la PDU.
Hay innumerables cosas a considerar con MMS. Una cosa que viene a la mente es cómo molesta presentación de diapositivas son, por lo que lo que hago es detectar si hay más de 1 partes en la PDU, a continuación, copiar los encabezados y crear MultimediaMessagePdu separado de los cuales los guardo al proveedor de contenido MMS del teléfono por separado . No olvide copiar los encabezados especialmente si está apoyando mensajes de grupo. La mensajería de grupo es otra historia porque el número de teléfono entrante en la PDU no cuenta toda la historia (MultimediaMessagePdu.mmpdu ()). Hay más contactos en el encabezado que extrae utilizando el código siguiente.
private HashSet<String> getRecipients(GenericPdu pdu) { PduHeaders header = pdu.getPduHeaders(); HashMap<Integer, EncodedStringValue[]> addressMap = new HashMap<Integer, EncodedStringValue[]>(ADDRESS_FIELDS.length); for (int addrType : ADDRESS_FIELDS) { EncodedStringValue[] array = null; if (addrType == PduHeaders.FROM) { EncodedStringValue v = header.getEncodedStringValue(addrType); if (v != null) { array = new EncodedStringValue[1]; array[0] = v; } } else { array = header.getEncodedStringValues(addrType); } addressMap.put(addrType, array); } HashSet<String> recipients = new HashSet<String>(); loadRecipients(PduHeaders.FROM, recipients, addressMap, false); loadRecipients(PduHeaders.TO, recipients, addressMap, true); return recipients; }
Este es el método de los destinatarios de carga:
private void loadRecipients(int addressType, HashSet<String> recipients, HashMap<Integer, EncodedStringValue[]> addressMap, boolean excludeMyNumber) { EncodedStringValue[] array = addressMap.get(addressType); if (array == null) { return; } // If the TO recipients is only a single address, then we can skip loadRecipients when // we're excluding our own number because we know that address is our own. if (excludeMyNumber && array.length == 1) { return; } String myNumber = excludeMyNumber ? mTelephonyManager.getLine1Number() : null; for (EncodedStringValue v : array) { if (v != null) { String number = v.getString(); if ((myNumber == null || !PhoneNumberUtils.compare(number, myNumber)) && !recipients.contains(number)) { // Only add numbers which aren't my own number. recipients.add(number); } } } }
A continuación se muestra cómo iterar las partes de MultimediaMessagePdu.
private void processPduAttachments() throws Exception { if (mGenericPdu instanceof MultimediaMessagePdu) { PduBody body = ((MultimediaMessagePdu) mGenericPdu).getBody(); if (body != null) { int partsNum = body.getPartsNum(); for (int i = 0; i < partsNum; i++) { try { PduPart part = body.getPart(i); if (part == null || part.getData() == null || part.getContentType() == null || part.getName() == null) continue; String partType = new String(part.getContentType()); String partName = new String(part.getName()); Log.d("Part Name: " + partName); Log.d("Part Type: " + partType); if (ContentType.isTextType(partType)) { } else if (ContentType.isImageType(partType)) { } else if (ContentType.isVideoType(partType)) { } else if (ContentType.isAudioType(partType)) { } } catch (Exception e) { e.printStackTrace(); // Bad part shouldn't ruin the party for the other parts } } } } else { Log.d("Not a MultimediaMessagePdu PDU"); } }
Hay muchas más consideraciones como el soporte de GIF animado, que es totalmente posible 🙂 Algunas compañías de soporte reconocen los informes y los informes de entrega también, lo más probable es que se olvide de estas comunicaciones wap a menos que un usuario realmente quiere informes de entrega mms.
- Android nGPS: obtener ubicación basada en el campo magnético en lugar de gps o triangulación de células
- Insignia en Android TabHost