Создайте PDU для Android, который работает с SmsMessage.createFromPdu() (GSM 3gpp)

Цель: (ПРИМЕЧАНИЕ. Выбранный ответ генерирует PDU GSM (3gpp) для CDMA (3gpp2), пожалуйста, см. здесь p >

Создание PDU, который можно передать в SmsMessage.createFromPdu(byte[] pdu). Я "трансляция намерения" в один из моих BroadcastReciever, который прослушивает SMS-сообщения.

Один BroadcastReciever

Использование android.provider.Telephony.SMS_RECEIVED для "реальных" SMS

Использование пользовательского действия intent-filter для этих новых "SMS-сообщений приложения".

@Override
public void onReceive(Context context, Intent intent) {

    Bundle bundle = intent.getExtras();

    if (bundle != null) {
        Object[] pdusObj = (Object[]) bundle.get("pdus");
        SmsMessage[] messages = new SmsMessage[pdusObj.length];

        // getting SMS information from Pdu.
        for (int i = 0; i < pdusObj.length; i++) {
            messages[i] = SmsMessage.createFromPdu((byte[]) pdusObj[i]);
        }

        for (SmsMessage currentMessage : messages) {
            //the currentMessage.getDisplayOriginatingAddress() 
            //or .getDisplayMessageBody() is null if I Broadcast a fake sms
            Log.i("BB", "address:"+currentMessage.getDisplayOriginatingAddress()+" message:"+currentMessage.getDisplayMessageBody());
    ...

Итак, я хочу, чтобы мой BroadcastReciever мог обрабатывать оба типа сообщений без добавления дополнительного кода

(да, я знаю, что у меня может быть другой BroadcastReciever для другого действия intent-filter, но я хотел бы на самом деле снять это, поскольку я знаю, что это можно сделать, я упрямый)

Исследование:

Я занимаюсь исследованиями весь день и ночь. Я попытался написать свой собственный, хотя я очень страшен с математикой и преобразованиями и создаю подходящий алгоритм. Я просмотрел темы в блоках PDU и Создать PDU Android, но ссылка нарушена в ответе, Я даже посмотрел на com.google.android.mms.pdu исходный код

до сих пор мне удалось создать PDU без "исходящего адреса", используя какой-то код из http://www.wrankl.de/JavaPC/SMSTools.html

PDU:

назначение: 555 сообщение: helloworld

"1100038155f50000aa0ae8329bfdbebfe56c32"

Что явно недействительно...

Боковые заметки:

Я не планирую ничего делать с PDU помимо локального использования, я не хочу жестко закодированный PDU в своем коде, потому что я не повторно использую PDU.

Если есть что-то, что я могу добавить к коду, который я использую для добавления в "исходящий адрес", это будет работать. Или у кого-нибудь есть информация о библиотеке, о которой я не знаю?

Спасибо

Обновление:

попробовал

byte[] by =(byte[])(SmsMessage.getSubmitPdu("12345", "1234", "hello", false).encodedMessage);

который дает мне следующее (в шестнадцатеричном представлении)

"0000100200000000000000000000000004010203040000000e000320ec400107102e8cbb366f00"

не работает

Ответ 1

Возможно, этот фрагмент не содержит много полей сведений, как вы хотите, но для моей простой цели он может вызывать уведомление, подобное другому sms.

    private static void createFakeSms(Context context, String sender,
        String body) {
    byte[] pdu = null;
    byte[] scBytes = PhoneNumberUtils
            .networkPortionToCalledPartyBCD("0000000000");
    byte[] senderBytes = PhoneNumberUtils
            .networkPortionToCalledPartyBCD(sender);
    int lsmcs = scBytes.length;
    byte[] dateBytes = new byte[7];
    Calendar calendar = new GregorianCalendar();
    dateBytes[0] = reverseByte((byte) (calendar.get(Calendar.YEAR)));
    dateBytes[1] = reverseByte((byte) (calendar.get(Calendar.MONTH) + 1));
    dateBytes[2] = reverseByte((byte) (calendar.get(Calendar.DAY_OF_MONTH)));
    dateBytes[3] = reverseByte((byte) (calendar.get(Calendar.HOUR_OF_DAY)));
    dateBytes[4] = reverseByte((byte) (calendar.get(Calendar.MINUTE)));
    dateBytes[5] = reverseByte((byte) (calendar.get(Calendar.SECOND)));
    dateBytes[6] = reverseByte((byte) ((calendar.get(Calendar.ZONE_OFFSET) + calendar
            .get(Calendar.DST_OFFSET)) / (60 * 1000 * 15)));
    try {
        ByteArrayOutputStream bo = new ByteArrayOutputStream();
        bo.write(lsmcs);
        bo.write(scBytes);
        bo.write(0x04);
        bo.write((byte) sender.length());
        bo.write(senderBytes);
        bo.write(0x00);
        bo.write(0x00); // encoding: 0 for default 7bit
        bo.write(dateBytes);
        try {
            String sReflectedClassName = "com.android.internal.telephony.GsmAlphabet";
            Class cReflectedNFCExtras = Class.forName(sReflectedClassName);
            Method stringToGsm7BitPacked = cReflectedNFCExtras.getMethod(
                    "stringToGsm7BitPacked", new Class[] { String.class });
            stringToGsm7BitPacked.setAccessible(true);
            byte[] bodybytes = (byte[]) stringToGsm7BitPacked.invoke(null,
                    body);
            bo.write(bodybytes);
        } catch (Exception e) {
        }

        pdu = bo.toByteArray();
    } catch (IOException e) {
    }

    Intent intent = new Intent();
    intent.setClassName("com.android.mms",
            "com.android.mms.transaction.SmsReceiverService");
    intent.setAction("android.provider.Telephony.SMS_RECEIVED");
    intent.putExtra("pdus", new Object[] { pdu });
    intent.putExtra("format", "3gpp");
    context.startService(intent);
}

private static byte reverseByte(byte b) {
    return (byte) ((b & 0xF0) >> 4 | (b & 0x0F) << 4);
}

Надеюсь, вы найдете что-то полезное

Обновление:

 public static final SmsMessage[] getMessagesFromIntent(
                Intent intent) {
            Object[] messages = (Object[]) intent.getSerializableExtra("pdus");
            byte[][] pduObjs = new byte[messages.length][];

            for (int i = 0; i < messages.length; i++) {
                pduObjs[i] = (byte[]) messages[i];
            }
            byte[][] pdus = new byte[pduObjs.length][];
            int pduCount = pdus.length;
            SmsMessage[] msgs = new SmsMessage[pduCount];
            for (int i = 0; i < pduCount; i++) {
                pdus[i] = pduObjs[i];
                msgs[i] = SmsMessage.createFromPdu(pdus[i]);
            }
            return msgs;
        }

Ответ 2

Это было долгое время с тех пор, как я совершил какие-либо прямые споры PDU, но когда я это сделал, я быстро сдался и использовал SMSLib: утилиты PDU он отлично работал для отправки через телефоны Nokia (через последовательную ссылку). Мое предположение (что может быть неправильно) заключается в том, что они будут работать и для Android, предполагая, что интерфейс действительно соответствует спецификации.

Ответ 3

Проверьте этот код в console.c. Именно здесь эмулятор android создает pdu и RIL.java, где сообщение CMT преобразуется в SmsMessage. Вы можете использовать SmsMessage.getPdu, чтобы получить pdu. Но SmsMessage.newFromCmt выглядит внутренним api. Так что это может быть ненадежным.

Кроме того, это просто для Gsm, cdma имеет совершенно другой код и поскольку RIL.java и модем полностью специфичны для производителя, это может работать только на эмуляторе.

Обычно код GSM более надежный на Android, поэтому может работать и на телефоне gsm. Попробуйте.