制作前台服务 运行 直到它停止
Making a foreground service run until it's stopped
我的目标是在后台有一个应用程序 运行,即使屏幕关闭也是如此。就像一个音乐播放器。
现在每个人都声称您需要为此提供前台服务。为此,我正在使用 class 扩展 Worker:
public class WorkerKlasse extends Worker {
String CHANNEL_ID = "1";
Context context;
public WorkerKlasse(
@NonNull Context context,
@NonNull WorkerParameters parameters) {
super(context, parameters);
this.context = context;
notificationManager = (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
}
private NotificationManager notificationManager;
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel() {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Kanal", importance);
channel.setDescription("Beschreibung");
channel.setSound(null,null);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = (NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
@NonNull
private ForegroundInfo createForegroundInfo(@NonNull String progress) {
// Build a notification using bytesRead and contentLength
Context context = getApplicationContext();
// This PendingIntent can be used to cancel the worker
PendingIntent intent = WorkManager.getInstance(context)
.createCancelPendingIntent(getId());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel();
}
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("Test")
.setTicker("Test2")
.setSound(null)
.setSmallIcon(R.drawable.ic_launcher_background)
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, "A", intent)
.build();
return new ForegroundInfo(1,notification);
}
@NonNull
@Override
public Result doWork() {
int testint = getInputData().getInt("testint",0);
...
String progress = "Beginn";
setForegroundAsync(createForegroundInfo(progress));
//do something, in my case
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.testsound);
mediaPlayer.start();
try {
Thread.sleep(testint);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Result.success();
}
}
(在 return Result.success();
之前,前台服务应该停止),我在 MainActivity 中从这个开始:
WorkRequest myUploadWork =
new OneTimeWorkRequest.Builder(WorkerKlasse.class)
.setInputData(
new Data.Builder()
.putInt("testint",testint)
//...
.build()
)
.build();
WorkManager
.getInstance(MainActivity.this)
.enqueue(myUploadWork);
然而,当屏幕变暗或我按一下电源按钮使其变暗时,它不会保持 运行ning。只有输入密码才能进入phone,它才会继续。不过,顶部的图标表明它是前台服务。
Worker 是关于您正在执行的有限工作,可能与用户进行交互。但它不适用于音乐播放等可能的无限任务。
前台服务用于执行任何具有 visible
进程表示的“后台”作业。
此处的“背景”意味着用户可能没有直接使用您的应用程序,而是有时或以并行方式与之交互。例如,收听您正在播放的音乐。
并且由于 Android... 我不记得了,但现在很常见,任何前台服务都应该有一个通知,该通知始终对用户可见。这是很好的做法。
如果您正在流式传输任何音乐或连续声音,您可能希望在此通知中添加控件,以便用户能够管理播放。
所以,首先,把worker换成前台服务。
现在是主要问题:如果您想安排前台服务的启动怎么办。
您可以创建一个警报,并在它触发时启动前台服务。例如,Whatsapp 一直这样做以同步聊天。
创建告警和启动前台服务的例子有很多:
https://developer.android.com/guide/components/services#StartingAService
https://developer.android.com/training/scheduling/alarms#set
现有解决方案如何:
Mediaplayer 操作 mediaPlayer.start();
未阻塞线程。
通过制作 Thread.sleep
来阻止它是不好的做法。
前台服务可以用标志 Service.START_STICKY
启动,如果您还要调用 Service.startForeground
,它会尽可能长 运行。没有任何流等待一些神秘的超时。
我的目标是在后台有一个应用程序 运行,即使屏幕关闭也是如此。就像一个音乐播放器。 现在每个人都声称您需要为此提供前台服务。为此,我正在使用 class 扩展 Worker:
public class WorkerKlasse extends Worker {
String CHANNEL_ID = "1";
Context context;
public WorkerKlasse(
@NonNull Context context,
@NonNull WorkerParameters parameters) {
super(context, parameters);
this.context = context;
notificationManager = (NotificationManager)
context.getSystemService(NOTIFICATION_SERVICE);
}
private NotificationManager notificationManager;
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel() {
int importance = NotificationManager.IMPORTANCE_DEFAULT;
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, "Kanal", importance);
channel.setDescription("Beschreibung");
channel.setSound(null,null);
// Register the channel with the system; you can't change the importance
// or other notification behaviors after this
NotificationManager notificationManager = (NotificationManager)context.getSystemService(NOTIFICATION_SERVICE);
notificationManager.createNotificationChannel(channel);
}
@NonNull
private ForegroundInfo createForegroundInfo(@NonNull String progress) {
// Build a notification using bytesRead and contentLength
Context context = getApplicationContext();
// This PendingIntent can be used to cancel the worker
PendingIntent intent = WorkManager.getInstance(context)
.createCancelPendingIntent(getId());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createChannel();
}
Notification notification = new NotificationCompat.Builder(context, CHANNEL_ID)
.setContentTitle("Test")
.setTicker("Test2")
.setSound(null)
.setSmallIcon(R.drawable.ic_launcher_background)
.setOngoing(true)
// Add the cancel action to the notification which can
// be used to cancel the worker
.addAction(android.R.drawable.ic_delete, "A", intent)
.build();
return new ForegroundInfo(1,notification);
}
@NonNull
@Override
public Result doWork() {
int testint = getInputData().getInt("testint",0);
...
String progress = "Beginn";
setForegroundAsync(createForegroundInfo(progress));
//do something, in my case
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.testsound);
mediaPlayer.start();
try {
Thread.sleep(testint);
} catch (InterruptedException e) {
e.printStackTrace();
}
return Result.success();
}
}
(在 return Result.success();
之前,前台服务应该停止),我在 MainActivity 中从这个开始:
WorkRequest myUploadWork =
new OneTimeWorkRequest.Builder(WorkerKlasse.class)
.setInputData(
new Data.Builder()
.putInt("testint",testint)
//...
.build()
)
.build();
WorkManager
.getInstance(MainActivity.this)
.enqueue(myUploadWork);
然而,当屏幕变暗或我按一下电源按钮使其变暗时,它不会保持 运行ning。只有输入密码才能进入phone,它才会继续。不过,顶部的图标表明它是前台服务。
Worker 是关于您正在执行的有限工作,可能与用户进行交互。但它不适用于音乐播放等可能的无限任务。
前台服务用于执行任何具有 visible
进程表示的“后台”作业。
此处的“背景”意味着用户可能没有直接使用您的应用程序,而是有时或以并行方式与之交互。例如,收听您正在播放的音乐。
并且由于 Android... 我不记得了,但现在很常见,任何前台服务都应该有一个通知,该通知始终对用户可见。这是很好的做法。
如果您正在流式传输任何音乐或连续声音,您可能希望在此通知中添加控件,以便用户能够管理播放。
所以,首先,把worker换成前台服务。 现在是主要问题:如果您想安排前台服务的启动怎么办。
您可以创建一个警报,并在它触发时启动前台服务。例如,Whatsapp 一直这样做以同步聊天。
创建告警和启动前台服务的例子有很多:
https://developer.android.com/guide/components/services#StartingAService
https://developer.android.com/training/scheduling/alarms#set
现有解决方案如何:
Mediaplayer 操作 mediaPlayer.start();
未阻塞线程。
通过制作 Thread.sleep
来阻止它是不好的做法。
前台服务可以用标志 Service.START_STICKY
启动,如果您还要调用 Service.startForeground
,它会尽可能长 运行。没有任何流等待一些神秘的超时。