BroadcastReceiver SMS_Received在新设备上不起作用

14

在查阅了多个资源和问题后,我仍然面临着检测传入短信的问题。

下面的代码显示了基本内容:

广播接收器类,在onReceive中显示toast

public class IncomingSms extends BroadcastReceiver {
    public void onReceive(Context context, Intent intent) {
        Toast.makeText(context, "something received", Toast.LENGTH_SHORT).show();
    }
}

具有注册接收器和权限的简单清单文件

<application
    <receiver 
        android:name=".IncomingSms"
        android:permission="android.permission.BROADCAST_SMS"
        android:exported="true">

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

</application>

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

上面的代码声明并注册了接收器,并具有适当的权限。此外,优先级设置为MAX_INT或2147483647。
我的设备是Nexus 6P,安装了默认的Messenger应用程序(我还尝试过Hangouts)。该应用程序仍然不显示我的toast。在旧的三星设备上尝试后,toast可以正常打印。
优先级问题
我在6P上安装了一个名为Manifest Viewer的应用程序,它允许我查看设备上安装的应用程序的manifest.xml。我检查了Messenger和Hangouts的清单,针对SMS标签的接收器,并发现它们都指定了优先级2147483647。这似乎是这两个信使应用程序最大化了优先级,并且一旦它们消耗了消息,它们就不允许其他应用程序介入。请注意,这些是原始的Google应用程序,而不是第三方应用程序。
此时,我非常困惑:
他们为什么要这样做?
如何绕过它?
2个回答

40

问题已经解决。

问题不在于优先级,而是因为我的手机是Nexus 6P(又名API 23)。

仅通过manifest.xml文件提供权限是不够的,我还需要添加运行时权限请求代码。请参见Android文档中关于运行时权限的说明

将以下代码添加到您的MainActivity中:

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

在MainActivity类的顶部定义如下内容:

private int MY_PERMISSIONS_REQUEST_SMS_RECEIVE = 10;

同时添加此覆盖:

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == MY_PERMISSIONS_REQUEST_SMS_RECEIVE) {
        // YES!!
        Log.i("TAG", "MY_PERMISSIONS_REQUEST_SMS_RECEIVE --> YES");
    }
}

也拥有Nexus 6P。谢谢,这正是我所需要的!谢谢。 - RJB
2
谢谢,好的帖子,非常有帮助。虽然我认为问题更多地与API级别23有关,而不是Nexus设备。也许你应该注意最后一个override并不是真正需要的,只是为了像我这样的代码复制僵尸存在 ;-) - anhoppe
@anhoppe 是的,如果您正在运行API版本>= 23,则他们应该提前通知您需要执行此操作。 - committedandroider
2
这解决了我的问题 - 我只请求了READ_SMS权限,但没有请求RECEIVE_SMS权限。尽管我遵循了Android Authority上的教程! - Magnus
你需要检查grantResults数组,以确定你的应用程序是否真正收到了权限。 - MrObjectOriented
显示剩余2条评论

2
请确保您的实现与此类似。

SMS接收器类

    public class SmsReceiver extends BroadcastReceiver {

        private static final String SMS_RECEIVED = "android.provider.Telephony.SMS_RECEIVED";

        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(SMS_RECEIVED)) {
                Bundle bundle = intent.getExtras();
                if (bundle != null) {
                    // get sms objects
                    Object[] pdus = (Object[]) bundle.get("pdus");
                    if (pdus.length == 0) {
                        return;
                    }
                    // large message might be broken into many
                    SmsMessage[] messages = new SmsMessage[pdus.length];
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < pdus.length; i++) {
                        messages[i] = SmsMessage.createFromPdu((byte[]) pdus[i]);
                        sb.append(messages[i].getMessageBody());
                    }
                    String sender = messages[0].getOriginatingAddress();
                    String message = sb.toString();
                    Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
                    // prevent any other broadcast receivers from receiving broadcast
                    // abortBroadcast();
                }
            }
        }
    }

Manifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.smsreceiver"
    android:versionCode="1"
    android:versionName="1.0">
    <uses-sdk android:minSdkVersion="4" />
    <uses-permission android:name="android.permission.RECEIVE_SMS" />
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity
           // your activity
        </activity>
        <receiver android:name="com.example.smsreceiver.SmsReceiver" android:enabled="true">
            <intent-filter android:priority="2147483647">
                <action android:name="android.provider.Telephony.SMS_RECEIVED" />
            </intent-filter>
        </receiver>
    </application>
</manifest>

请确保使用您自己定义的包。此处定义的包是虚拟的。


我想先确保在“onReceive”中检测到任何内容,然后再深入进行更详细的实现。我尝试了你的片段只是为了确认,但仍然没有输出。我仍然相信这与Nexus股票应用程序设置的优先级有关。 - Khorkhe
如果需要的话,可以查看这个教程,它可能会对你有所帮助。http://androidexample.com/Incomming_SMS_Broadcast_Receiver_-_Android_Example/index.php?view=article_discription&aid=62&aaid=87 - Adnan Amjad
只是为了检查。从设置中强制关闭短信应用程序,然后测试您的应用程序。 - Adnan Amjad
问题不在于广播寄存器的实现或在清单中注册它。您需要像顶部答案建议的那样要求其他应用程序权限。 - committedandroider

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接