【问题标题】:Oreo BroadcastReceiver SMS Received not workingOreo BroadcastReceiver SMS 收到不工作
【发布时间】:2018-02-14 14:28:30
【问题描述】:

我正在开发的一个应用程序允许用户允许该应用程序读取确认短信的内容以自行输入验证码。对于使用早于 Oreo (API 26) 的操作系统的所有设备,BroadcastReceiver 的实现可以正常工作并允许正确接收 SMS。通过这个实现,我的意思是把接收器对象放在 AndroidManifest 中。

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

但是,从 Oreo 开始,必须将 BroadcastReceivers 显式注册到适当的上下文中。我已经实现了如下:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            smsReceiver = new SmsReceiver();
            IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
            intentFilter.addAction(Telephony.Sms.Intents.DATA_SMS_RECEIVED_ACTION);
            this.registerReceiver(smsReceiver, intentFilter);
        }

此代码块在收到 Manifest.permission.READ_SMS 的权限后执行。 SmsReceiver 类扩展了 BroadcastReceiver 并覆盖了它的 onReceive() 方法。

在这里,我有几个问题:

  1. 我已经测试了这个实现,并在我的 SmsReceiver 中的 onReceive() 方法上设置了断点。当 SMS 到达时,应用程序永远不会进入 onReceive() 方法。为什么会这样?

  2. 我按照 Android 开发者网站上描述的方式实例化了我的 IntentFilter,即使用 ConnectivityManager.CONNECTIVITY_ACTION 操作。我知道 SmsReceiver 有效,因为 onReceive() 中的断点总是在接收者注册时命中。但是,该操作仅仅是 CONNECTIVITY_ACTION。 SMS_RECEIVED_ACTION 永远不会被接收者捕获。用这个动作实例化 IntentFilter 是绝对必要的,还是可以省略?

  3. 还有什么我遗漏的东西可能导致我的接收器无法接收到到达的 SMS?

【问题讨论】:

  • SMS_RECEIVEDon the broadcast whitelist,因此您使用 &lt;intent-filter&gt; 的原始方法应该仍然有效。
  • 我也这么认为,但不知何故,尽管该实现适用于所有以前的操作系统 :( 。一般来说,在 Oreo 上接收短信是否会破坏这一点?
  • “它不知何故没有,即使实现适用于所有以前的操作系统”——这很奇怪。我没有看到任何关于它不起作用的问题,我原以为如果它被打破了,现在有人会抱怨。您在什么设备上进行测试?
  • 到目前为止,我用过 HMD Global (Nokia 8) 和 Nexus,都是 Oreo。我还知道一个 OnePlus 3,也有 Oreo,它无法在 onReceive 中捕捉到短信。基本上所有 API 26 及以上的东西都不会捕捉到它,下面的所有东西都会捕捉到它。
  • 三星 S8 也是如此。这就是我所做的让它只工作ONCETurned SMS permission off and on after some seconds manually and it worked.你们中有人解决了这个问题吗?

标签: android broadcastreceiver android-broadcastreceiver android-8.0-oreo


【解决方案1】:

以前我请求 -Manifest.permission.READ_SMS 没有用,然后我将权限更改为 -Manifest.permission.RECEIVE_SMS 然后它开始在 oreo 中工作,我还在清单中指定了接收者我不知道不管有没有帮助,但这对我来说是一天

   public static void requestPermissionForReadSMS(Fragment fragment) {
    //        if (fragment.shouldShowRequestPermissionRationale(Manifest.permission.READ_SMS)) {
    //            Helpers.showRequestPermissionAlertDialog(fragment, fragment.getString(R.string.read_sms_permission), fragment.getString(R.string.permission_request));

    //        } else {
            fragment.requestPermissions(new String[]{Manifest.permission.RECEIVE_SMS},
                    Constants.READ_SMS_PERMISSION);
   // }

        }

【讨论】:

  • 我已经挣扎了好几个小时,并且使用了相同的 READ_SMS 权限。你拯救了我的一天。
【解决方案2】:

对我来说这个作品:

private int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10;
ActivityCompat.requestPermissions(this,new String[]{Manifest.permission.RECEIVE_SMS},
        MY_PERMISSIONS_REQUEST_SMS_RECEIVE);

在授予权限后,在您的主要活动中提及上述代码。 之后覆盖这个:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] 
            permissions, @NonNull int[] grantResults) {
            super.onRequestPermissionsResult(requestCode, permissions, grantResults);
            if (requestCode == MY_PERMISSIONS_REQUEST_SMS_RECEIVE) {
                Log.d("TAG", "My permission request sms received successfully");
            }
 }

仅此而已。所以现在不需要在几秒钟后手动关闭和打开短信权限。

【讨论】:

    【解决方案3】:

    @rohit sharma 给出的答案最初对我有用,但后来我也在诸如 oneplus、mi、oppo 和 vivo 等各种设备上测试了我的应用程序,发现

    1.在 vivo、oppo 和 mi(具有 miui)设备上,有一种称为自动启动的功能,默认情况下禁用,因此 SMS_RECIEVED_ACTION 不起作用(这里的工作是指在 sms_recieved 上启动应用程序或在后台运行任何服务)甚至被从最近给出的隐含禁令列表中列入白名单。

    2.在 oneplus 设备上,有电池优化功能,如果您的应用被列为电池优化(默认为是),那么 SMS_RECIEVED_ACTION 仅在您的应用处于前台或后台时有效,如果您的应用被杀死或手机重启后,广播接收器将无法工作。要使 SMS_RECIEVD_ACTION 正常工作,您必须从电池优化中删除该应用程序。有关这方面的更多信息,您可以关注此线程 here

    【讨论】:

    • 自动启动是个大问题,我们无能为力,除非用户启用,否则它也适用于推送通知。
    • 在 Android 9 中,有两个地方我关闭了我的应用程序的电池优化:在设置中---> 电池优化和优化电池使用。 Android 9 的变化很奇怪,谷歌应该认真修改。
    【解决方案4】:

    同时关闭和打开短信权限。几秒钟后,它起作用了。

    【讨论】:

    • 为什么要把别人的文字复制到你的答案中?
    • 对不起,我的目的不是在得到解决方案后复制另一个答案,我只是为这个问题添加解决方案。我很抱歉。我忘了提到会解决这个问题的人。
    【解决方案5】:

    只需添加

    android:permission="android.permission.BROADCAST_SMS"
    

    到 Manifest 中的接收者标签。

    如此理想的清单注册广播接收器:-

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

    更新:-

    现在SMS RETRIEVER api 被推荐给read SMS(否则play store 不会allow 在某些情况下发布apk)。所以请查看链接。

    【讨论】:

    • 您需要在 ... 部分中授予&lt;uses-permission android:name="android.permission.RECEIVE_SMS"/&gt; 权限 AND 添加android:permission="android.permission.BROADCAST_SMS" 权限作为 属性 - 在 Android 8 上使用我的 LG G6 测试
    【解决方案6】:

    对于 Oreo 及更高版本,请在您的 requestPermission 语句中特别添加 Manifest.permission.RECEIVE_SMS,无论您可能已经要求其他与短信相关的权限。在清单中列出相同的权限,但不列出将像您所做的那样动态注册的接收器(以静态和编程方式放置接收器会破坏目的)。

    requestPermissions(new String[]{Manifest.permission.READ_SMS, Manifest.permission.RECEIVE_SMS},
                        Constants.SMS_REQUEST_PERMISSION_CODE);
    

    这样做的原因是,从文档中引用,在 Android 8.0(API 级别 26)之前,如果应用在运行时请求权限并且该权限被授予,系统也会错误地授予该应用其余的属于同一个权限组并且在清单中注册的权限。

    对于面向 Android 8.0 的应用,此行为已得到纠正。该应用程序仅被授予其明确请求的权限。但是,一旦用户向应用授予权限,该权限组中的所有后续权限请求都会自动授予。

    最后一点是您需要确保在再次测试之前在您的模拟器/设备中撤销 SMS 权限的原因。

    【讨论】:

    • 在 Vivo mobile 中,手动检查自动启动权限,以便在应用程序关闭或终止时接收工作。 (在安卓 9 上测试)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多