为什么当设备进入睡眠模式时前台服务停止工作
Why does foreground service stop working when device go into sleep mode
我想创建一个不断检查位置变化并将当前位置放入 firebase 的应用程序(例如 运行ners 的应用程序)。
不幸的是,每次设备进入睡眠模式时,前台服务都会停止或暂停。
对于初学者,我想创建一个前台服务,它每秒不断地将信息(可以是时间戳或简单的字符串)写入基础。
一段时间后,它只是停止写入 firebase 而不调用 stopself()。
该服务在模拟器上运行良好(即使进入睡眠状态),但在真实设备上测试时停止 - 在我的例子中是华为,Android 8.1.0。
我应该怎么做才能在设备的每个状态下强制为 运行 提供服务?
My MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startService(intent);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startService(intent);
}
}
}
MyService:
public class MyService extends Service {
int i =0;
private String CHANNEL_ID = "2345";
@Override
public void onCreate() {
super.onCreate();
}
public MyService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1000, createNotification());
String action = intent.getExtras().getString("action");
switch (action){
case "start":
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
myfunction();
handler.postDelayed(this, 1000);
}
};
break;
case "stop":
stopfunction();
break;
}
handler.postDelayed(runnable, 1000);
return START_NOT_STICKY;
}
private void stopfunction() {
stopSelf();
}
private void myfunction() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("locations");
myRef.child("location").setValue(i);
i++;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel(){
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, getString(R.string.infoTxt),
NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(channel);
}
private Notification createNotification(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
createChannel();
}
Intent notificationItent = new Intent(this, MainActivity.class);
notificationItent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationItent, 0);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setColor(ContextCompat.getColor(this, android.R.color.background_dark))
.setContentIntent(intent)
.setSmallIcon(R.drawable.ic_launcher_background)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
.setContentTitle("GPS Location")
.build();
}
}
前台服务一般应用于需要用户注意的任务,例如视觉过程。
使用 Background 服务代替
我已经尝试了所有方法:服务、前台服务、广播接收器、jobSheduler、WorkerManager – 没有任何帮助。然后我发现这是一个新的华为功能,叫做“power-intensive app monitor”。它会杀死 运行 长时间在后台运行的所有应用程序,除非用户授予它特殊权限。
执行此操作的路径:
设置 -> 安全和隐私 -> 位置服务 -> 最近的位置请求:您的应用程序名称 -> 电池 -> 取消选中 Power-intensive 提示,应用程序启动:手动管理:检查所有三个位置:Auto-launch,辅助启动,运行 在后台。
我不知道有没有办法以编程方式执行此操作。我认为最好的方法是创建一种帮助 activity 并向用户解释如果应用程序无法运行该怎么做。
我想创建一个不断检查位置变化并将当前位置放入 firebase 的应用程序(例如 运行ners 的应用程序)。
不幸的是,每次设备进入睡眠模式时,前台服务都会停止或暂停。
对于初学者,我想创建一个前台服务,它每秒不断地将信息(可以是时间戳或简单的字符串)写入基础。 一段时间后,它只是停止写入 firebase 而不调用 stopself()。
该服务在模拟器上运行良好(即使进入睡眠状态),但在真实设备上测试时停止 - 在我的例子中是华为,Android 8.1.0。 我应该怎么做才能在设备的每个状态下强制为 运行 提供服务?
My MainActivity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "start");
startService(intent);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startForegroundService(intent);
}
else {
Intent intent = new Intent(this, MyService.class);
intent.putExtra("action", "stop");
startService(intent);
}
}
}
MyService:
public class MyService extends Service {
int i =0;
private String CHANNEL_ID = "2345";
@Override
public void onCreate() {
super.onCreate();
}
public MyService() {
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
startForeground(1000, createNotification());
String action = intent.getExtras().getString("action");
switch (action){
case "start":
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
@Override
public void run() {
myfunction();
handler.postDelayed(this, 1000);
}
};
break;
case "stop":
stopfunction();
break;
}
handler.postDelayed(runnable, 1000);
return START_NOT_STICKY;
}
private void stopfunction() {
stopSelf();
}
private void myfunction() {
FirebaseDatabase database = FirebaseDatabase.getInstance();
DatabaseReference myRef = database.getReference("locations");
myRef.child("location").setValue(i);
i++;
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return null;
}
@RequiresApi(Build.VERSION_CODES.O)
private void createChannel(){
NotificationManager notificationManager = (NotificationManager) this.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel channel = new NotificationChannel(CHANNEL_ID, getString(R.string.infoTxt),
NotificationManager.IMPORTANCE_HIGH);
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationManager.createNotificationChannel(channel);
}
private Notification createNotification(){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
createChannel();
}
Intent notificationItent = new Intent(this, MainActivity.class);
notificationItent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
PendingIntent intent = PendingIntent.getActivity(this, 0, notificationItent, 0);
return new NotificationCompat.Builder(this, CHANNEL_ID)
.setColor(ContextCompat.getColor(this, android.R.color.background_dark))
.setContentIntent(intent)
.setSmallIcon(R.drawable.ic_launcher_background)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setOnlyAlertOnce(true)
.setContentTitle("GPS Location")
.build();
}
}
前台服务一般应用于需要用户注意的任务,例如视觉过程。 使用 Background 服务代替
我已经尝试了所有方法:服务、前台服务、广播接收器、jobSheduler、WorkerManager – 没有任何帮助。然后我发现这是一个新的华为功能,叫做“power-intensive app monitor”。它会杀死 运行 长时间在后台运行的所有应用程序,除非用户授予它特殊权限。 执行此操作的路径: 设置 -> 安全和隐私 -> 位置服务 -> 最近的位置请求:您的应用程序名称 -> 电池 -> 取消选中 Power-intensive 提示,应用程序启动:手动管理:检查所有三个位置:Auto-launch,辅助启动,运行 在后台。
我不知道有没有办法以编程方式执行此操作。我认为最好的方法是创建一种帮助 activity 并向用户解释如果应用程序无法运行该怎么做。