簡體   English   中英

后台服務沒有運行可能是因為打盹模式

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM