android 8.0 service

参考资料:

https://blog.csdn.net/o279642707/article/details/82352431

https://blog.csdn.net/o279642707/article/details/82352431

https://www.cnblogs.com/Jhon-Mr/p/7699899.html

https://developer.android.google.cn/guide/topics/ui/notifiers/notifications#ManageChannels

https://www.cnblogs.com/guanxinjing/p/9861476.html

 

1.来源

      1.在开始之前,先了解一下前后台服务的区别:

      这里借用一张图:

      

类别区别应用
前台服务会在通知一栏显示 ONGOING 的 Notification, 当服务被终止的时候,通知一栏的 Notification 也会消失,这样对于用户有一定的通知作用。音乐播放
后台服务默认的服务即为后台服务,即不会在通知一栏显示 ONGOING 的 Notification。 当服务被终止的时候,用户是看不到效果的。监控进程,可以是天气监控,系统状态监控等等

 

       2.谷歌在andorid 8.0提出了一个行为变更:当您的应用进入已缓存状态时,如果没有活动的组件,系统将解除应用具有的所有唤醒锁。此外,为提高设备性能,系统会限制未在前台运行的应用的某些行为。

       具体而言: 
       * 现在,在后台运行的应用对后台服务的访问受到限制。 
       * 应用无法使用其清单注册大部分隐式广播(即,并非专门针对此应用的广播)。 
       默认情况下,这些限制仅适用于针对 O 的应用。不过,用户可以从 Settings 屏幕为任意应用启用这些限制,即使应用并不是以 O 为目标平台。 

       对于我这样的api coder而言,最实际的是以下部分
       Android 8.0 还对特定函数做出了以下变更: 
      * 如果针对 Android 8.0 的应用尝试在不允许其创建后台服务的情况下使用 startService() 函数,则该函数将引发一个 IllegalStateException。 
      * 新的 Context.startForegroundService() 函数将启动一个前台服务。现在,即使应用在后台运行,系统也允许其调用 Context.startForegroundService()。不过,应用必须在创建服务后的五秒内调用该服务的 startForeground() 函数。 

      3.除了前台服务的限制,谷歌还设置一个叫做通知渠道的限制。

      顾名思义:通知渠道就是通知的方法。在8.0(api26)之后,所有的通知必须通过自定义的通知渠道显示。用户可以基于这个基础对所有的通知进行更细化的控制。

       因为前台服务需要显示通知,所以在启动服务的同时,需要去创建(如果没有)通知渠道,如果没有通知渠道,那么服务将无法运行。总之,在android 8.0 谷歌对后台服务做出了非常多的限制,比如进程保活,双开后台进程的方法在8.0无法用以前的思路完成了(╯‵□′)╯︵┻━┻。

2.android 8.0 启动服务

     启动服务的代码:     

start_service.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(MainActivity.this, ZTestService.class);
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    startForegroundService(intent);
                    //8.0之后只允许使用如上方式启动服务(一定是前台)
                }else{
                    startService(intent);
                }
            }
        });

 

  接下来就是最重要的部分,服务的代码:

import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.IBinder;
import android.support.annotation.RequiresApi;
import android.util.Log;

import com.example.zhangzihao.testbig.R;

public class ZTestService extends Service {

    private final String TAG = "test";
    private static final String CHANNEL_ID = "myService";

    //创建服务时调用
    @RequiresApi(api = Build.VERSION_CODES.O)
    @Override
    public void onCreate() {
        super.onCreate();
        //设置通知渠道
        NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        NotificationChannel Channel = new NotificationChannel(CHANNEL_ID, "主服务", NotificationManager.IMPORTANCE_HIGH);
        Channel.enableLights(true);//设置提示灯
        Channel.setLightColor(Color.GREEN);//设置提示灯颜色
        Channel.setShowBadge(true);//显示logo
        Channel.setDescription("你好啊");//设置描述
        Channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); 
        //设置锁屏可见 VISIBILITY_PUBLIC=可见
        if (manager != null) {
            manager.createNotificationChannel(Channel);
        }

        Notification notification = new Notification.Builder(this)
                .setChannelId(CHANNEL_ID)
                .setContentTitle("主服务")//标题
                .setContentText("运行中...")//内容
                .setWhen(System.currentTimeMillis())
                .setSmallIcon(R.mipmap.ic_launcher)//小图标一定需要设置,否则会报错(如果不设置它启动服务前台化不会报错,但是你会发现这个通知不会启动),如果是普通通知,不设置必然报错
                .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher))
                .build();
        //如果不设置startForeground方法,那么5秒之后就会报错
        startForeground(1, notification);
        
        //服务前台化只能使用startForeground()方法
        // ,不能使用 notificationManager.notify(1,notification)
        
        

    }

    //服务执行的操作
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    //销毁服务时调用
    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy");
    }

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

 

 

注意点:

  1. 只能使用startForegroundService.
  2. 启动服务前台化通知的方法是startForeground(),如果使用notificationManager.notify(),将不会关联你启动的服务,系统会将它作为一个普通通知处理

那么8.0及其以上是只能启动前台服务了吗?

笔者找了部分博客,下面这个可以作为启动后台服务的一个参考,不过这并不是Google所推崇的,如果可以还是尽量使用前台服务。

https://blog.csdn.net/c1392851600/article/details/79659582

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值