在android Oreo

时间:2017-10-01 11:10:49

标签: android broadcastreceiver receiver android-jobscheduler

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

来自Android文档:

  

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

我读过几篇文章,如this one on medium。有JobSchedulerExplicit Receiver等解决方案,但是第一个用于网络状态的更改,我找不到在SMS_RECEIVED事件和第二个事件上触发作业的方法在您的活动启动并运行之前有效。

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

修改

也许code in JobInfoBuilder doc on android website可以提供帮助。它监视设备上照片的变化,并在更改时启动作业。但是我找不到合适的Uri来做同样的短信(甚至不确定是否可以通过ContentObserver来监听短信)

2 个答案:

答案 0 :(得分:4)

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

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

MainActivity.java

String action = "START"
final Intent intent = new Intent(this, CallMonitorService.class);
intent.setAction(action);
startService(intent);

CallMonitorService.java 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想要的,但是通过app中的按钮用户可以停止服务和监视接收器是破坏服务的直接结果(我清除了那部分代码)。

答案 1 :(得分:3)

我认为现在你很安全,因为SMS_RECEIVED_ACTION存在于当前获得豁免的隐含广播list中。此外,在收到系统广播后,您可以启动前台服务或安排作业(在您的情况下执行网络操作)。此外,我也使用相同的操作,并在测试它似乎工作正常。