Подтвердить что ты не робот

BroadcastReceiver + SMS_RECEIVED

Я хочу, чтобы мое приложение поймало входящие SMS-сообщения. Есть несколько примеров этого. Похоже, нам просто нужно это сделать:

// AndroidManifest.xml
<receiver android:name=".SMSReceiver"> 
  <intent-filter> 
    <action android:name="android.provider.Telephony.SMS_RECEIVED" /> 
  </intent-filter> 
</receiver>        

// SMSReceiver.java
public class SMSReceiver extends BroadcastReceiver 
{ 
    @Override 
    public void onReceive(Context context, Intent intent) { 
        Log.i(TAG, "SMS received.");
        ....
    }
}

Это правильно? Я отправляю свой телефон на некоторые sms-сообщения, но оператор журнала никогда не печатается. У меня есть некоторые другие SMS-приложения, установленные на телефоне, которые отображают всплывающее окно при получении sms - они каким-то образом блокируют намерение получить доступ к моему приложению, они просто поглощают его полностью?

Спасибо

4b9b3361

Ответ 2

Еще одна вещь, о которой эти ответы не упомянуты, - вы должны потребовать разрешение android.permission.BROADCAST_SMS. Если вы этого не сделаете, любое приложение может обманывать сообщения в вашем приложении.

<receiver android:name=".SMSReceiver"
              android:exported="true"
              android:permission="android.permission.BROADCAST_SMS">
             <intent-filter>
                 <action android:name="android.provider.Telephony.SMS_RECEIVED"/>
             </intent-filter>
 </receiver>

Ответ 3

В пути есть несколько ошибок. Вы можете найти всю необходимую информацию о stackoverflow. Для удобства я собрал всю информацию в этом ответе.

Что нужно заметить

  • Я предполагаю android kitkat и выше.
  • Цель использования sms - "android.provider.Telephony.SMS_RECEIVED"
  • Вы можете изменить приоритет фильтра намерений, но это не обязательно.
  • Вам нужно это разрешение "android.permission.RECEIVE_SMS" в манифесте xml, чтобы получать sms-сообщения. В android 6 и выше вам также необходимо запросить разрешение во время выполнения.
  • Вам не нужно устанавливать тип данных MIME в фильтр намерений. Фильтр Intent должен проходить только на пустые данные, если не задан тип MIME, но, к счастью, он будет работать без MIME.
  • adb shell am broadcast не будет работать. Используйте telnet-соединение с симулятором для проверки получения sms.
  • Длинные sms-сообщения делятся на маленькие куски sms. Нам нужно их конкатенировать.

Как отправить sms-сообщение в эмулятор

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

Для этого мы будем использовать виртуальное устройство и telnet-соединение с ним.

  • Создайте виртуальное устройство в студии android и запустите симулятор
  • Посмотрите на строку заголовка в окне симулятора. Имя устройства и номер порта . Нам нужно знать этот номер порта в следующих шагах.
  • Теперь подключитесь к номеру порта, указанному в строке заголовка симулятора, с помощью telnet

     $ telnet localhost 5554
    
  • Если вы видите это: Android Console: Authentication required, вам необходимо аутентифицировать соединение с помощью этой команды:

     auth xxxxxx
    

    Замените xxxxxx выше маркером, читаемым из файла ~/.emulator_console_auth_token.

  • Теперь вы должны иметь возможность запускать все команды. Чтобы отправить sms-сообщение, введите следующую команду:

     sms send 555 "This is a message"
    

    Если вы можете заменить 555 на номер телефона отправителя и собственное сообщение.

Как слушать трансляции SMS_RECEIVED

Чтобы получить трансляции, вам необходимо зарегистрировать объект BroadcastReceiver. Вы можете сделать это в функции manifest.xml ИЛИ только для вызова registerReceiver. Я покажу вам последнее, поскольку легче рассуждать и все же более гибко.

Подключение широковещательного приемника к основной активности

Поток данных является одним из способов. От широковещательного приемника до основного действия. Поэтому самый простой способ заставить их говорить - использовать функциональный интерфейс. Эта функция будет выполнять такую ​​функцию, и широковещательный приемник будет иметь экземпляр активности, переданный в качестве параметра в конструкторе.

Файл SmsHandler.java:

package ...

interface SmsHandler {
    void handleSms(String sender, String message);
}

Реализация широковещательного приемника

Радиовещательный приемник получит намерение в обратном вызове. Мы будем использовать функцию Telephony.Sms.Intents.getMessagesFromIntent(intent) для получения sms-сообщений. Обратите внимание на параметр SmsHandler в конструкторе. Это будет активность, на которую мы отправим полученные sms.

Файл SmsInterceptor.java:

package ...

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.provider.Telephony;
import android.telephony.SmsMessage;

public class SmsInterceptor extends BroadcastReceiver {

    private SmsHandler handler;

    /* Constructor. Handler is the activity  *
     * which will show the messages to user. */
    public SmsInterceptor(SmsHandler handler) {
        this.handler = handler;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        /* Retrieve the sms message chunks from the intent */
        SmsMessage[] rawSmsChunks;
        try {
            rawSmsChunks = Telephony.Sms.Intents.getMessagesFromIntent(intent);
        } catch (NullPointerException ignored) { return; }

        /* Gather all sms chunks for each sender separately */
        Map<String, StringBuilder> sendersMap = new HashMap<>();
        for (SmsMessage rawSmsChunk : rawSmsChunks) {
            if (rawSmsChunk != null) {
                String sender = rawSmsChunk.getDisplayOriginatingAddress();
                String smsChunk = rawSmsChunk.getDisplayMessageBody();
                StringBuilder smsBuilder;
                if ( ! sendersMap.containsKey(sender) ) {
                    /* For each new sender create a separate StringBuilder */
                    smsBuilder = new StringBuilder();
                    sendersMap.put(sender, smsBuilder);
                } else {
                    /* Sender already in map. Retrieve the StringBuilder */
                    smsBuilder = sendersMap.get(sender);
                }
                /* Add the sms chunk to the string builder */
                smsBuilder.append(smsChunk);
            }
        }

        /* Loop over every sms thread and concatenate the sms chunks to one piece */
        for ( Map.Entry<String, StringBuilder> smsThread : sendersMap.entrySet() ) {
            String sender  = smsThread.getKey();
            StringBuilder smsBuilder = smsThread.getValue();
            String message = smsBuilder.toString();
            handler.handleSms(sender, message);
        }
    }
}

Основное действие

Наконец, нам нужно реализовать интерфейс SmsHandler в основной активности и добавить регистрацию широковещательного приемника и проверку разрешения на функцию onCreate.

Файл MainActivity.java:

package ...

import ...

public class MainActivity extends AppCompatActivity implements SmsHandler {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        /* Register the broadcast receiver */
        registerSmsListener();

        /* Make sure, we have the permissions */
        requestSmsPermission();
    }

    /* This function will be called by the broadcast receiver */
    @Override
    public void handleSms(String sender, String message) {
        /* Here you can display the message to the user */
    }

    private void registerSmsListener() {
        IntentFilter filter = new IntentFilter();
        filter.addAction("android.provider.Telephony.SMS_RECEIVED");
        /* filter.setPriority(999); This is optional. */
        SmsInterceptor receiver = new SmsInterceptor(this);
        registerReceiver(receiver, filter);
    }

    private void requestSmsPermission() {
        String permission = Manifest.permission.RECEIVE_SMS;
        int grant = ContextCompat.checkSelfPermission(this, permission);
        if ( grant != PackageManager.PERMISSION_GRANTED) {
            String[] permission_list = new String[1];
            permission_list[0] = permission;
            ActivityCompat.requestPermissions(this, permission_list, 1);
        }
    }
}

Наконец, не забудьте добавить разрешение RECEIVE_SMS в ваш манифест xml

<?xml version="1.0" encoding="utf-8"?>
<manifest ...>
    <uses-permission android:name="android.permission.RECEIVE_SMS"/>
    <application>
        ...
    </application>
</manifest>

Ответ 4

Также обратите внимание, что приложение Hangouts в настоящее время блокирует мой BroadcastReceiver от получения SMS-сообщений. Мне пришлось отключить функциональность SMS в приложении Hangouts (Настройки- > SMS- > Включить SMS-сообщение), прежде чем мой SMS BroadcastReceived начнет увольняться.

Изменить: Похоже, что некоторые приложения будут прерватьBroadcast() в намерении, которое не позволит другим приложениям получать намерение. Решение состоит в том, чтобы увеличить атрибут android:priority в теге intent-filter:

    <receiver android:name="com.company.application.SMSBroadcastReceiver" >
        <intent-filter android:priority="500">
            <action android:name="android.provider.Telephony.SMS_RECEIVED" />
        </intent-filter>
    </receiver>

Подробнее см. здесь: Включение поддержки SMS в Hangouts 2.0 нарушает BroadcastReceiver SMS_RECEIVED в моем приложении

Ответ 5

Пробовал ли вы emulator?

После развертывания вашего приложения в эмуляторе вы можете отправлять события, такие как SMS, через DDMS или через командную строку, подключившись к telnet:

telnet localhost <port_emulator>
send sms <incoming_tel_number> <sms_content>

port_emulator обычно 5554

Ответ 7

Android Messenger (клиент SMS) имеет функцию "Чат", которая передает сообщения по WiFi вместо SMS.

Если человек, с которым вы тестируете, также использует Messenger, вам нужно отключить эту функцию на одном или обоих ваших устройствах, в противном случае SMS-сообщение фактически не принимается:

Чтобы отключить функции чата:

  1. Открытые сообщения Сообщения Логотип Круглый.
  2. Нажмите Еще, а затем Настройки.
  3. Нажмите "Дополнительно", а затем выберите "Функции чата".
  4. Включите или отключите функцию чата.

https://support.google.com/messages/answer/7189714?hl=en