Как создать намерение, которое эмулирует входящие смс

Прямо сейчас я могу получить смс со следующим кодом:

override fun onReceive(c: Context, i: Intent) {
        val bundle = intent.extras
        if (bundle != null && intent.action == SMS_RECEIVED) {
            var currentMessage: SmsMessage
            var msgs: Array<SmsMessage>? = null
            var pdusObj: Array<Any>? = null
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                msgs = Telephony.Sms.Intents.getMessagesFromIntent(intent)
                currentMessage = msgs!![0]
            } else {
                pdusObj = bundle.get("pdus") as Array<Any>
                currentMessage = SmsMessage.createFromPdu(pdusObj[0] as ByteArray)
            }
            mPhoneNumb = currentMessage.displayOriginatingAddress
}

Мне интересно, могу ли я каким-либо образом сделать что-то обратное: создать намерение (с моим номером телефона и текстовым сообщением) для эмуляции входящих смс.

Есть какой-либо способ сделать это?

ОБНОВЛЕНИЕ:

благодаря MikeM найдите это решение: >Создайте PDU для Android, который работает с SmsMessage.createFromPdu() (GSM 3gpp)

но я все еще не могу отправить поддельное смс на свой широковещательный приемник, на этот раз я получаю вылет со следующей ошибкой:

SecurityException: Permission Denial: not allowed to send broadcast android.provider.Telephony.SMS_RECEIVED from pid=14860, uid=10621

но у меня уже есть это разрешение! вот мой манифест:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.test.test">

    <uses-permission android:name="android.permission.READ_SMS"/>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <uses-permission android:name="android.permission.VIBRATE"/>

<application
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <receiver android:name=".receiver.SmsReceiver">
            <intent-filter android:priority="1000">
                <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
            </intent-filter>
        </receiver>
</application>
</manifest>

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

public class SendTestSms {

    public 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) {
                e.printStackTrace();
            }

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

        Intent intent = new Intent(context, SmsReceiver.class);
        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.sendBroadcast(intent);
    }

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

есть идеи, почему мое разрешение не имеет значения для отправки трансляции?


person Andriy Antonov    schedule 02.02.2017    source источник
comment
Вы можете, но вы сможете отправить его только своему получателю.   -  person Mike M.    schedule 02.02.2017
comment
это именно то, что мне нужно сделать :)   -  person Andriy Antonov    schedule 02.02.2017
comment
В этом посте есть пример создания необходимых PDU, но вам придется заменить там вызовы Intent и startService() на таргетинг Intent ваш приемник и вызов sendBroadcast(). Однако есть и другие способы проверки вашего приемника, если это все, что вы пытаетесь сделать. В эмуляторе вы можете использовать telnet или отправить от одного к другому или использовать встроенный инструмент.   -  person Mike M.    schedule 02.02.2017
comment
Полное раскрытие: я никогда не пробовал ничего из этого. У меня неограниченный обмен сообщениями, поэтому я просто отправляю себе СМС для проверки.   -  person Mike M.    schedule 02.02.2017
comment
Благодарность! я попробую первый, потому что мне нужно проверить получение смс с мобильного (без эмулятора).   -  person Andriy Antonov    schedule 02.02.2017
comment
@MikeM, пожалуйста, взгляните на мой обновленный вопрос. будем рады любым идеям и предложениям!   -  person Andriy Antonov    schedule 04.02.2017
comment
Да, вы не можете транслировать действие SMS_RECEIVED; вы можете только получить его. Вот почему вы можете настроить таргетинг только на свой Receiver. Вам придется удалить вызов setAction() или изменить действие на что-то другое. И удалить setClassName() тоже. На самом деле это не очень хороший тест, поскольку единственное, что вы действительно проверяете, это то, можете ли вы создавать и декодировать PDU. Вот почему я упомянул это в первую очередь. :-)   -  person Mike M.    schedule 04.02.2017