Odbieraj wiadomości MMS w Android KitKat
Więc ten film Android 4.4 SMS API z #DevBytes wyjaśnia ostatnie zmiany w SMS API w KitKat. Zapewniają również link do przykładowego projektu. http://goo.gl/uQ3Nih
Sugerują, że zajmujesz się odbieraniem MMS w usłudze. Wszystko wygląda dobrze, z wyjątkiem tego, że nie wspominają o najbardziej nieudokumentowanym kawałku. Jak właściwie obsługiwać przychodzące MMS.
Oto próbka z projekt https://gist.github.com/lawloretienne/8970938
Próbowałem "obsługiwać MMS"
Https://gist.github.com/lawloretienne/8971050
Mogę uzyskać dodatki z intencji, ale jedyną sensowną rzeczą, którą mogę wyodrębnić, jest numer, z którego wysłano MMS.
Czy ktoś może wskazać mi właściwy kierunek, jak to zrobić?
Zauważyłem, że WAP_PUSH_MESSAGE zawiera kilka rzeczy, od, temat i CONTENT_LOCATION.
Lokalizacja zawartości wydaje się być adresem url, w którym znajduje się zawartość MMS. Jak Mogę uzyskać do tego dostęp?
Oto przykład tego adresu URL
https://atl1mmsget.msg.eng.t-mobile.com/mms/wapenc?location=XXXXXXXXXXX_14zbwk&rid=027
Gdzie X jest cyfrą w numerze telefonu urządzenia, na którym testuję.
Wygląda na to, że MMSC (Multimedia Messaging Service Center) dla T-Mobile w USA to http://mms.msg.eng.t-mobile.com/mms/wapenc
Według tej listy: http://www.activexperts.com/xmstoolkit/mmsclist/
1 answers
Nie ma żadnej dokumentacji, więc tutaj jest kilka informacji, które pomogą.
[[9]}1) kom.google.android.mms.opracowano na podstawie materiału źródłowego. Potrzebujesz Pdu utils.2) otrzymujesz powiadomienie push z tablicy bajtów extra o przychodzącej transmisji mms (intent.getByteArrayExtra("dane")).
3) Parse the notification push into a GenericPdu (new PduParser(rawPdu).parse()).
4) do komunikacji z serwerem WAP operatora potrzebne będą transakcje. Dostaję ustawienia transakcji po #5 poniżej. Używam:
TransactionSettings transactionSettings = new TransactionSettings(mContext, mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS).getExtraInfo());
[[9]}5) Wymuś komunikację sieciową przez wifi. Używam następujących.
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) Następnie należy zapewnić drogę do gospodarza.
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);
}
}
}
Oto metoda 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;
}
Lubię również używać metody opartej na odbiciu dla poprawy funkcjonalności ensureRouteToHost:
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) po zapewnieniu trasy do hosta możesz potrzebować HttpUtls ze źródła. Mocno zmodyfikowałem moją implementację używając OkHttp dla poprawy komunikacja.
byte[] rawPdu = HttpUtils.httpConnection(mContext, mContentLocation, null, HttpUtils.HTTP_GET_METHOD, mTransactionSettings.isProxySet(), mTransactionSettings.getProxyAddress(), mTransactionSettings.getProxyPort());
8) z wynikowej tablicy bajtów użyj Pduparsera do parowania GenericPdu. Następnie można wyodrębnić ciało i rzucić do MultimediaMessagePdu.
9) następnie można iterację części PDU.
Istnieje niezliczona ilość rzeczy do rozważenia Z MMS. Jedną rzeczą, która przychodzi mi na myśl, jest to, jak irytujące są pokazy slajdów, więc to, co robię, to wykrywam, czy w PDU jest więcej niż 1 część, następnie kopiuję nagłówki i tworzę oddzielne MultimediaMessagePdu, z których zapisz je osobno u dostawcy treści mms telefonu. Nie zapomnij skopiować nagłówków, zwłaszcza jeśli obsługujesz wiadomości grupowe. Grupowe wiadomości to inna historia, ponieważ numer telefonu w PDU nie mówi całej historii (MultimediaMessagePdu.mmpdu ()). W nagłówku jest więcej kontaktów, które wyodrębniasz za pomocą następującego kodu.
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;
}
Oto metoda odbiorców obciążenia:
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);
}
}
}
}
Oto jak iterować MultimediaMessagePdu części.
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");
}
}
Jest o wiele więcej rozważań, takich jak animowane wsparcie GIF, które jest całkowicie możliwe :) niektórzy przewoźnicy obsługują raporty potwierdzające, a raporty dostawy też, najprawdopodobniej możesz zaniedbać te komunikaty wap, chyba że użytkownik naprawdę chce raportów dostawy mms.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-23 15:02:48