我正在针对sdk版本27进行定位,最低版本为19,并尝试获得在后台持续运行的服务。我尝试了不同的服务启动选项,但它仍然会随着应用程序被杀死。我尝试使用BroadcastReceiver在服务被杀死时启动服务,但出现错误,说应用程序在后台运行,无法启动服务,因此我尝试使用JobScheduler,但这也给我同样的错误。这应该如何实现呢?例如,如果我制作一个计步器应用程序,如何使其在后台持续运行?
我正在针对sdk版本27进行定位,最低版本为19,并尝试获得在后台持续运行的服务。我尝试了不同的服务启动选项,但它仍然会随着应用程序被杀死。我尝试使用BroadcastReceiver在服务被杀死时启动服务,但出现错误,说应用程序在后台运行,无法启动服务,因此我尝试使用JobScheduler,但这也给我同样的错误。这应该如何实现呢?例如,如果我制作一个计步器应用程序,如何使其在后台持续运行?
我使用Work-Manager创建了永久运行的服务,运行得非常完美。
public void onDestroy() {
try {
myTimer.cancel();
timerTask.cancel();
} catch (Exception e) {
e.printStackTrace();
}
Intent intent = new Intent("com.android.app");
intent.putExtra("valueone", "tostoreagain");
sendBroadcast(intent);
}
在 onReceive 方法中
@Override
public void onReceive(Context context, Intent intent) {
Log.i("Service Stoped", "call service again");
context.startService(new Intent(context, ServiceCheckWork.class));
}
如果设备重新启动,则我们有onBootCompleted操作来捕获接收器
当您针对SdkVersion“O”时
在MainActivity.java中定义getPendingIntent()
private PendingIntent getPendingIntent() {
Intent intent = new Intent(this, YourBroadcastReceiver.class);
intent.setAction(YourBroadcastReceiver.ACTION_PROCESS_UPDATES);
return PendingIntent.getBroadcast(this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
}
在这里,我们使用带有BroadcastReceiver的PendingIntent,而此BroadcastReceiver已在AndroidManifest.xml中定义。 现在,在YourBroadcastReceiver.java类中,它包含一个onReceive()方法:
Override
public void onReceive(Context context, Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_PROCESS_UPDATES.equals(action)) {
NotificationResult result = NotificationResult.extractResult(intent);
if (result != null) {
List<Notification> notifications = result.getNotification();
NotificationResultHelper notificationResultHelper = new
NotificationResultHelper(
context, notifications);
// Save the notification data to SharedPreferences.
notificationResultHelper.saveResults();
// Show notification with the notification data.
notificationResultHelper.showNotification();
Log.i(TAG,
NotificationResultHelper.getSavedNotificationResult(context));
}
}
}
}
就像你所说的:
我尝试使用BroadcastReceiver在服务被关闭时启动服务,但是却出现错误,提示应用程序在后台并且无法启动服务
在Oreo版本中,当你处于后台状态并且想要启动一个服务时,该服务必须成为前台服务。使用以下代码:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
context.startForegroundService(intent);
} else {
context.startService(intent);
}
如果您在Oreo中使用此代码,则在onStartCommand
中有几秒钟的时间来启动前台,否则您的服务将被视为未响应,并可能被用户强制关闭(在Android 8或更高版本中)。
无需使用BroadcastReceiver
在服务关闭后启动服务,只需从您的服务的onStartCommand
返回START_STICKY
或START_REDELIVER_INTENT
即可在服务关闭后重新启动服务。
示例:
public class TemporaryForegroundService extends Service {
public static final int NOTIFICATION_ID = 666;
private static Notification notification;
@Override
public void onCreate() {
super.onCreate();
if(notification == null)
notification = new NotificationCompat.Builder(this, NotificationChannels.importantChannel(this)).
setSmallIcon(R.mipmap.ic_launcher).setContentTitle("The unseen blade").setContentText("If you see me, congrats to you.").build();
startForeground(NOTIFICATION_ID, notification);
startService(new Intent(this, PermanentBackgroundService.class));
stopForeground(true);
stopSelf();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return START_NOT_STICKY;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
public class PermanentBackgroundService extends Service {
private Runnable keepAliveRunnable = new Runnable() {
@Override
public void run() {
keepServiceAlive();
if(handler != null) handler.postDelayed(this, 15*1000);
}
};
private Handler handler;
public void onCreate(){
handler = new Handler();
handler.postDelayed(keepAliveRunnable, 30* 1000);
}
public void onDestroy() {
super.onDestroy();
keepServiceAlive();
}
private void keepServiceAlive() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService(new Intent(PermanentBackgroundService.this, TemporaryForegroundService .class));
} else {
startService(new Intent(PermanentBackgroundService.this, TemporaryForegroundService .class));
}
}
}