[英]Background service not running may be because of doze mode
我想在晚上 11:59 准確地在服務器上上傳一些數據。 這次我想收集數據,只要有互聯網,它就應該上傳數據。 首選是使用WorkManager
但是,我無法將其設置在確切的時間。 對於確切的時間,我們必須使用AlarmManager
並且我們必須為互聯網實現我們自己的邏輯或廣播接收器。
所以,我設置OneTimeWorkRequest
此使用AlarmManager。 但問題是它不能在后台工作並且當應用程序在前台時工作正常。
顯現
<service android:name=".Home.services.WorkerService"
android:enabled="true"
android:exported="true"/>
從片段啟動服務
private void setUpService(){
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.HOUR_OF_DAY,23);
calendar.set(Calendar.MINUTE,59);
Intent intent = new Intent(getActivity(), WorkerService.class);
PendingIntent pendingIntent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) pendingIntent = PendingIntent.getForegroundService(getActivity(),0,intent,0);
else pendingIntent = PendingIntent.getService(getActivity(),0,intent,0);
AlarmManager alarmManager = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE);
assert alarmManager != null;
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,calendar.getTimeInMillis(),AlarmManager.INTERVAL_DAY,pendingIntent);
}
工作服務
public class WorkerService extends Service {
AppDatabase database;
@Override
public void onCreate() {
super.onCreate();
database = AppDatabase.getInstance(this);
readSteps();
Constraints constraints = new Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build();
int user_id = database.getUserDao().getSuperUser().id;
Date date = new Date();
String formattedDate = String.valueOf(DateFormat.format("yyyy-MM-dd",date));
float steps = database.getFitnessDao().getDateData(date,user_id).getSteps();
Data data = new Data.Builder()
.putInt("user_id",user_id)
.putString("date",formattedDate)
.putFloat("steps",steps)
.build();
OneTimeWorkRequest oneTimeWorkRequest = new OneTimeWorkRequest.Builder(StepWorker.class)
.setConstraints(constraints)
.setInputData(data)
.build();
WorkManager.getInstance(this).enqueue(oneTimeWorkRequest);
}
private void readSteps(){
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener(dataSet -> {
int super_user = database.getUserDao().getSuperUser().id;
float total = dataSet.isEmpty() ? 0 : dataSet.getDataPoints().get(0).getValue(Field.FIELD_STEPS).asInt();
database.getFitnessDao().updateSteps(super_user,total,new Date());
})
.addOnFailureListener(e -> {
});
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
}
除非您被 Doze 列入白名單,否則沒有什么可以讓您選擇確切的時間。 這必須由用戶完成,而不是應用程序。 警報和工作管理器都受它影響。 如果在應該完成鬧鍾或工作時手機處於關閉狀態,並且應用程序未列入白名單,則它將等待下一個打盹窗口。
您需要修改您的服務類WorkerService
以在后台連續運行它我已經編輯了您的服務類,請使用它
public class WorkerService extends Service {
AppDatabase database;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
database = AppDatabase.getInstance(this);
readSteps();
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
// check here the device current time is equal to 11:59 Pm or not
// run your code if current current time is equal to 11:59
handler.postDelayed(this, 30000);
}
}, 30000); // every 30 seconds
return START_STICKY;
}
private void readSteps(){
Fitness.getHistoryClient(this, GoogleSignIn.getLastSignedInAccount(this))
.readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA)
.addOnSuccessListener(dataSet -> {
int super_user = database.getUserDao().getSuperUser().id;
float total = dataSet.isEmpty() ? 0 : dataSet.getDataPoints().get(0).getValue(Field.FIELD_STEPS).asInt();
database.getFitnessDao().updateSteps(super_user,total,new Date());
})
.addOnFailureListener(e -> {
});
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startMyOwnForeground();
} else {
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "1");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(1, notification);
}
}
@RequiresApi(api = Build.VERSION_CODES.O)
private void startMyOwnForeground() {
String channelName = "BackgroundService";
NotificationChannel chan = new NotificationChannel("2", channelName, NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
assert manager != null;
manager.createNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "2");
Notification notification = notificationBuilder.setOngoing(true)
.setSmallIcon(R.mipmap.ic_launcher)
.setPriority(NotificationManager.IMPORTANCE_MIN)
.setCategory(Notification.CATEGORY_SERVICE)
.build();
startForeground(2, notification);
}
@Override
public void onTaskRemoved(Intent rootIntent) {
Intent restartServiceIntent = new Intent(getApplicationContext(), this.getClass());
restartServiceIntent.setPackage(getPackageName());
PendingIntent restartServicePendingIntent = PendingIntent.getService(getApplicationContext(), 1, restartServiceIntent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmService = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
alarmService.set(
AlarmManager.ELAPSED_REALTIME,
SystemClock.elapsedRealtime() + 1000,
restartServicePendingIntent);
super.onTaskRemoved(rootIntent);
}
}
現在像這樣在片段中啟動服務
startService(new Intent(context, WorkerService.class));
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.