【问题标题】:SMS Broadcast Receiver in Oreo+Oreo+ 中的 SMS 广播接收器
【发布时间】:2019-09-04 16:06:45
【问题描述】:

我正在尝试拦截发送到我的设备的 SMS 消息。大约一年前,我编写了一个应用程序来执行此操作,但我发现它不再捕获消息(即使代码未更改)。

我认为这与权限无关。我尝试在 SDK 23(需要运行时权限)和 SDK 22(无运行时权限)下编译。 (在23的情况下,我验证了RECEIVE_SMS权限是成功授予的)。

关于这个问题的大多数问题/答案都很老了。恕我直言,答案似乎并不开明,例如添加 BROADCAST_SMS 权限,调用原生代码等

我的方法是实现广播接收器。以下代码除外。

广播接收器

//  SmsRecv.java - SMS Receiver    

package com.ramrod.SmsReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class SmsRecv extends BroadcastReceiver {

    //@ Handler for received sms messages
    @Override
    public void onReceive(
        Context ctx,
        Intent intent)
    {    
        // NEVER REACHED!
        Main.toast( "SMS RECEIVED." );
        // PROCESS MESSAGE HERE...    
    }

清单

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.ramrod.SmsReceiver"
      android:versionCode="100"
      android:versionName="1.00">

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

    <application
      android:icon="@drawable/icon"
      android:label="SmsReceiver"
      android:theme="@android:style/Theme"
    >
      <activity android:name=".Main"
            android:label="SmsReceiver"
          >
          <intent-filter>
              <action android:name="android.intent.action.MAIN" />
              <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
      </activity>

      <receiver android:name=".SmsRecv"
          android:exported="true"
          android:enabled="true"
          >
          <intent-filter android:priority="999999" >
              <action android:name="android.provider.Telephony.SMS_RECEIVED" />
          </intent-filter>
      </receiver>

    </application>
</manifest>

BUILD.GRADLE

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "27.0.3"

    defaultConfig {
        applicationId "com.ramrod.SmsReceiver"
        minSdkVersion 23
        targetSdkVersion 23
    }
    ...

在运行 Oreo V8.0.0 的三星 S7 上测试。我通过从另一部手机发送短信对此进行了测试。这些被正确接收但从未触发 SmsRecv()。

在阅读过程中,我发现现在 SMS 广播接收器将不再工作,除非它是设备上的默认 SMS 应用程序(嗯?)。

非常感谢任何建议。

【问题讨论】:

  • “我验证了权限 RECEIVE_SMS 已成功授予” – 您是如何验证的,确切地说?您在哪个特定的 Android 版本上进行了测试? “我遇到了这样的想法,即现在 SMS 广播接收器将不再工作,除非它是设备上的默认 SMS 应用程序” – 不,只要你有权限,并且适当的接收器设置,你仍然可以获得@987654324 @广播,除非有任何制造商特定的限制。 Main.toast( "SMS RECEIVED." ); 看起来很可疑。为什么不直接在 onReceive() 中使用 Toast,或者更好的是,记录打印或断点?
  • 在我的 onRequestPermissionsResult() 方法中验证了权限。还检查了 Settings->Apps->SmsReceiver->Permissions。我在 Oreo V8.0.0 上测试过。
  • Main.toast 只是 Toast 的一个便利包装器(它可以工作)。我确实设置了一个从未达到的断点。在一次尝试中,我确实尝试了 Log.i() 但没有任何输出。
  • 嗯,这个包装器需要一个有效的Context,如果它来自Activity 中的一些静态成员,它就相当脆弱。 Anyhoo,从奥利奥开始,您必须明确请求您使用的每个单独的权限;即,您必须在运行时显式请求RECEIVE_SMS 权限才能传递该广播。例如,仅请求 READ_SMS 不再有效。您是否特别要求RECEIVE_SMS?另外,您是在模拟器还是物理设备上进行测试?如果是后者,是哪家厂商?
  • 哦,我刚刚注意到您已将设备型号编辑到问题中。我有一个运行 8.0 的 S7,并且可以验证您在接收 SMS 时应该没有问题,只要您已正确设置所有内容。

标签: android broadcastreceiver sms


【解决方案1】:

我终于知道出了什么问题。显然,Android 版本的 Oreo+ 不再提供 implicit 广播*(即清单文件 中指定的那些)。您现在必须在代码中显式注册您的接收器(即使用 registerReceiver())。

(*注意:Mike M 正确地指出,根据 Android 文档,接收到的 SMS 广播不受此限制,但实际上对我来说并非如此)。

所以我为完成这项工作所做的是:

  • 从清单中完全删除
  • 在我的活动 onCreate() 中创建我的接收器和一个 intentFilter 的实例;

        MyReceiver = new SmsRecv();
        MyFilter   = new IntentFilter(Telephony.Sms.Intents.SMS_RECEIVED_ACTION );  
    
  • 在我的 Activity 的 onResume() 中注册接收器。

        i = registerReceiver( MyReceiver, MyFilter);  
    
  • 在我的 Activity 的 onPause() 中取消注册接收器。 (这是防止泄漏所必需的)。

        unregisterReceiver( MyReceiver );
    

通过这些更改,应用程序运行良好。

【讨论】:

  • 抱歉,这对于SMS_RECEIVED 是不正确的。它在不受这些限制的广播列表中:developer.android.com/guide/components/broadcast-exceptions。我在聊天室中留下了一个完整示例的链接,在清单中注册了接收器,我保证它可以在奥利奥上运行(除非制造商特定的限制)。此外,隐式广播与您注册接收器的位置没有任何关系。这是关于广播Intent是如何构造的。
  • 嗯,我不知道。我只能说 registerReceiver 方法对我来说非常有效,但清单 方法却不行。我明白你的观点,SMS_RECEIVED 应该是豁免的,但这在实践中并不适用(对我来说)。
  • 感谢您的示例代码,但我现在有了一个可行的解决方案,而且我已经花了太多时间把头撞到墙上了 :)
  • @DontPanic,嗨,我也在寻找类似的解决方案。但是,当您最小化应用程序时,您可以接收广播吗?因为我看到您在最小化应用程序后立即取消注册接收器。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多