BroadcastReceiver + SMS_RECEIVED

时间:2009-12-29 05:28:02

标签: android

我希望我的应用能够捕获传入的短信。这方面有一些例子。看起来我们只需要这样做:

// 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.");
        ....
    }
}

这是对的吗?我正在给手机发送一些短信,但日志声明永远不会被打印出来。我确实在手机上安装了一些其他短信应用程序,当收到短信时显示弹出窗口 - 他们是否以某种方式阻止意图传递给我的应用程序,他们只是完全消耗它?

由于

7 个答案:

答案 0 :(得分:30)

您还需要在清单文件中指定使用权限:

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

以下教程应该有所帮助:

React on incoming SMS
SMS messaging in Android

答案 1 :(得分:9)

这些答案还没有提到的另一件事 - 您应该要求权限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>

答案 2 :(得分:9)

路上有一些陷阱。您可以在stackoverflow上找到所有需要的信息。为方便起见,我已收集了此答案中的所有信息。

需要注意的事项

  1. 我假设android kitkat及以上。
  2. 发送短信的意图是"android.provider.Telephony.SMS_RECEIVED"
  3. 您可以更改意图过滤器的优先级,但这不是必需的。
  4. 您需要在manifest xml中使用此权限"android.permission.RECEIVE_SMS"才能接收短信。在android 6及更高版本中,您还需要在运行时请求权限。
  5. 您无需在intent过滤器中设置MIME类型。如果没有设置MIME类型,Intent过滤器应仅传递空数据,但幸运的是,它仍然可以在没有MIME的情况下工作。
  6. adb shell am broadcast无效。使用telnet连接到模拟器来测试短信接收。
  7. 长短信息被分成小的短信块。我们需要将它们连接起来。
  8. 如何将短信发送到模拟器

    最重要的是有可能向设备发送虚假短信,因此我们可以测试代码。

    为此,我们将使用虚拟设备和telnet连接。

    1. 在android studio中创建虚拟设备并运行模拟器
    2. 查看模拟器窗口中的标题栏。设备名称和端口号。我们需要在接下来的步骤中知道这个端口号。
    3. 现在使用telnet连接到模拟器标题栏中显示的端口号

       $ telnet localhost 5554
      
    4. 如果您看到:Android Console: Authentication required,则需要使用此命令验证连接:

       auth xxxxxx
      

      使用从xxxxxx文件中读取的令牌替换上面的~/.emulator_console_auth_token

    5. 现在您应该能够运行所有命令。要发送短信,请输入以下命令:

       sms send 555 "This is a message"
      

      您可以使用发件人电话号码和自己的信息替换555.

    6. 如何收听SMS_RECEIVED广播

      要获取广播,您需要注册BroadcastReceiver对象。您可以在manifest.xml OR 中调用registerReceiver函数执行此操作。我会告诉你后者,因为它更容易推理,而且更灵活。

      将广播接收器与主要活动连接

      数据流是一种方式。从广播接收器到主要活动。因此,让他们说话的最简单方法是使用功能界面。活动将实现这样的功能,广播接收器将把活动实例作为构造函数中的参数传递。

      文件SmsHandler.java:

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

      实施广播接收器

      广播接收器将获得回调意图。我们将使用函数Telephony.Sms.Intents.getMessagesFromIntent(intent)来获取短信。注意构造函数中的SmsHandler参数。这将是我们发送收到的短信的活动。

      文件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>
      

答案 3 :(得分:3)

另请注意,环聊应用程序目前会阻止我的BroadcastReceiver接收短信。在我的SMS BroadcastReceived开始被解雇之前,我不得不在环聊应用中禁用短信功能(设置 - &gt;短信 - &gt;开启短信)。

编辑:似乎某些应用程序将在意图上abortBroadcast(),这将阻止其他应用程序接收意图。解决方案是增加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>

在此处查看更多详情:Enabling SMS support in Hangouts 2.0 breaks the BroadcastReceiver of SMS_RECEIVED in my app

答案 4 :(得分:2)

您是否尝试使用emulator

在模拟器中部署应用程序后,您可以通过DDMS或通过连接telnet通过命令行发送SMS等事件:

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

port_emulator通常是5554

答案 5 :(得分:1)

您应该以编程方式阅读本文关于发送和接收短信的内容。 http://mobiforge.com/developing/story/sms-messaging-android

答案 6 :(得分:0)

Android Messenger( SMS 客户端)具有“聊天”功能,可通过WiFi而不是SMS传输消息。

如果要测试的人也使用Messenger,则需要在一个或两个设备上禁用此功能,否则实际上不会收到SMS消息:

  

要关闭聊天功能,请执行以下操作:

     
      
  1. 打开消息消息徽标回合。
  2.   
  3. 点击“更多”,然后点击“设置”。
  4.   
  5. 点击“高级”,然后点击“聊天”功能。
  6.   
  7. 打开或关闭启用聊天功能。
  8.   

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