Android笔记—仿绿色守护嗜睡模式通知
资料来源如下
- 第一行代码(第二版)
- Android Training Notifying the User
- Android API 通知
- 【Android】状态栏通知Notification、NotificationManager详解
编程环境
- Android Studio 2.2.3
导语
- OneTapDoze遇到的第一个难题,顺带记录Android 通知相关内容
最终效果
绿色守护进入doze模式后,会在通知栏创建一个计时通知 如下图
退出doze模式后,会指示进入doze和退出doze的时间段。
我们要仿照的样式就是这样,进入退出doze,对应创建通知的代码都在doze模式改变的Broadcast中。
基础部分
创建通知
- 行文前:
Android每次版本几乎都会有通知API的改动,不同版本之间通知兼容性很是问题,为此我们使用support_v7 库中的NotificationCompat.Builder代替Notification.Builder二者使用方式相同
涉及到的两个类
- NotificationManager
- Notification (support库中对应NotificationCompat)
NotificationManager
- 状态栏通知的管理类,负责发通知、清除通知等
- NotificationManager 是一个系统Service,必须通过 getSystemService()方法来获取
Notification
- 具体的状态栏通知对象,可以设置icon、文字、提示声音、振动等参数
- 一个Builder对象至少包含三个方面
- 一个小图标,通过setSmallIcon()方法设置。
- 通知标题,通过setContentTitle()方法设置。
- 详细文本,通过setContentText()方法设置。
简单示例
创建通知构建器
代码1
2
3
4
5
6Notification notification = new NotificationCompat.Builder(this)
.setContentTitle("这是通知标题")
.setContentText("这是通知内容")
//这里使用的是应用图标,一般没人这么干,就是为了方便
.setSmallIcon(R.mipmap.ic_launcher)
.build();发布通知
- 获得NotificationManager的实例
- 使用notify()方法发布通知。在调用notify()方法 指定通知的ID,(ID用于通知更新) 加载Notification实例
1
2
3
4int mNotificationId = 001;
NotificationManager manager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
manager.notify(mNotificationId, notification);
效果如下
- android 7.0 / 6.0 /4.0 通过
更新通知
可以创建一个全新的NotificationCompat对象,也可以在原NotificationCompat对象基础上修改,最后只要 .notify 方法中对应同一个 mNotificationId ,系统就会自动更新已有通知,代码不在累赘。
基础部分到此,足矣
正题
- 实现时间段的显示,肯定会保存系统进入doze 退出doze对应的时间点。再计算出中间经历的时间。
提取系统时间
java.util.Date
这里用到了java中的 时间类型 java.util.Date
java.util.Date 是java中常用时间类型,可以被SimpleDateFormat格式化format() 指定输出的时间格式
比如我们需要 小时:分:秒SimpleDateFormat scanf = new SimpleDateFormat("HH:mm:ss");
scanf.format(java.util.Date)
即可。提前当前系统时间
1
2java.util.Date time_after = null;
time_after = new java.util.Date(System.currentTimeMillis());计算时间差
理论上是两个时间相减再格式化输出即可,可惜没成,原因还没找到。于是土办法:- 调用 .getTime() 方法,将 java.util.Date 转化为毫秒计时(long)
- 取两者差值
- 转化为 时间长短 字符串返回,
代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21size = (time_after.getTime() - time_befor.getTime());
string = scanf.format(time_befor) + "-" + scanf.format(time_after) + "="+ trform(size);
String trform(long size) {
long day, hour, min, secone;
day = size / (1000 * 60 * 60 * 24); //以天数为单位取整
hour = (size / (60 * 60 * 1000) - day * 24); //以小时为单位取整
min = ((size / (60 * 1000)) - day * 24 * 60 - hour * 60); //以分钟为单位取整
secone = (size / 1000 - day * 24 * 60 * 60 - hour * 60 * 60 - min * 60);
if (day != 0) {
return day + "d" + hour + "h" + min + "m" + secone + "s";
} else if (hour != 0) {
return hour + "h" + min + "m" + secone + "s";
} else if (min != 0) {
return min + "m" + secone + "s";
} else {
return secone + "s";
}
}
通知扩展布局
在如下图片中,可以发现,通知在发出后,只默认显示最近一次的时间记录,其他时间记录可以在此条通知上下滑查看。明显与基础部分不同。
此处应用了 Builder.setStyle() 拓展布局,顾名思义,这是用于拓展通知显示范围
使用扩展布局
- 使用拓展布局
- 构建一个 inboxStyle 对象
- .addLine方法 添加 String inboxStyle 行
- 使用 Builder.setStyle( inboxStyle )加载到通知
- 等待通知发布即可。
- 简单例程如下
1
2
3
4
5
6//创建 inboxStyle
NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle();
//添加 String 行 ,前提是 我已经创建了一个 String
inboxStyle.addLine(string);
// 在notification 设置 inboxStyle 在一堆 build 里面
.setStyle(inboxStyle) - 清除原有内容,发布新的 inboxStyle 只需要
inboxStyle = new NotificationCompat.InboxStyle();
Doze模式改变广播
- 对应
ACTION_DEVICE_IDLE_MODE_CHANGED
- 坑:只能动态注册,静态注册无效,具体代码中
powermanger.ACTION_DEVICE_IDLE_MODE_CHANGED
需要实例化 PowerManger ,而 PowerManger 又是与 Activity绑定,所以只有应用保持后台存活时才会进入广播。 - 例程如下
1
2
3
4
5
6
7
8//实例化 PowerManager
PowerManager powermanger = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
//动态注册广播
intentFilter = new IntentFilter();
intentFilter.addAction(powermanger.ACTION_DEVICE_IDLE_MODE_CHANGED);
//idlemodechage 是 BroadcastReceiver
idlemodechage = new IdleModeChange();
registerReceiver(idlemodechage, intentFilter);
相关文章