必威体育Betway必威体育官网
当前位置:首页 > IT技术

Android O后台服务限制总结

时间:2019-08-26 12:40:00来源:IT技术作者:seo实验室小编阅读:83次「手机版」
 

android o

我们看Android O的新特性的时候会看到这样一个介绍:

多个 Android 应用和服务可以同时运行。 例如,用户可以在一个窗口中玩游戏,同时在另一个窗口中浏览网页,并使用第三个应用播放音乐。

同时运行的应用越多,对系统造成的负担越大。 如果还有应用或服务在后台运行,这会对系统造成更大负担,进而可能导致用户体验下降;例如,音乐应用可能会突然关闭。

为了降低发生这些问题的几率,Android 8.0 对应用在用户不与其直接交互时可以执行的操作施加了限制。

也就是系统不允许后台应用创建后台服务。

系统可以区分 前台 和 后台 应用。 (用于服务限制目的的后台定义与内存管理使用的定义不同;一个应用按照内存管理的定义可能处于后台,但按照能够启动服务的定义又处于前台。)如果满足以下任意条件,应用将被视为处于前台:

  • 具有可见 Activity(不管该 Activity 已启动还是已暂停)。
  • 具有前台服务。
  • 另一个前台应用已关联到该应用(不管是通过绑定到其中一个服务,还是通过使用其中一个内容提供程序)。 例如,如果另一个应用绑定到该应用的服务,那么该应用处于前台:

    • IME
    • 壁纸服务
    • 通知侦听器
    • 语音或文本服务

如果以上条件均不满足,应用将被视为处于后台。

绑定服务不受影响

这些规则不会对绑定服务产生任何影响。 如果您的应用定义了绑定服务,则不管应用是否处于前台,其他组件都可以绑定到该服务。

好了从官网复制的内容就到这里了,接下来说说处理办法,和现象效果。官网介绍的办法就是把我们的后台服务转变为前台服务,为我们提供了新的启动服务方法:startForegroundService,使用这个方法启动的服务必须在5秒内使用startForeground方法以显示新服务的用户可见通知,否则的话将抛出异常:context.startForegroundService() did not then call Service.startForeground()。

首先我们定义自己的service:

public class MyService extends Service {

    @Nullable
    @Override
    public IBinder onBind(intent intent) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("zhangdi","MyService onCreate");
        sendnotification();
    }

    @Override
    public int onStartcommand(Intent intent, int flags, int startId) {
        Log.i("zhangdi","MyService onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.i("zhangdi","MyService onDestroy");
        super.onDestroy();
    }

    private void sendNotification() {

        if (build.VERSION.SDK_INT>=26) {
            Intent intent = new Intent(this, StopActivity.class);
            //创建NotificationChannel并与NotificationManager、Notification关联,否则系统会
            //提示Failed to post notification on channel “null”
            String channelId = "channel1";
//            NotificationChannel channel = new NotificationChannel(channelId, "通知", NotificationManager.IMPORTANCE_LOW);
//            NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//            manager.createNotificationChannel(channel);
            Notification nf = new Notification.Builder(this, channelId)
                    .setcontenttitle("通知")
                    .setContentText("一个服务正在运行")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setContentIntent(PendingIntent.getActivities(this, 100, new Intent[]{intent}, PendingIntent.FLAG_CANCEL_CURRENT))
                    .build();
            startForeground(10, nf);
        }
    }
}

然后在MainActivity中启动这个服务:

public class MainActivity extends APPCompatActivity {

    @Override
    protected void onCreate(Bundle savedinstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (Build.VERSION.SDK_INT>=26) {
            startForegroundService(new Intent(this, MyService.class));
        }

        //startService(new Intent(this, MyService.class));
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.i("zhangdi","activity onStop");
    }

    @Override
    protected void onDestroy() {
        Log.i("zhangdi","activity onDestroy");
        super.onDestroy();
    }
}

运行效果图:

这个效果图大家都看懂了吧?就是启动应用在MainActivity中启动服务,然后退出应用,我们会看到通知栏会出现一个通知提醒我们应用还有一个服务在运行,而且我们点击这个通知还能跳到系统的页面中去强制停止服务,感觉是不是有点吊吊的。但是,是不是哪有点不对?看上面我在service中写的代码,我明明自己定义了一个notification啊,现在怎么弹出来的是系统的?也没有报错了啊,怎么肥事?好吧,细心的朋友应该发现了在我们应用启动的时候快速的弹出了一个系统吐司,也没看清是什么,但是不要紧我们再重新运行,截图看看到底提示了什么?

系统吐司截图:

它提示的是:failed to post notification on channel "null",好吧系统在这里告诉我们为什么我们的通知没能发送成功了,是缺少channel值,可是channel是什么呢?我也不知道,所以我去百度查了,查的结果是:这个channel指的是NotificationChannel,官网对它的解释是:A representation of settings that apply to a collection of similarly themed notifications.百度翻译为:应用于相似主题集合的设置的表示形式。是不是没太看懂?我又向下看了看类里提供的方法,是一些为notification设置声音、震动、提示灯的方法,那我是不是可以把它理解为是一个细化notification设置系统提示形式的类。其实我在上边service的代码里也设置了这个属性,只是注释掉了,为了看看没有的效果,现在只需要解开注释就能看到正确的效果了。

最后注意一下NotificationChannel的设置只是在Android8.0才开始的,低版本里并没有这个设置,还是我们原来notification怎么使用就怎么使用。

还有个问题我在写demo的时候也使用了原来的startService方法来启动服务,我发现,这个方法也还是可以启动服务的,如果我们没有把它转为前台服务,在我们的应用退出后,这个后台服务还会运行一段时间,之后会被系统停止,但是不会抛出异常:Context.startForegroundService() did not then call Service.startForeground(),也就是说系统不会告诉你,你的服务已经被我停止了,你的一些后台操作也进行不下去了。

我总结的就这些了,有哪不对的地方,希望看的朋友能够严厉指出,毕竟谁也不希望自己一直错下去不是。

相关阅读

TeamViewer 13破解版|TeamViewer 13无商业限制破解版

下载来源处:TeamViewer 13无商业限制破解版TeamViewer 13是一款功能强大、使用方便、并且非常知名的远程桌面控制工具软件,同时也是

网络平台推有偿抢票服务:变相黄牛行为该被叫停

近日,携程、去哪儿、高铁等多个互联网平台相继推出偿抢票服务,简而言之就是用户多花钱就能增加抢票成功的概率,但究竟概率提高多少,几

每日话题:街旁网即将关闭服务器 LBS签到应用“死亡”?

A5站长网(www.admin5.com)1月23日消息,近日有消息称国内最早的签到应用“街旁”要关闭服务器,但是具体关闭时间尚不清楚

滴滴出行金融服务上线,所有服务均拥有合规牌照

A5创业网(公众号:iadmin5)1月3日报道,滴滴出行于昨日宣布正式推出金融服务。金融服务频道也已经在滴滴出行的APP端正式上线,这个页面已

Android Drawable 详解

Android Drawable 详解 @(Technical)[Android, Drawable, StateListDrawable, LayerDrawable, AnimationDrawable] 1、Drawa

分享到:

栏目导航

推荐阅读

热门阅读