运行 在 android Oreo 中接收短信服务
Run service on incoming SMS in android Oreo
我正在开发一个应用程序,每当收到短信时都需要 运行 一些代码(网络)。
在 API 25 及更低版本中没问题,我在 Manifest 文件中注册了一个隐式 receiver
并在扩展 BroadcastReceiver
的指定 class 中启动我的服务。在 API 26 中,您不能在 receiver
中注册 android.provider.Telephony.SMS_RECEIVED
,因为它不起作用。
来自 Android 文档:
Note: If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts that are exempted from that restriction. In most cases, you can use scheduled jobs instead.
我读过几篇文章,例如 this one on medium。有 JobScheduler
或 Explicit Receiver
等解决方案,但第一个用于更改网络状态,我找不到在 SMS_RECEIVED
事件和第二个事件上触发作业的方法在您的 activity 启动并 运行ning 之前有效。
由于我的应用程序的性质,我需要侦听传入的 SMS,无论该应用程序是否 运行ning。如何在 API 26+ 中做到这一点?
编辑
也许 code in JobInfoBuilder doc on android website 可以提供帮助。它监视设备上照片的变化并在变化时开始工作。但是我找不到合适的 Uri 来对 SMS 做同样的事情(甚至不确定是否可以通过 ContentObserver
监控 SMS)
我认为目前您是安全的,因为 SMS_RECEIVED_ACTION
存在于当前豁免的隐式广播 list 中。此外,在收到系统广播后,您可以启动前台服务或安排工作(在您的情况下执行网络操作)。此外,我也在使用相同的操作,经测试它似乎工作正常。
由于androidO中有很多方法可以完成这项工作,所以我post这个答案并提到我解决问题的方法。显然,问题是指一般问题,而不是 SMS_RECEIVED
接收器本身。
我启动了一个前台服务,并在其中注册了一个动态或显式接收器来监听来电(例如):
在MainActivity.java
中:
String action = "START"
final Intent intent = new Intent(this, CallMonitorService.class);
intent.setAction(action);
startService(intent);
在 CallMonitorService.java
s onCreate()
方法中,我将 BroadcastReceiver callExplicitReceiver
作为字段:
final IntentFilter intentFilter = new IntentFilter();
intentFilter.setPriority(2147483647);
intentFilter.addAction("android.intent.action.PHONE_STATE");
this.callExplicitReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
// do the stuff here
}
}
};
registerReceiver(callExplicitReceiver, intentFilter);
然后在 onStartCommand()
:
if (intent.getAction().equals("START")) {
Intent callServiceNotificationIntent = new Intent(this, MainActivity.class);
callServiceNotificationIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent
.getActivity(this, CALL_SERVICE_REQUEST_CODE,
callServiceNotificationIntent, CALL_SERVICE_FLAG);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(CALL_NOTIFICATION_CONTENT_TITLE)
.setTicker(CALL_NOTIFICATION_TICKER)
.setContentText(CALL_NOTIFICATION_CONTENT_TEXT)
.setSmallIcon(R.drawable.ic_info_outline_black_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(CALL_NOTIFICATION_ID, notification);
}
最后:
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(callExplicitReceiver);
}
我认为这是一个很好的方法,因为由于不可关闭的通知,用户会收到 运行 服务的通知,而这正是 android Oreo
想要的,但是通过一个按钮在应用程序中,用户可以停止服务和监控接收器作为破坏服务的直接结果(我清除了那部分代码)。
我正在开发一个应用程序,每当收到短信时都需要 运行 一些代码(网络)。
在 API 25 及更低版本中没问题,我在 Manifest 文件中注册了一个隐式 receiver
并在扩展 BroadcastReceiver
的指定 class 中启动我的服务。在 API 26 中,您不能在 receiver
中注册 android.provider.Telephony.SMS_RECEIVED
,因为它不起作用。
来自 Android 文档:
Note: If your app targets API level 26 or higher, you cannot use the manifest to declare a receiver for implicit broadcasts (broadcasts that do not target your app specifically), except for a few implicit broadcasts that are exempted from that restriction. In most cases, you can use scheduled jobs instead.
我读过几篇文章,例如 this one on medium。有 JobScheduler
或 Explicit Receiver
等解决方案,但第一个用于更改网络状态,我找不到在 SMS_RECEIVED
事件和第二个事件上触发作业的方法在您的 activity 启动并 运行ning 之前有效。
由于我的应用程序的性质,我需要侦听传入的 SMS,无论该应用程序是否 运行ning。如何在 API 26+ 中做到这一点?
编辑
也许 code in JobInfoBuilder doc on android website 可以提供帮助。它监视设备上照片的变化并在变化时开始工作。但是我找不到合适的 Uri 来对 SMS 做同样的事情(甚至不确定是否可以通过 ContentObserver
监控 SMS)
我认为目前您是安全的,因为 SMS_RECEIVED_ACTION
存在于当前豁免的隐式广播 list 中。此外,在收到系统广播后,您可以启动前台服务或安排工作(在您的情况下执行网络操作)。此外,我也在使用相同的操作,经测试它似乎工作正常。
由于androidO中有很多方法可以完成这项工作,所以我post这个答案并提到我解决问题的方法。显然,问题是指一般问题,而不是 SMS_RECEIVED
接收器本身。
我启动了一个前台服务,并在其中注册了一个动态或显式接收器来监听来电(例如):
在MainActivity.java
中:
String action = "START"
final Intent intent = new Intent(this, CallMonitorService.class);
intent.setAction(action);
startService(intent);
在 CallMonitorService.java
s onCreate()
方法中,我将 BroadcastReceiver callExplicitReceiver
作为字段:
final IntentFilter intentFilter = new IntentFilter();
intentFilter.setPriority(2147483647);
intentFilter.addAction("android.intent.action.PHONE_STATE");
this.callExplicitReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction().equals(TelephonyManager.ACTION_PHONE_STATE_CHANGED)) {
// do the stuff here
}
}
};
registerReceiver(callExplicitReceiver, intentFilter);
然后在 onStartCommand()
:
if (intent.getAction().equals("START")) {
Intent callServiceNotificationIntent = new Intent(this, MainActivity.class);
callServiceNotificationIntent.setFlags(
Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
PendingIntent pendingIntent = PendingIntent
.getActivity(this, CALL_SERVICE_REQUEST_CODE,
callServiceNotificationIntent, CALL_SERVICE_FLAG);
Notification notification = new NotificationCompat.Builder(this)
.setContentTitle(CALL_NOTIFICATION_CONTENT_TITLE)
.setTicker(CALL_NOTIFICATION_TICKER)
.setContentText(CALL_NOTIFICATION_CONTENT_TEXT)
.setSmallIcon(R.drawable.ic_info_outline_black_24dp)
.setContentIntent(pendingIntent)
.setOngoing(true)
.build();
startForeground(CALL_NOTIFICATION_ID, notification);
}
最后:
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(callExplicitReceiver);
}
我认为这是一个很好的方法,因为由于不可关闭的通知,用户会收到 运行 服务的通知,而这正是 android Oreo
想要的,但是通过一个按钮在应用程序中,用户可以停止服务和监控接收器作为破坏服务的直接结果(我清除了那部分代码)。