收到Android的奇巧彩信 [英] Receive MMS messages in Android KitKat

查看:101
本文介绍了收到Android的奇巧彩信的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以这个视频 Android 4.4系统的手机短信的API从#DevBytes 的解释了最近的变化,以奇巧短信的API。他们还提供了示例项目的链接。 http://goo.gl/uQ3Nih

So this video Android 4.4 SMS APIs from #DevBytes explains the recent changes to the SMS APIs in KitKat. They also provide a link with a sample project. http://goo.gl/uQ3Nih

他们认为你处理彩信的服务接收。这一切看起来正常,但他们却忘​​了提及最无证件。如何真正处理传入的彩信。

They suggest that you handle the receive of an MMS in a service. Which all looks fine, except they neglect to mention the most undocumented piece. How to actually handle an incoming MMS.

下面是该项目的样本 <一href="https://gist.github.com/lawloretienne/8970938">https://gist.github.com/lawloretienne/8970938

我曾经试图处理彩信

<一个href="https://gist.github.com/lawloretienne/8971050">https://gist.github.com/lawloretienne/8971050

我可以从意图获取额外但唯一有意义的事情,我可以提取是从中彩信发送的数量。

I can get the extras from the intent but the only meaningful thing that I can extract is the number from which the MMS was sent.

任何人都可以点我怎么去这个方向是正确的?

Can anyone point me in the right direction about how to go about this?

我注意到一个WAP_PUSH_MESSAGE包含几件事情,一个发件人,主题,和CONTENT_LOCATION。

I noticed that a WAP_PUSH_MESSAGE contains a few things, a FROM, SUBJECT, and CONTENT_LOCATION.

的内容位置似乎是其中的MMS的内容被包含的URL。如何访问呢?

The content location appears to be the url where the content of the MMS is contained. How can I access this?

下面是URL的一个例子

Here is an example of that URL

<$c$c>https://atl1mmsget.msg.eng.t-mobile.com/mms/wapenc?location=XXXXXXXXXXX_14zbwk&rid=027

当X是在我正在测试的装置的电话号码数字。

Where the X is a digit in the phone number of the device I am testing on.

它看起来像在美国MMSC(多媒体信息服务中心)为T-Mobile是 http://mms.msg.eng.t-mobile.com/mms/wapenc

It looks like the MMSC (Multimedia Messaging Service Center) for T-Mobile in the U.S. is http://mms.msg.eng.t-mobile.com/mms/wapenc

根据这一列表:<一href="http://www.activexperts.com/xmstoolkit/mmsclist/">http://www.activexperts.com/xmstoolkit/mmsclist/

推荐答案

有零文档所以这里的一些信息,以帮助。

There's zero documentation so here's some info to help.

1)com.google.android.mms.pdu从源。你需要的PDU utils的。

1) com.google.android.mms.pdu from source. You need the Pdu utils.

2)你从传入业务广播的字节数组多余的通知推送(intent.getByteArrayExtra(数据))。

2) You get the notification push from byte array extra of the incoming mms broadcast (intent.getByteArrayExtra("data")).

3)解析通知推到一个GenericPdu(新PduParser(rawPdu).parse())。

3) Parse the notification push into a GenericPdu (new PduParser(rawPdu).parse()).

4)你需要TransactionSettings与运营商的WAP服务器通信。我得到下面的#5后,事务设置。我使用的:

4) You'll need TransactionSettings to communicate with the carrier's wap server. I get the transaction settings after #5 below. I use:

TransactionSettings transactionSettings = new TransactionSettings(mContext, mConnMgr.getNetworkInfo(ConnectivityManager.TYPE_MOBILE_MMS).getExtraInfo());

通过wifi 5)强制网络​​通讯。我用下面的。

5) Force network comm over wifi. I use the following.

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)然后,您需要确保对主机的路由。

6) You then need to ensure a route to the 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);
        }
    }
}

这里的lookupHost方式:

Here's the lookupHost method:

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;
}

我也喜欢使用基于反射的方法改进ensureRouteToHost功能:

I also like to use a reflection based method for improved ensureRouteToHost functionality:

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进行改进的通信。

7) After ensuring a route to the host you can then need HttpUtls from source. I've heavily modified my implementation using OkHttp for improved communications.

byte[] rawPdu = HttpUtils.httpConnection(mContext, mContentLocation, null, HttpUtils.HTTP_GET_METHOD, mTransactionSettings.isProxySet(), mTransactionSettings.getProxyAddress(), mTransactionSettings.getProxyPort());

8)从所得的字节数组使用PduParser到parge的GenericPdu。然后你就可以提取体投地一MultimediaMessagePdu。

8) From the resulting byte array use the PduParser to parge the GenericPdu. Then you can extract the body and cast to a MultimediaMessagePdu.

9),然后就可以遍历PDU的部分。

9) Then you can iterate the parts of the PDU.

有无数的事情彩信考虑。我所想到的一件事是如何讨厌幻灯片的,所以我要做的就是检测是否有超过1件在PDU,然后我复制标题和创建单独的MultimediaMessagePdu其中我将它们保存到手机的彩信内容提供商分别。不要忘了,特别是如果你是支持群发复制的标题。集团短信是另一个故事,因为在PDU的incomging电话号码,并不能说明整个故事(MultimediaMessagePdu.mmpdu())。有一个在头更联系人您提取使用下面的code。

There are countless things to consider with MMS. One thing that comes to mind is how annoying Slideshows are, so what I do is detect if there are more than 1 parts in the PDU, then I copy the headers and create separate MultimediaMessagePdu of which I save them to the phone's mms content provider separately. Don't forget to copy the headers especially if you are supporting group messaging. Group messaging is another story because the incomging telephone number in the PDU doesn't tell the whole story (MultimediaMessagePdu.mmpdu()). There's more contacts in the header that you extract using the following code.

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;
}

下面是负载收件人方式:

Here's the load recipients method:

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部分。

Here's how to iterate the MultimediaMessagePdu parts.

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通信,除非用户真的想彩信的发送情况报告。

There's many more considerations such as animated GIF support, which is entirely possible :) Some carriers support acknowledge reports, and delivery reports too, you can most likely neglect these wap communications unless a user really really wants mms delivery reports.

这篇关于收到Android的奇巧彩信的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆