android Foreground Service 前台服务/notification全局通知
android Foreground Service 前台服务/notification全局通知
- 前言
- 要素简介
- 前台服务(Foreground Service)
- 全局通知(notification)
- 功能实现
- 声明服务与获取权限
- Notification 初始化
- NotificationChannel 通知渠道
- update
- 移除通知
- 启动服务
- 完整AppService.java代码
- 效果演示图
- 结语
前言
我在设计一款自用的用于自我管理的app,为了增强自我反馈,我想要这个软件能够持续的显示我执行某一个事件所用的时间。并且为了使得软件不会被系统自动关闭,百般斟酌后我选了前台服务方案。
要素简介
前台服务(Foreground Service)
前台服务(Foreground Service)相比起后台服务(Service),拥有一个优势那就是在系统内存不足的时候不允许系统杀死的服务,并且在运行时需要能被用户所知,需要在状态栏创建一个通知来管理。
全局通知(notification)
全局通知(notification),常用于告知用户某些事件在某个事件发生,在发动时会在状态栏和通知栏都显示信息,用户可以点击信息进行某些功能的管理
功能实现
声明服务与获取权限
声明权限
<!-- 通知权限 -->
<!-- <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>--><!-- 前台权限权限 --><uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
声明service
<service android:name=".AppService"/>
在最新版本中notification已被启用,改为使用NotificationCompat
案例如下:
Notification 初始化
registerNotificationChannel();notifyId = 0x975;//(int) System.currentTimeMillis();Intent nfIntent = new Intent(this, HostActivity.class);mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);mBuilder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标).setContentTitle("下拉列表中的Title") // 设置下拉列表里的标题.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标.setContentText("要显示的内容") // 设置上下文内容.setWhen(System.currentTimeMillis()) // 设置该通知发生的时间//.setPriority(Notification.PRIORITY_MIN) //设定为最低优先级.setPriority(Notification.PRIORITY_HIGH) //设定为最高优先级.setOngoing(true)//设定为点击后不消失;if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {mBuilder.setContentTitle(getResources().getString(R.string.app_name));}//notificationManager.notify(notifyId, mBuilder.build());startForeground(notifyId, mBuilder.build());
- 其中notifyId是通知的唯一标识当通知的notify一致时,再发布通知则会覆盖原有的通知内容。这个方法也常用于实时更新通知内容
- 前台服务发布通知的方法为startForeground,使用方法和notificationManager.notify类似,不需要另外再注册Manager。
NotificationChannel 通知渠道
而在高版本的安卓中,还需要注册通知渠道:
/*** 注册通知通道*/private void registerNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);NotificationChannel notificationChannel = notificationManager.getNotificationChannel(CHANNEL_ID);if (notificationChannel == null) {NotificationChannel channel = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,NotificationManager.IMPORTANCE_HIGH//NotificationManager.IMPORTANCE_MIN);//NotificationManager.IMPORTANCE_HIGH //NONE 为不弹出横幅,HIGH为弹出横幅;//是否在桌面icon右上角展示小红点channel.enableLights(true);//小红点颜色channel.setLightColor(Color.RED);//通知显示channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);//是否在久按桌面图标时显示此渠道的通知channel.setShowBadge(true);notificationManager.createNotificationChannel(channel);}}}
update
用于刷新通知内容
/*** 主自定义线程启动函数*/private void startMyThread() {stopThread=false;Thread dateFlash=new Thread() {@Overridepublic void run() {super.run();while (!stopThread) {try {Thread.sleep(1000);//每1s刷新一次} catch (InterruptedException e) {e.printStackTrace();}updateUI();startForeground(notifyId, mBuilder.build());}}};dateFlash.start();}
移除通知
stopForeground(true);
//true表示移除
启动服务
启动前台服务的方法和一般方法相同
/*** 启动前台服务*/private void show2(){Intent mIntent=new Intent(MainActivity.this,AppService.class) ;// mIntent.putExtra("startId",now_Event.getEvent_id());
// mIntent.putExtra("startHour",now_Event.getStart_hour());
// mIntent.putExtra("startMin",now_Event.getStart_min());startService(mIntent);//直接启动服务方式启动//mAppService.startForeground(110, notification);// 开始前台服务}
完整AppService.java代码
package com.example.myapplication;import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.util.Log;import java.util.Calendar;import androidx.core.app.NotificationCompat;public class AppService extends Service {public static final String CHANNEL_ID = " com.example.myapplication.AppService";public static final String CHANNEL_NAME = " com.example.myapplication";@Overridepublic IBinder onBind(Intent intent) {return null;}private static final String TAG = AppService.class.getSimpleName();@Overridepublic void onCreate() {super.onCreate();Log.d(TAG, "onCreate()");registerNotificationChannel();notifyId = 0x975;//(int) System.currentTimeMillis();Intent nfIntent = new Intent(this, HostActivity.class);mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);mBuilder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent.setLargeIcon(BitmapFactory.decodeResource(this.getResources(),R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标).setContentTitle("下拉列表中的Title") // 设置下拉列表里的标题.setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标.setContentText("要显示的内容") // 设置上下文内容.setWhen(System.currentTimeMillis()) // 设置该通知发生的时间//.setPriority(Notification.PRIORITY_MIN) //设定为最低优先级.setPriority(Notification.PRIORITY_HIGH) //设定为最低优先级.setOngoing(true)//设定为点击后不消失;if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) {mBuilder.setContentTitle(getResources().getString(R.string.app_name));}//notificationManager.notify(notifyId, mBuilder.build());startForeground(notifyId, mBuilder.build());startMyThread(); //启动主线程}@Overridepublic void onDestroy() {Log.d(TAG, "onDestroy()");stopForeground(true);super.onDestroy();}/*** 自定义变量群*/boolean stopThread=false;NotificationCompat.Builder mBuilder;NotificationManager notificationManager;int notifyId;int test_cnt=0;Calendar calendar = Calendar.getInstance();/*** 主自定义线程启动函数*/private void startMyThread() {stopThread=false;Thread dateFlash=new Thread() {@Overridepublic void run() {super.run();while (!stopThread) {try {Thread.sleep(1000);//每1s刷新一次} catch (InterruptedException e) {e.printStackTrace();}updateUI();startForeground(notifyId, mBuilder.build());}}};dateFlash.start();}/*** 注册通知通道*/private void registerNotificationChannel() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);NotificationChannel notificationChannel = notificationManager.getNotificationChannel(CHANNEL_ID);if (notificationChannel == null) {NotificationChannel channel = new NotificationChannel(CHANNEL_ID,CHANNEL_NAME,NotificationManager.IMPORTANCE_HIGH//NotificationManager.IMPORTANCE_MIN);//NotificationManager.IMPORTANCE_HIGH //NONE 为不弹出横幅,HIGH为弹出横幅;//是否在桌面icon右上角展示小红点channel.enableLights(true);//小红点颜色channel.setLightColor(Color.RED);//通知显示channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);//是否在久按桌面图标时显示此渠道的通知channel.setShowBadge(true);notificationManager.createNotificationChannel(channel);}}}private void updateUI() {/*** 显示当前任务和执行时间*/mEvent now_Event = MainActivity.now_Event;String event_time = "";//Log.i(TAG, "--------flash--------");if (now_Event == null)return;String event_name = "";switch (now_Event.getEvent_id()) {case 10001:event_name = "休眠";break;case 10002:event_name = "恰饭";break;case 10003:event_name = "其他生理需求";break;case 10004:event_name ="开发项目 ";break;case 10005:event_name ="巩固技术 ";break;case 10006:event_name ="其他工作任务 ";break;case 10007:event_name ="满足求知欲 ";break;case 10008:event_name ="满足好胜心 ";break;case 10009:event_name="休闲娱乐 ";break;case 10010:event_name="学习";break;case 10011:event_name="锻炼";break;case 10012:event_name="自我提升 ";break;}calendar = Calendar.getInstance();int n_hour = calendar.get(Calendar.HOUR_OF_DAY);int n_minute = calendar.get(Calendar.MINUTE);int show_hour;int show_minute;int set_hour = now_Event.getStart_hour();int set_minute = now_Event.getStart_min();if (n_minute < set_minute) {show_hour = n_hour - set_hour - 1;show_minute = n_minute + 60 - set_minute;} else {show_hour = n_hour - set_hour;show_minute = n_minute - set_minute;}event_time = ""+show_hour + "小时" + show_minute+"分钟";//记录时间mBuilder.setContentTitle(event_name); // 设置下拉列表里的标题mBuilder.setContentText("执行了:"+ event_time);// 设置上下文内容}}
效果演示图
某个正在执行的任务:
通知栏状态显示:
完整工程下载(待完成)
结语
完整的APP还在制作中,但是这一部分功能还是成功实现了。
在实现的过程中遇到了一个难题:无法隐藏或者显示横幅
生成通知时会产生一个横幅,有时候又不生成。我期望是不生成的,期望通过app内设置能够实现,但是目前设置均无效,渴望路过的大神能够解惑(〃‘▽’〃)
android Foreground Service 前台服务/notification全局通知相关推荐
- Android Foreground Service (前台服务)-by:nixs
一.如何保活后台服务 在Android Services (后台服务) 里面,我们了解了Android四大组件之一的Service,知道如何使用后台服务进行来完成一些特定的任务.但是后台服务在系统内存 ...
- Foreground Service前台服务
Foreground Service前台服务 介绍前台服务 模拟播放器前台服务发送通知 介绍前台服务 前台服务是那些被认为用户知道(用户所认可的)且在系统内存不足的时候不允许系统杀死的服务.前台服务必 ...
- 邊實驗邊分析 - Android Foreground Service的使用
邊實驗邊分析 - Android Foreground Service的使用 一.簡述 二.Android LowMemoryKiller 介紹 三.startService方法的調用行爲測試 給Se ...
- Android Service前台服务 StartForeground
前言 前面写了一个脚本 来执行自动打卡 效果还不错 又学习了一些android的体系知识点 其中就用到了前台服务 利用播放器的模式 来消除被杀的可能 提高Service的优先级 如何保活Service ...
- Android Foreground Service
为了防止后台服务被系统干掉,我们需要将服务提升为前台服务. 示例代码: 需要在AndroidManifest 添加 前台服务的权限 : <uses-permission android:name ...
- android q启动前台服务,Android 启动前台服务,适配 vivo 与 OPPO 手机,第一期
Android 启动前台服务,华为.小米.三星.OPPO.VIVO的配合程度接 这是前文链接,我先甩在这里,上篇文章主要分析了几种品牌手机关于通知的配合程度,这篇文章先写第一期的解决方案,毕竟需求还是 ...
- Android 如何屏蔽联通服务信息WAP通知信息http://g.iuni.com.cn, 百度无耻不让发贴批拼联通
如何屏蔽联通服务信息WAP通知信息http://g.iuni.com.cn, 百度知道无耻不让发贴批拼联通. 如是你用联通的卡,你经常甚至每天都收到多条垃圾短信,其中有一种是看不到发送方的号码的,这就 ...
- Service前台服务
让服务以notification的形式,显示在前台,不容易被杀死 只需在Service的inCreate里面,构建notification,不是用NotificationManager启动,而是用st ...
- Android前台服务讲解二之自定义通知视图(RemoteViews)及数据UI更新
Notification支持文字内容显示.震动.三色灯.铃声等多种提示形式,在默认情况下,Notification仅显示消息标题.消息内容.送达时间这3项内容. 1.更新系统通知Notificatio ...
最新文章
- ant design pro 加载慢_ant design pro (九)引入外部模块
- openssl生成https证书
- python打开figure对象_Python ——绘图 plt.figure()的使用
- html5生日时间怎么写代码,用JavaScript写得比较日期,计算生日的函数,
- 电路常识性概念(2)-电容
- Halcon:Image、region、xld常用的处理
- Jenkins修改管理员密码
- python实现批量更改xml文件中内容替换
- Docker安装Mysql 案例和Tomcat测试
- Spring学习总结(29)——Spring异步处理@Async的使用以及原理、源码分析(@EnableAsync)
- 9 月,有远见的程序员,都关注了这个人!
- Android自动化测试之Monkey
- 【Pandas分组聚合】进阶:透视表、交叉表(pivot_table() 、crosstab())
- GitHub 这8大超实用小技巧,99.9%的人都不知道!
- 【解决】client does not support authentication转载的两种解法
- 一个window下的简单的全局快捷键向指定的进程发送的c代码与exe程序下载(二)
- Dell PowerEdge™ R510 Servers 安装 Ubuntu Server 10.04 LTS 笔记
- 计算机网络——知识点
- 网络重置导致无法联网
- SpringBoot整合RabbitMQ 访问保错: reply-text=NOT_ALLOWED - access to vhost '/' refused for user 'cuit'
热门文章
- php如何升级swoole,升级 Swoole
- Python 模拟鼠标点击(可后台)
- HY000][1129] null, message from server: Host '192.168.109.3' is blocked because of many connection
- linux基础56——uniq
- 鬼脚七:淘宝卖家需知的搜索知识(上)
- vue/uniapp - 返回上一页并onLoad刷新数据
- 半路出家: 如何转行成为软件开发者
- 《CSDN社区电子杂志——移动开发杂志》总第2期发布!
- 常见决策树分类算法都有哪些?
- iOS Swift 5中的键盘处理