在android Oreo中对传入的SMS运行服务

sza*_*i20 6 android broadcastreceiver receiver android-jobscheduler

我正在开发一个应用程序,只要收到短信,就需要运行一些代码(网络).
在API 25和更低版本中它很好,我receiver在Manifest文件中注册了一个隐式文件,并在扩展的指定类中启动我的服务BroadcastReceiver.但是在API 26中,您无法注册android.provider.Telephony.SMS_RECEIVED,receiver因为它不起作用.

来自Android文档:

注意:如果您的应用程序的目标是API级别26或更高级别,则不能使用清单来声明隐式广播的接收者(特定于您的应用程序的广播),除了一些免于该限制的隐式广播.在大多数情况下,您可以使用预定作业.

在媒体上看过几篇像这样的文章.有喜欢的解决方案,JobScheduler或者Explicit Receiver,但是第一个被用于网络状态的变化,我无法找到一个方法来触发任务SMS_RECEIVED的事件,第二个是有效的,直到你的活动启动并运行.

由于我的应用程序的性质,我需要监听传入的短信,无论应用程序是否正在运行.如何在API 26+中做到这一点?

编辑

也许Android网站上的JobInfoBuilder doc中代码可以提供帮助.它监视设备上照片的变化,并在更改时启动作业.但是我找不到合适的Uri用短信做同样的事情(甚至不确定是否有可能通过短信监听短信ContentObserver)

sza*_*i20 4

由于有很多方法可以在android O中完成这项工作,我发布这个答案并提到我解决问题的方法.显然,问题是指一般问题而不是SMS_RECEIVED接收器本身.

我启动一个前台服务,在那里我注册一个动态或显式接收器来监听传入的呼叫(例如):

MainActivity.java:

String action = "START"
final Intent intent = new Intent(this, CallMonitorService.class);
intent.setAction(action);
startService(intent);
Run Code Online (Sandbox Code Playgroud)

CallMonitorService.javas 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);
Run Code Online (Sandbox Code Playgroud)

然后在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);
    }
Run Code Online (Sandbox Code Playgroud)

最后:

@Override
public void onDestroy() {
    super.onDestroy();
    unregisterReceiver(callExplicitReceiver);
}
Run Code Online (Sandbox Code Playgroud)

我认为这是一个很好的方法,因为用户因为不可拒绝的通知而被通知正在运行的服务,这就是android Oreo想要的,但是通过应用程序中的按钮用户可以停止服务和监视接收器作为破坏的直接结果服务(我清除了那部分代码).