前言 

google在更新Android8.0后对Service的权限越发收紧。导致目前想要启动服务必需实现服务的前台化(否则在服务启动5秒后,系统将自动报错)。下面我们就来看看如何在8.0上启动服务。

看看8.0之前的版本怎么启动Service

  在看8.0启动服务的方法之前,我们先看看8.0之前是怎么启动服务的。这样可以对比,也可以理解增加了那些部分。

  1.在Activity启动服务:

  1. Intent intent = new Intent(MainActivity.this,MainService.class);
  2. startService(intent);

  8.0之前是使用startService 直接启动服务的。后续服务就可以在后台运行了

  2.将服务前台化:

  虽然8.0之前如果没有明确需求,是可以不需要让服务前台化通知栏显示的,但是我们为了对比实现下8.0之前的服务前台化。

  1. public void onCreate() {
  2. super.onCreate();
  3. Notification notification = new Notification.Builder(this)
  4. .setContentTitle("主服务")//设置标题
  5. .setContentText("运行中...")//设置内容
  6. .setWhen(System.currentTimeMillis())//设置创建时间
  7. .setSmallIcon(R.mipmap.ic_launcher)//设置状态栏图标
  8. .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))//设置通知栏图标
  9. .build();
  10. startForeground(1,notification);
  11. }

可以服务启动后,可以在服务的onCreate()里直接实现服务前台化。

8.0版本怎么启动Service

  1.在Activity里启动服务

  1. Intent intent = new Intent(MainActivity.this,MainService.class);
  2. startForegroundService(intent);

  可以看到启动的方法变成了startForegroundService();

  2.创建8.0版本必需实现的服务前台化

  1. private static final String CHANNEL_ID = "NFCService";
  2. public void onCreate() {
  3. super.onCreate();
  4. NotificationManager manager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
  5. NotificationChannel Channel = new NotificationChannel(CHANNEL_ID,"主服务",NotificationManager.IMPORTANCE_HIGH);
  6.      Channel.enableLights(true);//设置提示灯
  7.      Channel.setLightColor(Color.RED);//设置提示灯颜色
  8. Channel.setShowBadge(true);//显示logo
  9. Channel.setDescription("ytzn");//设置描述
  10. Channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC); //设置锁屏可见 VISIBILITY_PUBLIC=可见
  11. manager.createNotificationChannel(Channel);
  12.  
  13. Notification notification = new Notification.Builder(this)
  14. .setChannelId(CHANNEL_ID)
  15. .setContentTitle("主服务")//标题
  16. .setContentText("运行中...")//内容
  17. .setWhen(System.currentTimeMillis())
  18. .setSmallIcon(R.mipmap.ic_launcher)//小图标一定需要设置,否则会报错(如果不设置它启动服务前台化不会报错,但是你会发现这个通知不会启动),如果是普通通知,不设置必然报错
  19. .setLargeIcon(BitmapFactory.decodeResource(getResources(),R.mipmap.ic_launcher))
  20. .build();
  21. startForeground(1,notification);//服务前台化只能使用startForeground()方法,不能使用 notificationManager.notify(1,notification); 这个只是启动通知使用的,使用这个方法你只需要等待几秒就会发现报错了
  22.  
  23. }

8.0版本后多了一个需要创建的NotificationChannel,在Notification里多了一个需要设置的setChannelId();

  8.0版本启动服务注意点:

  1. 请注意8.0版本只能使用startForegroundService()启动服务,不能在使用startService()
  2. 请注意在new NotificationChannel(CHANNEL_ID,"主服务",NotificationManager.IMPORTANCE_HIGH); 的第一个参数id为Channel的通道id需要与Notification的setChannelId()设置的id一致,否则会报前台服务无效的异常。
  3. 注意启动服务前台化通知的方法是startForeground(),如果使用notificationManager.notify(),将不会关联你启动的服务,系统会将它作为一个普通通知处理

最后了解什么是NotificationChannel

Android O 引入了 通知渠道(Notification Channels),以提供统一的系统来帮助用户管理通知,如果是针对 android O 为目标平台时,必须实现一个或者多个通知渠道,以向用户显示通知。若并不以 Android O 为目标平台,当应用运行在 android O 设备上时,其行为将与运行在 Android 7.0 上时相同。
开发者可以为需要发送的每个不同的通知类型创建一个通知渠道。还可以创建通知渠道来反映应用的用户做出的选择。例如,可以为聊天应用的用户创建的每个聊天组建立单独的通知渠道。
Android O 的用户可以使用一致的系统 UI 管理大多数与通知有关的设置。所有发布至通知渠道的通知都具有相同的行为。当用户修改任何下列特性的行为时,修改将作用于通知渠道:

  • 重要性
  • 声音
  • 振动
  • 在锁屏上显示
  • 替换免打扰模式

通知优先级和重要性

Android O 弃用了为单个通知设置优先级的功能。创建通知渠道时可以设置建议重要性级别。为通知渠道指定的重要性级别适用于发布至该渠道的所有通知消息。可以配置五个级别中的一个,这些级别代表着通知渠道可以打断用户的程度,范围是 IMPORTANCE_NONE(0)IMPORTANCE_HIGH(4)。默认重要性级别为 3:在所有位置显示,发出提示音,但不会对用户产生视觉干扰。创建通知渠道后,只有系统可以修改其重要性。用户可以在设置中找到。

创建通知渠道

要创建通知渠道,请执行下列操作:

  • 构建一个在软件包内具有唯一 ID 的通知渠道对象。
  • 为该通知渠道对象配置所需的任何初始设置(例如提示音以及对用户可见的可选说明)。
  • 将通知渠道对象提交到通知管理器。

如果试图使用初始值创建的通知渠道已存在,不会执行任何操作,因此启动应用时可以放心地执行以上步骤序列。

创建通知渠道组

如果应用支持多个帐户,则可为每个帐户创建一个通知渠道组。通知渠道组用于对一款应用内的多个同名通知渠道进行管理。例如,一款社交网络应用可能提供面向个人帐户以及企业帐户的支持。在此情境下,每个帐户可能都需要多个功能和名称相同的通知渠道。
一个包括 2 个通知渠道的个人帐户:

  • 帖子新增评论的通知。
  • 联系人推荐帖子的通知。

一个包括 2 个通知渠道的企业帐户:

  • 帖子新增评论的通知。
  • 联系人推荐帖子的通知。

在本例中,将与每个用户帐户相关的通知渠道组织成专用组可确保用户能在 Settings 中轻松地进行区分。每个通知渠道组都必须在软件包内具有唯一 ID,并具有用户可见的名称。下面这段代码演示了如何创建通知渠道组。

  1. // 通知渠道组的id.
  2. String group = "my_group_01";
  3. // 用户可见的通知渠道组名称.
  4. CharSequence name = getString(R.string.group_name);
  5. NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  6. mNotificationManager.createNotificationChannelGroup(new NotificationChannelGroup(group, name));

新建渠道组后,便可调用 setGroup()将某个新渠道关联到该组。注意,只能在将渠道提交给通知管理器之前修改通知渠道与组之间的关联。

创建通知

要创建通知,请调用 Notification.Builder.build(),它返回的 Notification对象包含的指定值。要发出通知,请通过调用 [notify()](https://developer.android.google.cn/reference/android/app/NotificationManager.html#notify(int, android.app.Notification))将 Notification对象传递给系统。
创建的通知Notification对象必须包含以下内容:

如果 应用是以 Android O 为目标平台并且在不指定有效通知渠道的情况下发布通知,那么通知将无法发布,系统会记录错误。
注:可以在 Android O 中启用一个新设置,当针对 Android O 的应用试图在没有通知渠道的情况下发布时,以 toast 形式显示屏幕警告。要为运行 Android O 的开发设备启用该设置,请转到 Settings > Developer options,然后打开 Show notification channel warnings

向渠道发布通知

下面这段代码说明如何向通知渠道发布简单通知。请注意,代码利用渠道的 ID 将通知与通知渠道关联起来。

  1. mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  2. // 为该通知设置一个id
  3. int notifyID = 1;
  4. // 通知渠道的id
  5. String CHANNEL_ID = "my_channel_01";
  6. // Create a notification and set the notification channel.
  7. Notification notification = new Notification.Builder(MainActivity.this)
  8. .setContentTitle("New Message")
  9. .setContentText("You've received new messages.")
  10. .setSmallIcon(R.drawable.ic_notify_status)
  11. .setChannelId(CHANNEL_ID)
  12. .build();
  13. // 发布通知
  14. mNotificationManager.notify(id, notification);

读取通知渠道设置

用户可以修改通知渠道的设置,包括振动和提示音等行为。开发者可以调用以下两个方法来发现用户对通知渠道应用的设置:

更新通知渠道设置

一旦创建了通知渠道,其设置和行为就由用户掌控。可以再次调用 createNotificationChannel()以重命名现有通知渠道,或更新其说明。以下示例代码说明如何通过创建启动 Activity 的 Intent 将用户重定向到通知渠道的设置。在本例中,Intent 要求提供扩展数据,包括通知渠道的 ID 和应用的软件包名称。

  1. Intent intent = new Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS);
  2. intent.putExtra(Settings.EXTRA_CHANNEL_ID,mChannel.getId());
  3. intent.putExtra(Settings.EXTRA_APP_PACKAGE, getPackageName());startActivity(intent);

删除通知渠道

可以通过调用 deleteNotificationChannel()
来删除通知渠道。作为一个垃圾信息预防机制,通知设置中将显示已删除渠道的数量。可以通过以下任一方法清除开发设备上的测试渠道:重新安装应用;清除与应用副本关联的数据。以下示例代码演示了如何删除通知渠道。

  1. NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
  2. // 通知渠道的id
  3. String id = "my_channel_01";
  4. NotificationChannel mChannel = mNotificationManager.getNotificationChannel(id);
  5. mNotificationManager.deleteNotificationChannel(mChannel);

Android 开发 8.0版本启动Service的方法的更多相关文章

  1. android 开发 实现多个动态权限的方法(并且兼容6.0以下的版本权限授权)

    android开发权限授权因为版本的不同有不同的授权方式,6.0以下的版本使用的是在注册表中添加权限的静态授权(这种授权权限提示只会出现在app安装的时候),而6.0以上(包含6.0)就需要动态授权的 ...

  2. Android开发指南--0 总览

    无意间发现一个网站,主打IOS方面的教程,然而作为一个Android开发者,我就找了下网站里有没有Android的教程,还真有,这里就翻译一下. 翻译目标教程:https://www.raywende ...

  3. Android开发之解决APP启动白屏或者黑屏闪现的问题

    在做搜芽的过程中,发现那个外包人缘做的不行,由于启动的时候会停顿,然后白屏一会,联想到几个月前我在我的三僚企业通信软件里面拉起9K-Mail的时候也会黑屏,所以决定学习一下.解决一下.这不,万能的网络 ...

  4. Redis 3.0版本启动时出现警告的解决办法

    原文:http://m.blog.csdn.net/article/details?id=50864933 Redis 3.0.7版本启动时出现警告的解决办法 发表于2016/3/12 12:52:4 ...

  5. 解决IDEA2018.1.5或者Android Studio 3.0版本的输入法不跟随光标问题

    问题1:IDEA2018.1.5版本的输入法不跟随光标 解决办法1:修改JDK版本,步骤如下: 1. 使用快捷键ctrl+shift+A,在输入框中输入Switch Boot JDK,如图所示 2.替 ...

  6. Android开发之去掉标题栏的三种方法,推荐第三种

    Android:去掉标题栏的三种方法和全屏的三种方法 第一种:一般入门的时候常常使用的一种方法 onCreate函数中增加下面代码: requestWindowFeature(Window.FEATU ...

  7. android开发中关于继承activity类中方法的调用

    android开发中关于继承activity类中的函数,不能在其他类中调用其方法. MainActivity.java package com.example.testmain; import and ...

  8. Android开发之通过Intent启动其他App的Service

    在Android5.0以前可以通过隐式Intent方式启动其他App的Service,就跟Activity启动隐式Intent一样的. 但是在5.0以后,只能使用显示的Intent方式启动了. 启动其 ...

  9. Android 开发进程 0.35 升级编译版本Android12

    Android12升级 工作需要升级到编译版本31 在这里记录一下遇到的问题. 错误:Manifest merger failedManifest merger failed 这个问题通常搜到的答案是 ...

随机推荐

  1. day11.3分页操作divmod

    # 分页显示 divmod(被除数,除数) INFO_LIST = [] for i in range(836): template = "第%s天,笨笨先僧 always be there ...

  2. 关于jstl中碰到的Property 'username' not found on type java.lang.String异常

    在jstl的forEach循环的时候总是有异常,刚开始以为是把类的属性名打错了,因为显示的是Property not found,但就算从类文件里面复制属性名过来依然显示的是Property not ...

  3. python rabbitMQ持久化队列消息

    import pika connection = pika.BlockingConnection( pika.ConnectionParameters('localhost'))#建立一个最基本的so ...

  4. 学习笔记DL003:神经网络第二、三次浪潮,数据量、模型规模,精度、复杂度,对现实世界冲击

    神经科学,依靠单一深度学习算法解决不同任务.视觉信号传送到听觉区域,大脑听学习处理区域学会“看”(Von Melchner et al., 2000).计算单元互相作用变智能.新认知机(Fukushi ...

  5. BUAA-OO第一单元小结

    引言 四周过去了,oo课程的第一阶段作业也算告一段落.在第一单元的内容中,主题是始终如一的多项式求导,但三次作业要求完善的求导功能一次比一次丰富,难度也逐渐增加,也是费了不少心思.接下来就回顾与小结一 ...

  6. Go 包管理工具--glide

    网上有一篇解释glide比较好的文章:https://my.oschina.net/u/553243/blog/1475626 在命令行中输入glide $glide NAME: glide - Ve ...

  7. 全志A33开发板的安卓控制LED-2-JNI基础

    虽然您可以完全使用Java编写应用程序,但有些情况下Java本身并不能满足您的应用程序的需求.当应用程序不能完全用Java编写时,程序员使用JNI编写Java本机方法来处理这些情况. 以下示例说明何时 ...

  8. java 大数运算[转]

    用JAVA 实现算术表达式(1234324234324 + 8938459043545)/5 + 343434343432.59845 因为JAVA语言中的long 定义的变量值的最大数受到限制,例如 ...

  9. Mysql逆向工程效率神器之使用IDE自动生成Java实体类

    Mysql逆向工程效率神器之使用IDE自动生成Java实体类 简介:实战使用IDE根据Mysql自动生成java pojo实体类 1.IDEA连接数据库 菜单View→Tool Windows→Dat ...

  10. vue中直接修改props中的值并未给出警告,为啥?

    问:vue中直接修改props中的值并未给出警告,为啥? 答:如果props传入的值是引用类型,在子组件中改变其元素,不改变引用,那么不报错: 如果是基本类型,那么在修改时浏览器控制台会有报错信息. ...