Попытка получить MMS-сообщение android [duplicate]

Вам нужно правильно отделить статические данные от данных экземпляра. В вашем коде onLoan и setLoanItem() являются членами экземпляра. Если вы хотите ссылаться / называть их, вы должны сделать это через экземпляр. Таким образом, вы либо хотите

public void loanItem() {
    this.media.setLoanItem("Yes");
}

, либо

public void loanItem(Media object) {
    object.setLoanItem("Yes");
}

в зависимости от того, как вы хотите передать этот экземпляр.

14
задан toobsco42 14 February 2014 в 21:03
поделиться

1 ответ

Есть нулевая документация, поэтому вот вам информация.

1) com.google.android.mms.pdu из источника. Вам нужны Pdu utils.

2) Вы получаете уведомление из массива байтов, кроме входящего MMS-сообщения (intent.getByteArrayExtra («данные»)).

3) Разбор уведомление вводится в GenericPdu (новый PduParser (rawPdu) .parse ()).

4) Вам понадобятся TransactionSettings для связи с WAP-сервером оператора. Я получаю настройки транзакции после №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, из которых я сохраняю их в контентном провайдере телефона mms отдельно , Не забудьте скопировать заголовки, особенно если вы поддерживаете групповые сообщения. Групповая передача сообщений - еще одна история, потому что номер телефона 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 отчеты о доставке.

22
ответ дан Noah Seidman 22 August 2018 в 07:47
поделиться
  • 1
    Привет @Noah, в исходном коде Android есть тонны классов, которые связаны с mms. есть ли определенный набор классов, которые мне нужны, чтобы заставить это работать? Потому что есть тонны зависимостей для разрешения с недопустимым импортом. – toobsco42 20 April 2014 в 04:27
  • 2
    В первую очередь вам нужны утилиты pdu. com.google.android.mms.pdu. Вам понадобятся TransactionSettings и его зависимости, у него есть некоторые проблемы, и во многих отношениях они должны быть значительно упрощены, по крайней мере, проекция и предложение предложения поставщика контента. Помните, что запрос в настройках транзакции будет надежно работать только на устройствах KitKat. – Noah Seidman 14 May 2014 в 22:48
  • 3
    Я не понимаю, как использовать константы, такие как ADDRESS_FIELDS.length, вы можете уточнить, к чему они должны быть инициализированы? – Tim Miller 5 June 2015 в 19:00
  • 4
    @TimMiller Это значения, импортированные из одного из исходных файлов. private static final int[] ADDRESS_FIELDS = new int[] { PduHeaders.BCC, PduHeaders.CC, PduHeaders.FROM, PduHeaders.TO }; – Abandoned Cart 22 April 2017 в 02:56
  • 5
    – not2qubit 4 October 2018 в 17:14
Другие вопросы по тегам:

Похожие вопросы: