Ответ 1
Там есть нулевая документация, поэтому здесь можно найти некоторую информацию.
1) com.google.android.mms.pdu из источника. Вам нужны утилиты Pdu.
2) Вы получаете извещение уведомления от байтового массива дополнительно от входящего широковещательного сообщения mms (intent.getByteArrayExtra( "данные" )).
3) Разберите уведомление в GenericPdu (новый PduParser (rawPdu).parse()).
4) Для связи с WAP-сервером оператора вам понадобятся TransactionSettings. Я получаю настройки транзакции после №5 ниже. Я использую:
TransactionSettings transactionSettings = new TransactionSettings(mContext, mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS).getExtraInfo());
5) Соедините сеть с Wi-Fi. Я использую следующее.
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) Затем вам необходимо обеспечить маршрут к хосту.
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);
}
}
}
Здесь метод 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;
}
Мне также нравится использовать метод, основанный на отражении, для улучшения функции обеспечения RouteToHost:
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) После обеспечения маршрута к хосту вам может понадобиться HttpUtls из источника. Я сильно изменил мою реализацию, используя OkHttp для улучшения связи.
byte[] rawPdu = HttpUtils.httpConnection(mContext, mContentLocation, null, HttpUtils.HTTP_GET_METHOD, mTransactionSettings.isProxySet(), mTransactionSettings.getProxyAddress(), mTransactionSettings.getProxyPort());
8). Из полученного массива байтов используйте PduParser для оплаты GenericPdu. Затем вы можете извлечь тело и бросить на MultimediaMessagePdu.
9) Затем вы можете выполнять итерацию частей PDU.
Есть множество вещей, которые следует учитывать при использовании MMS. Одна вещь, которая приходит на ум, - это то, как раздражают слайд-шоу, поэтому я обнаруживаю, что в PDU есть более 1 части, затем я копирую заголовки и создаю отдельный MultimediaMessagePdu, из которых я сохраняю их в телефоне., Не забудьте скопировать заголовки, особенно если вы поддерживаете групповые сообщения. Групповая передача сообщений - еще одна история, потому что номер телефона incomging в PDU не рассказывает всю историю (MultimediaMessagePdu.mmpdu()). Там больше контактов в заголовке, который вы извлекаете, используя следующий код.
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;
}
Здесь метод получателей нагрузки:
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);
}
}
}
}
Здесь, как итерировать части 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");
}
}
Есть много других соображений, таких как анимированная поддержка GIF, что вполне возможно:) Некоторые операторы поддерживают отчеты о подтверждении и отчеты о доставке тоже, вы, скорее всего, пренебрегаете этими wap-коммуникациями, если пользователь действительно не хочет получать отчеты о доставке mms.