第二十八章 后台服务
服务类(service)
- 继承service类, 例如
intentService
- 声明service类
类似于activity, 需要在AndroidManifest
中声明
<service android:name="com.bignerdranch.android.photogallery.PollService"/>
- 构造方法
- 重写相应的方法
onHandleIntent(Intent)
- 启动, 构造intent并通过
Context.startService(intent)
.
PendingIntent
- 是一种
token
对象. 用于描述intent
及其最终的行为
不像intent是一种立即的行为. - 有三种方法可以了解:
Pendingintent.getActivity()
Pendingintent.getService()
Pendingintent.getBroadcast()
Pendingintent.getservice(Context, int, Intent, flags)
打包了一个Context.startService(intent)
其flags有以下几种标志:
FLAG_ONE_SHOT:
只能使用一次的标志. 它将自动为您取消. 以后通过它发送的任何尝试都将失败。FLAG_NO_CREATE
:如果所描述的PendingIntent
尚不存在,则只返回null
而不创建它。FLAG_CANCEL_CURRENT
: 如果所描述的PendingIntent
已存在,则应在生成新内容之前取消当前内容。FLAG_UPDATE_CURRENT
: 如果所描述的PendingIntent
已经存在,那么保留它,但用这个新的intent
替换它的extra
数据。FLAG_IMMUTABLE
: 创建的PendingIntent
应是不可变的.0
: 就意味着你不打算使用任何一种flag来控制PendingIntent的创建。
使用AlarmManager延迟启动服务
- 使用
Context.ALARM_SERVICE
检索
AlarmManager alarmManager = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
- 设置AlarmManager有三点需要注意:
1.启动时间的精准与否: 非精准重复setRepeating
. 精准启动一次setWindow
或setExact
, 想重复, 则需要自己手动设置
2.时间的选择: 基于流逝的相对时间(推荐
) 还是达到某个固定的时刻启动
3.强制唤醒设备(在黑屏状态下): ELAPSED_REALTIME_WAKEUP
和 RTC_WAKEUP
AlarmManager.ELAPSED_REALTIME
对应SystemClock.elapsedRealtime()
相对流逝
AlarmManager.RTC
对应SystemClock.currentThreadTimeMillis
固定时刻private static final long POLL_INTERVAL = TimeUnit.MINUTES.toMillis(1);
参数为流逝的时间, 以分钟为单位. 是long型
Intent i = PollService.newIntent(context);
PendingIntent pi = PendingIntent.getService(context, 0, i, 0);
AlarmManager alarmManager = (AlarmManager)
context.getSystemService(Context.ALARM_SERVICE);
if (isOn){
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime(), POLL_INTERVAL, pi );
}else{
alarmManager.cancel(pi);
pi.cancel();
}
Notification
- 闪光灯权限
<uses-permission android:name="android.permission.FLASHLIGHT"/>
- 振动器权限
<uses-permission android:name="android.permission.VIBRATE"/>
- 创建NotificationManager
- 创建Notificationchannel
NotificationChannel channel = new NotificationChannel("fore_service", "前台服务", NotificationManager.IMPORTANCE_HIGH);
1.ID
: 通道的ID。每个包中必须是唯一的。如果值太长,可能会被截断。
2.name
: 频道的用户可见名称。当系统区域设置更改时,可以通过侦听ACTION_LOCALE_CHANGED
广播来重命名此频道。建议的最大长度为40个字符;如果值太长,可能会被截断。
3.importance
: 渠道的重要性。这将控制发送到此channel中通知的方式。 - 在
NotificationManager
中创建Notificationchannel
- 创建Notification
- 定制Notification的各种行为
- 发布notification
NotificationManager.notify(id, Notification)
id唯一标识, 如果相同就会替换消息(可以实现类似与进度条或者其他动态视觉效果)
Intent intent = new Intent(this, NotificationActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
NotificationManager manager = (NotificationManager) getSystemService
(NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel
("fore_service", "前台服务", NotificationManager.IMPORTANCE_HIGH);
assert manager != null;
manager.createNotificationChannel(channel);
notification = new NotificationCompat.Builder(MainActivity.this, "fore_service")
.setContentTitle("This is a content title")
.setContentText("This is a content text")
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.mipmap.ic_launcher)
.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.mipmap.ic_launcher))
.setContentIntent(pi)
.setAutoCancel(true)
.setVibrate(new long[]{0, 1000, 1000, 1000})
.setLights(Color.GREEN, 1000, 1000)
.build();
manager.notify(1, notification);
Log.d(TAG, "正常运行");
NotificationManager manager = (NotificationManager) getSystemService
(NOTIFICATION_SERVICE);
manager.cancel(1);
相关小记
- non-sticky
- sticky
- 绑定服务: 本地服务绑定和远程服务绑定
挑战练习
- 可穿戴设备上的通知
- 在Lollipop设备上使用
JobSchedule
和JobService