Android O 创建后台Service

一、服务分类

1)运行类型

  • 前台服务:用户可以看到,如音乐播发器,在通知栏显示通知。优先级高,不会因系统内存不足被回收。
  • 后台服务:用户无法看到,如天气服务,日期更新

2)功能分类

  • 不可通信的服务:用startservice启动
  • 可通信的后台服务:用bindservice启动

二、服务的两种启动方法

(1)Startservice启动特点

  • 生命周期:startservice---oncreate---onstartcommand---running---ondestroty
  • 无法与调用者通信
  • 外部调用stopservice或者stopself,服务才会停止运行并销毁
  • 多次startservice不会调用oncreate,会调用onstartcommand可根据传入的intent进行实际的操作。比如音乐视频播放进度。

2bindservie特点

  • 生命周期bindservice---oncreate---onbind---running---unbind---ondestroty
  • Client可通过binderservice通信
  • 调用者销毁时,解除与service绑定,也可调用unbinder方法解除

     Service 的设计逻辑是,如果我们调用了 startService 就必须调用 stopService 或者 stopSelf 才能关闭服务,如果我们调用了 bindService 就必须调用 unbindService 才能关闭服务,start 与 stop,bind 与 unbind 必须一一对应。

三、Android O 启动后台服务

android O sdk26以后)开始,后台应用不允许通过startservice创建后台服务。

补充知识点:一个应用可以有一个或者多个进程,当任何一个进程变为被转换成前台可见进程的时候,APP都会被认作前台应用

(1)第一个问题:后台应用为什么不允许startservice启动服务

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

同时运行的应用越多,对系统造成的负担越大。 如果还有应用或服务在后台运行,这会对系统造成更大负担,进而可能导致用户体验下降;例如,音乐应用可能会突然关闭。为了降低发生这些问题的几率,Android 8.0 对应用在用户不与其直接交互时可以执行的操作施加了限制。

      应用程序在后台,通过startservice启动服务,报错:Not allowed to start service Intent XXX : app is in background uid UidRecord

通过源码查看,看看当前app进程是否处于后台非激活状态,如果是的话 ,就不会允许startservice

      模拟后台应用startservice启动服务Android O 后台startService限制简析-阿里云开发者社区 (aliyun.com)

      绑定服务不受此影响

(2)第二个问题:如果想在后台应用通过startservice启动服务,如何兼容?

  1. ContextCompat.startForegroundService(MainActivity.this, new Intent(MainActivity.this, MyService.class));//系统自动判断版本
  2. notification:在service.oncreate()生命周期方法里添加通知,设置通知栏消息(可隐藏),调用service.startForeground方法,设置为前台服务
    @Override
    public void onCreate() {
        setServiceForeground();
        super.onCreate();
    }

    /**
     * 设置前台服务
     */
    private void setServiceForeground() {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            String channelId = getPackageName();
            NotificationChannel notificationChannel = new NotificationChannel(
                    channelId, "name", NotificationManager.IMPORTANCE_LOW);
            notificationChannel.setSound(null, null);
            NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            manager.createNotificationChannel(notificationChannel);
            Notification.Builder builder = new Notification.Builder(this);
            builder.setTicker("");
            builder.setContentTitle("");
            builder.setContentText("");
            builder.setChannelId(channelId);
            builder.setSmallIcon(R.mipmap.ic_launcher);
            Notification notification = builder.build();
            startForeground(223, notification);
        } else {
            Notification.Builder builder = new Notification.Builder(this);
            builder.setSound(null);
            builder.setPriority(Notification.PRIORITY_LOW);
            builder.setTicker("");
            builder.setContentTitle("");
            builder.setContentText("");
            Notification notification = builder.build();
            startForeground(223, notification);
        }

        3.pessimision

<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />

参考:Android O 后台startService限制简析-阿里云开发者社区 (aliyun.com)

posted @ 2022-08-29 11:48  随易来了  阅读(947)  评论(0编辑  收藏  举报