12

目標: (注: 選択した回答により、GSM (3gpp) PDU が生成されます) CDMA (3gpp2) については、こちらを参照してください。

に渡すことができる PDU を作成しますSmsMessage.createFromPdu(byte[] pdu)BroadcastRecieverSMS メッセージをリッスンしている 1 つに「インテントをブロードキャスト」しています。

1BroadcastReciever

「実際の」 SMSに使用android.provider.Telephony.SMS_RECEIVEDする

これらの新しい「アプリケーション SMS」のカスタムintent-filterアクションを使用します。

@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ことができることを知っていますが、私はそれができることを知っているので、実際にこれをやりたいと思っています、私は頑固です)

リサーチ:

私は昼夜を問わず研究を行っています。私は数学と変換と適切なアルゴリズムの作成に非常にひどいですが、自分で書いてみました。PDUsおよびCreate PDU AndroidのStack トピックを見てきましたが、回答のリンクが壊れています。私もソースコードを見ましたcom.google.android.mms.pdu

これまでのところ、 http://www.wrankl.de/JavaPC/SMSTools.htmlのコードを使用して、「発信元アドレス」なしで PDU を作成することしかできませんでした。

PDU:

宛先: 555 メッセージ: helloworld

"1100038155f50000aa0ae8329bfdbebfe56c32"

これは明らかに有効ではありません...

補足:

ローカルでの使用以外に PDU を使用する予定はありません。PDU を再利用しないため、コードにハード コーディングされた PDU は必要ありません。

「発信元アドレス」を追加するために使用しているコードに追加できるものがあれば、それは機能します。または、私が知らない図書館に関する情報を誰かが持っていますか?

ありがとう

アップデート:

試した

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

これにより、次のようになります(16進数表現)

"0000100200000000000000000000000004010203040000000e000320ec400107102e8cbb366f00"

うまくいきませんでした

4

3 に答える 3

27

たぶん、このスニペットにはあなたが望むような多くの詳細フィールドがありませんが、私の単純な目的のために、それは別の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;
        }
于 2012-09-09T11:05:20.443 に答える
1

直接PDUラングリングを行ってから長い時間が経ちましたが、すぐに諦めてSMSLibを使用しました。これは、ノキアの電話(シリアルリンク経由)経由での送信に完全に機能するPDUユーティリティです。私の仮定(間違っているかもしれません)は、インターフェースが実際に仕様に準拠していると仮定すると、Androidでも機能するということです。

于 2012-09-09T01:01:58.300 に答える
0

console.c でこのコードを確認してください。これは、Android エミュレーターがCMT メッセージが SmsMessage に変換される pduとRIL.javaを作成する場所です。を使用SmsMessage.getPduして pdu を取得できます。しかしSmsMessage.newFromCmt、内部APIのようです。そのため、信頼できない可能性があります。

さらに、これは Gsm のためだけのものです。cdma には完全に異なるコードフローがあり、RIL.java とモデムは完全にメーカー固有であるため、これはエミュレーターでのみ機能する可能性があります。

通常、GSM コードは Android でより信頼性が高いため、gsm 電話でも同様に機能する可能性があります。試してみてください。

于 2012-09-09T16:02:28.270 に答える