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, – они каким-то образом блокируют намерение получить доступ к моему приложению, они просто поглощают его полностью?

благодаря

Solutions Collecting From Web of "BroadcastReceiver + SMS_RECEIVED"

Вам также необходимо указать разрешение на использование в файле манифеста:

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

Следующие руководства помогут:

Реагировать на входящие SMS-сообщения
SMS-сообщения в Android

Еще одна вещь, о которой эти ответы не упомянуты, – вы должны потребовать разрешение 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> 

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

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

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

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

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

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

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

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

      auth xxxxxx 

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

  5. Теперь вы должны иметь возможность запускать все команды. Чтобы отправить сообщение 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> 

Также обратите внимание, что приложение 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 в моем приложении.

Вы пытались с эмулятором ?

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

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

Port_emulator обычно 5554

Вы должны прочитать эту статью о отправке и получении смс программно. http://mobiforge.com/developing/story/sms-messaging-android