为什么在 Android Oreo 屏幕关闭时前台服务会停止?
Why foreground service stops when screen is off on Android Oreo?
Android 当我关闭屏幕时,Oreo 停止了我的前台服务。它发生,当设备被拔掉。我在 Huawei MediaPad T5 上测试我的应用程序。我使用 Handler.postDelayed 每 30 秒发送一次测试请求。
我在 Android 8 中读到了有关后台执行限制的信息。在迁移指南中写道,前台服务应该可以工作。我不能使用 JobScheduler、JobIntenService 或 WorkManager,因为它们只能每 15 分钟重复一次。
我无法使用 Firebase 云消息传递,因为我的应用程序在离线状态下执行部分工作。
我用的也是绑定服务,因为应该没有后台限制。不幸的是,我的应用程序仍然无法正常工作。
我尝试使用 WakeLock,为另一个进程 AlarmManager 提供服务,将我的应用程序添加到白名单,但仍然无法正常工作。
我通过简单的 post 请求在后台测试 运行。我通过 Retrofit Library 连接到测试服务器。
主要活动
private LocalService mService;
private boolean mBound = false;
private Intent mIntent;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
mService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntent = new Intent(this, LocalService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.startForegroundService(getApplicationContext(), mIntent);
}
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
cpuLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kb:wl");
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
cpuLock.acquire();
}
public void onButtonClick(View v) {
if (mBound) {
bindService(mIntent, connection, BIND_AUTO_CREATE);
mService.send();
}
}
@Override
protected void onRestart() {
super.onRestart();
cpuLock.release();
}
本地服务class
public class LocalService extends Service {
private IBinder mBinder = new LocalBinder();
Handler mHandler;
String DEBUG_TAG = "local";
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "some_channel_id";
CharSequence channelName = "Channel La Manche";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, importance);
notificationManager.createNotificationChannel(notificationChannel);
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification =
new Notification.Builder(this, channelId)
.setContentTitle("post title")
.setContentText("post text")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.setTicker("post ticker")
.setOngoing(true)
.build();
startForeground(1, notification);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
mHandler = new Handler();
return mBinder;
}
public void send() {
mHandler.postDelayed(test, 1000);
}
private Runnable test = new Runnable() {
public void run() {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl("https://test.server.url/")
.build();
Post servicePost = retrofit.create(Post.class);
Call<String> request = servicePost.send("");
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
Log.i(DEBUG_TAG, "Code " + response.code());
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i(DEBUG_TAG, "Not connected to server. " + t.getMessage());
}
});
mHandler.postDelayed(test, 30 * 1000);
}
};
Post界面
@Headers("Content-Type: application/json" )
@POST("api/test")
Call<String> send(@Body String empty);
当平板电脑正在充电或未充电且屏幕打开时,应用程序运行完美。即使屏幕关闭,Endomondo 也能正常工作。我做错了什么?
您可以在 this repository 的帮助下解决您的问题。此存储库用于定位,但我相信它会对您有很大帮助。
Android 当我关闭屏幕时,Oreo 停止了我的前台服务。它发生,当设备被拔掉。我在 Huawei MediaPad T5 上测试我的应用程序。我使用 Handler.postDelayed 每 30 秒发送一次测试请求。
我在 Android 8 中读到了有关后台执行限制的信息。在迁移指南中写道,前台服务应该可以工作。我不能使用 JobScheduler、JobIntenService 或 WorkManager,因为它们只能每 15 分钟重复一次。
我无法使用 Firebase 云消息传递,因为我的应用程序在离线状态下执行部分工作。
我用的也是绑定服务,因为应该没有后台限制。不幸的是,我的应用程序仍然无法正常工作。
我尝试使用 WakeLock,为另一个进程 AlarmManager 提供服务,将我的应用程序添加到白名单,但仍然无法正常工作。
我通过简单的 post 请求在后台测试 运行。我通过 Retrofit Library 连接到测试服务器。
主要活动
private LocalService mService;
private boolean mBound = false;
private Intent mIntent;
private ServiceConnection connection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
mService = null;
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mIntent = new Intent(this, LocalService.class);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.startForegroundService(getApplicationContext(), mIntent);
}
PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
cpuLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "kb:wl");
}
@Override
protected void onStart() {
super.onStart();
Intent intent = new Intent(this, LocalService.class);
bindService(intent, connection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
cpuLock.acquire();
}
public void onButtonClick(View v) {
if (mBound) {
bindService(mIntent, connection, BIND_AUTO_CREATE);
mService.send();
}
}
@Override
protected void onRestart() {
super.onRestart();
cpuLock.release();
}
本地服务class
public class LocalService extends Service {
private IBinder mBinder = new LocalBinder();
Handler mHandler;
String DEBUG_TAG = "local";
public class LocalBinder extends Binder {
LocalService getService() {
return LocalService.this;
}
}
public int onStartCommand(Intent intent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onCreate() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationManager notificationManager =
(NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
String channelId = "some_channel_id";
CharSequence channelName = "Channel La Manche";
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(channelId, channelName, importance);
notificationManager.createNotificationChannel(notificationChannel);
Intent notificationIntent = new Intent(this, MainActivity.class);
PendingIntent pendingIntent =
PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification =
new Notification.Builder(this, channelId)
.setContentTitle("post title")
.setContentText("post text")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setContentIntent(pendingIntent)
.setTicker("post ticker")
.setOngoing(true)
.build();
startForeground(1, notification);
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
mHandler = new Handler();
return mBinder;
}
public void send() {
mHandler.postDelayed(test, 1000);
}
private Runnable test = new Runnable() {
public void run() {
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(ScalarsConverterFactory.create())
.baseUrl("https://test.server.url/")
.build();
Post servicePost = retrofit.create(Post.class);
Call<String> request = servicePost.send("");
request.enqueue(new Callback<String>() {
@Override
public void onResponse(@NonNull Call<String> call, @NonNull Response<String> response) {
Log.i(DEBUG_TAG, "Code " + response.code());
}
@Override
public void onFailure(@NonNull Call<String> call, @NonNull Throwable t) {
Log.i(DEBUG_TAG, "Not connected to server. " + t.getMessage());
}
});
mHandler.postDelayed(test, 30 * 1000);
}
};
Post界面
@Headers("Content-Type: application/json" )
@POST("api/test")
Call<String> send(@Body String empty);
当平板电脑正在充电或未充电且屏幕打开时,应用程序运行完美。即使屏幕关闭,Endomondo 也能正常工作。我做错了什么?
您可以在 this repository 的帮助下解决您的问题。此存储库用于定位,但我相信它会对您有很大帮助。