我正在处理的应用允许用户允许应用读取确认短信的内容以自行输入验证码。对于使用早于Oreo(API 26)的OS的所有设备,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()方法。
在这里,我有几个问题:
我测试了这个实现,并在我的SmsReceiver中的onReceive()方法上设置了断点。当SMS到达时,应用程序永远不会进入onReceive()方法。为什么会这样?
我按照Android Developer网站上描述的方式实例化我的IntentFilter,即使用ConnectivityManager.CONNECTIVITY_ACTION操作。我知道SmsReceiver有效,因为onReceive()中的断点总是在接收器注册时被击中。但是,该操作仅仅是CONNECTIVITY_ACTION。 SMS_RECEIVED_ACTION永远不会被接收器捕获。是否绝对有必要使用此操作实例化IntentFilter,还是可以将其删除?
我还缺少其他可能导致接收方无法接收到达短信的内容吗?
答案 0 :(得分:11)
之前我正在请求-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);
// }
}
答案 1 :(得分:5)
对我来说这有效:
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");
}
}
仅此而已。因此,现在无需在几秒钟后手动打开和关闭SMS权限。
答案 2 :(得分:3)
在手动几秒钟之后关闭并打开短信权限并且它有效。
答案 3 :(得分:2)
只需添加
android:permission="android.permission.BROADCAST_SMS"
到清单中的接收者标签。
所以理想的清单注册广播接收器:-
<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>
答案 4 :(得分:2)
@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
答案 5 :(得分:1)
对于Oreo或更高版本,无论您是否已经在寻求与SMS相关的其他权限,请在您的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权限,原因。
答案 6 :(得分:0)
在MainActivity或您要放置权限的地方
ActivityCompat.requestPermissions(MainActivity.this,
new String[] {Manifest.permission.READ_SMS,Manifest.permission.SEND_SMS,Manifest.permission.RECEIVE_SMS}, 1);
在清单中,您希望获得用户的权限
<uses-permission-sdk-23 android:name="android.permission.RECEIVE_SMS" />
<uses-permission-sdk-23 android:name="android.permission.READ_SMS" />
<uses-permission-sdk-23 android:name="android.permission.SEND_SMS" />
<uses-permission-sdk-23 android:name="android.permission.WRITE_SMS" />
将接收器放入清单
<receiver
android:name=".Controllers.SmsData.SmsListener"
android:enabled="true"
android:exported="true"
android:permission="android.permission.BROADCAST_SMS">
<intent-filter android:priority="6000">
<action android:name="android.provider.Telephony.SMS_RECEIVED" />
</intent-filter>
</receiver>