Android WorkManager只需要在特定的时间间隔之间工作,如何使用WorkManager约束?工作经理示例

Android WorkManager只需要在特定的时间间隔之间工作,如何使用WorkManager约束?工作经理示例,android,location,alarmmanager,android-workmanager,workmanagers,Android,Location,Alarmmanager,Android Workmanager,Workmanagers,我是第一次和工作经理一起工作,我已经成功地实施了它 我每30分钟进行一次定位以跟踪员工 当数据库第一次同步时,我启动了我的工作经理,但我想在每天晚上停止它。 这里是MyWorker.java public class MyWorker extends Worker { private static final String TAG = "MyWorker"; /** * The desired interval for location updates. Inexac

我是第一次和工作经理一起工作,我已经成功地实施了它

我每30分钟进行一次定位以跟踪员工

当数据库第一次同步时,我启动了我的工作经理,但我想在每天晚上停止它。

这里是MyWorker.java

public class MyWorker extends Worker {

    private static final String TAG = "MyWorker";
    /**
     * The desired interval for location updates. Inexact. Updates may be more or less frequent.
     */
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
    /**
     * The fastest rate for active location updates. Updates will never be more frequent
     * than this value.
     */
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS =
            UPDATE_INTERVAL_IN_MILLISECONDS / 2;
    /**
     * The current location.
     */
    private Location mLocation;
    /**
     * Provides access to the Fused Location Provider API.
     */
    private FusedLocationProviderClient mFusedLocationClient;

    private Context mContext;

    private String fromRegRegCode, fromRegMobile, fromRegGUID, fromRegImei, clientIP;

    /**
     * Callback for changes in location.
     */
    private LocationCallback mLocationCallback;

    public MyWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) {
        super(context, workerParams);
        mContext = context;
    }

    @NonNull
    @Override
    public Result doWork() {
        Log.d(TAG, "doWork: Done");
        //mContext.startService(new Intent(mContext, LocationUpdatesService.class));
        Log.d(TAG, "onStartJob: STARTING JOB..");
        mFusedLocationClient = LocationServices.getFusedLocationProviderClient(mContext);

        mLocationCallback = new LocationCallback() {
            @Override
            public void onLocationResult(LocationResult locationResult) {
                super.onLocationResult(locationResult);
            }
        };

        LocationRequest mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);

        try {
            mFusedLocationClient
                    .getLastLocation()
                    .addOnCompleteListener(new OnCompleteListener<Location>() {
                        @Override
                        public void onComplete(@NonNull Task<Location> task) {
                            if (task.isSuccessful() && task.getResult() != null) {
                                mLocation = task.getResult();

                                String currentTime = CommonUses.getDateToStoreInLocation();
                                String mLatitude = String.valueOf(mLocation.getLatitude());
                                String mLongitude = String.valueOf(mLocation.getLongitude());

                                LocationHistoryTable table = new LocationHistoryTable();
                                table.setLatitude(mLatitude);
                                table.setLongitude(mLongitude);
                                table.setUpdateTime(currentTime);
                                table.setIsUploaded(CommonUses.PENDING);

                                LocationHistoryTableDao tableDao = SohamApplication.daoSession.getLocationHistoryTableDao();
                                tableDao.insert(table);

                                Log.d(TAG, "Location : " + mLocation);
                                mFusedLocationClient.removeLocationUpdates(mLocationCallback);

                                /**
                                 * Upload on server if network available
                                 */
                                if (Util.isNetworkAvailable(mContext)) {
                                    checkForServerIsUP();
                                }

                            } else {
                                Log.w(TAG, "Failed to get location.");
                            }
                        }
                    });
        } catch (SecurityException unlikely) {
            Log.e(TAG, "Lost location permission." + unlikely);
        }

        try {
            mFusedLocationClient.requestLocationUpdates(mLocationRequest,
                    null);
        } catch (SecurityException unlikely) {
            //Utils.setRequestingLocationUpdates(this, false);
            Log.e(TAG, "Lost location permission. Could not request updates. " + unlikely);
        }
        return Result.success();
    }
}
每天晚上有什么特别的方法可以阻止它吗?


非常感谢您的帮助。

如果您想在特定时间执行某些操作,可以使用
AlarmManager
如下:

Intent alaramIntent = new Intent(LoginActivity.this, AutoLogoutIntentReceiver.class);
    alaramIntent.setAction("LogOutAction");
    Log.e("MethodCall","AutoLogOutCall");
    alaramIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES);
    PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, alaramIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.set(Calendar.HOUR_OF_DAY, 18);
    calendar.set(Calendar.MINUTE, 01);
    calendar.set(Calendar.SECOND, 0);
    AlarmManager alarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);

    Log.e("Logout", "Auto Logout set at..!" + calendar.getTime());
    alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);
创建一个
BroadcastReceiver
类:

public class AutoLogoutIntentReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(final Context context, Intent intent)
    {

        if("LogOutAction".equals(intent.getAction())){

            Log.e("LogOutAuto", intent.getAction());


            //Stops the visit tracking service
            Intent stopIntent = new Intent(context, VisitTrackingService.class);
            stopIntent.setAction(VisitTrackingService.ACTION_STOP_FOREGROUND_SERVICE);
            context.startService(stopIntent);

            //logs user out of the app and closes it
            SharedPrefManager.getInstance(context).logout();
            exit(context);

        }
    }
别忘了在清单(应用程序标记内部)中添加接收者:


有关报警管理器的更多信息,请检查此项


希望这有帮助

您不能暂停PeriodicWorkRequest,唯一的选择是必须取消该请求

解决方案:最好将条件检查添加到dowork()方法中,无论当前系统时间是在下午6点到早上6点之间,都不要做任何其他事情,这样做您的工作您必须添加条件检查


或者,您可以使用报警管理器在指定的时间启动服务,然后在指定的时间间隔内重复报警。当警报响起时,您可以启动服务并连接到服务器并制作您想要的您不能在一段时间内停止Workmanager

下面是技巧,只需在
doWork()
方法中添加此条件

基本上,你需要检查当前时间(如果是的话是晚上还是晚上)不执行任务

Calendar c = Calendar.getInstance();
int timeOfDay = c.get(Calendar.HOUR_OF_DAY);
 if(timeOfDay >= 16 && timeOfDay < 21){
    // this condition for evening time and call return here
     return Result.success();
}
else if(timeOfDay >= 21 && timeOfDay < 24){
    // this condition for night time and return success 
      return Result.success();
}
Calendar c=Calendar.getInstance();
int timeOfDay=c.get(日历小时);
如果(时间间隔>=16和时间间隔<21){
//此条件适用于夜间,并在此处呼叫返回
返回Result.success();
}
否则,如果(时间间隔>=21&&timeOfDay<24){
//此条件适用于夜间和返回成功
返回Result.success();
}

我会用两个工人。首先是管理,其次是获取位置。第一个是定期工作——晚上每24小时一次。它将停止LocationService并延迟再次调用它

您可以每天早上启动一个TimeRequest worker,这将触发您的LocationGathering周期性工作请求。并添加一个时间检查

 //Set initial delay for next OneTimeRequest in DoWork() method which can be calculated as
 public static int initialDelay(){
        int initialDelayMinutes = 0;
        try {

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");

            Calendar currentDate = Calendar.getInstance();
            Calendar dueDate = Calendar.getInstance();

            // Set Execution around 09:00:00 AM
           dueDate.set(Calendar.DAY_OF_MONTH,currentDate.get(Calendar.DAY_OF_MONTH));
            dueDate.set(Calendar.MONTH,currentDate.get(Calendar.MONTH));
            dueDate.set(Calendar.YEAR,currentDate.get(Calendar.YEAR));
            dueDate.set(Calendar.HOUR_OF_DAY, ChannelierConstants.AUTO_SYNC_TIMING.DAY_START.getType());
            dueDate.set(Calendar.MINUTE, 0);
            dueDate.set(Calendar.SECOND, 0);

            int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);
            int dueDateHour = dueDate.get(Calendar.HOUR_OF_DAY);
            int currentDateMinutes = currentDate.get(Calendar.MINUTE);

            //MyUtils.createLog("DUE HOUR "+dueDateHour,"CURRENT HOuR "+currentDateHour+"\t current minutes is "+currentDateMinutes);
            int diff = Math.abs(dueDateHour - currentDateHour);

            //MyUtils.createLog("HOUR DIFF --  "+diff,"24-diff is "+Math.abs(24 - diff));
            if (dueDate.before(currentDate)) {
                currentDate.add(Calendar.HOUR_OF_DAY, Math.abs(24-diff));
                initialDelayMinutes = ((Math.abs(24 - diff)) * 60) +currentDateMinutes;
            }else {
                initialDelayMinutes = 60 - currentDateMinutes;
            }


            createLog("MINUTES "+initialDelayMinutes,"DUE DATE +"+simpleDateFormat.format(currentDate.getTimeInMillis()));

        }catch (Exception ex){
            ex.printStackTrace();
        }
        return initialDelayMinutes;
    }


如果未在OneTimeRequest doWork()中计划/运行,还应检查periodicWorkRequest和触发器的状态

最后但并非最不重要的一点是检查PeriodicWorkRequest中的当前时间,如果超过结束位置跟踪工作的所需时间,则取消工作

  /**
     * This method is used to cancel periodic autosync if current time is before/ after the mentioned sync time
     * */
    public static boolean shouldCancelPeriodicAutoSync(String wrokerTAG,Context context) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int HOUR_OF_DAY = calendar.get(Calendar.HOUR_OF_DAY);
        createLog("HOUR OF DAY","--> "+HOUR_OF_DAY);
        if (HOUR_OF_DAY > ChannelierConstants.AUTO_SYNC_TIMING.DAY_START.getType() && HOUR_OF_DAY < ChannelierConstants.AUTO_SYNC_TIMING.DAY_END.getType()){
            return true;
        }else {
            createLog("Cancelling Periodic Sync ",""+wrokerTAG);
            WorkManager.getInstance(context).cancelUniqueWork(wrokerTAG);
            return false;
        }
    }

/**
*如果当前时间在所述同步时间之前/之后,此方法用于取消定期自动同步
* */
公共静态布尔值shouldCancelPeriodicAutoSync(字符串wrokerTAG,上下文){
SimpleDataFormat SimpleDataFormat=新的SimpleDataFormat(“yyy-MM-dd-HH:MM:ss”);
日历=Calendar.getInstance();
calendar.setTime(新日期());
int HOUR\u OF_DAY=calendar.get(calendar.HOUR\u OF_DAY);
createLog(“一天中的小时”,“-->”+一天中的小时);
if(HOUR_OF_DAY>ChannelierConstants.AUTO_SYNC_TIMING.DAY_START.getType()&&HOUR_OF_DAY
它是否适用于所有设备?必须是安卓奥利奥或派乐谢谢你的想法。特别感谢您提供的代码片段。我很高兴能帮助您,请尝试以下答案此解决方案的主要问题是,即使不需要,您也要运行doWork()方法。一个更好的解决方案是检查doWork()中的时间,如果它超出了您想要的范围,您可以安排一个新的PeriodicWorkRequest,初始延迟(需要v2.1-alpha02)并返回失败。WorkManager将负责取消当前的工作请求,您设置的延迟到期后,您的工作人员将在下次执行。如果您有任何疑问,请告诉我。
 //Set initial delay for next OneTimeRequest in DoWork() method which can be calculated as
 public static int initialDelay(){
        int initialDelayMinutes = 0;
        try {

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");

            Calendar currentDate = Calendar.getInstance();
            Calendar dueDate = Calendar.getInstance();

            // Set Execution around 09:00:00 AM
           dueDate.set(Calendar.DAY_OF_MONTH,currentDate.get(Calendar.DAY_OF_MONTH));
            dueDate.set(Calendar.MONTH,currentDate.get(Calendar.MONTH));
            dueDate.set(Calendar.YEAR,currentDate.get(Calendar.YEAR));
            dueDate.set(Calendar.HOUR_OF_DAY, ChannelierConstants.AUTO_SYNC_TIMING.DAY_START.getType());
            dueDate.set(Calendar.MINUTE, 0);
            dueDate.set(Calendar.SECOND, 0);

            int currentDateHour = currentDate.get(Calendar.HOUR_OF_DAY);
            int dueDateHour = dueDate.get(Calendar.HOUR_OF_DAY);
            int currentDateMinutes = currentDate.get(Calendar.MINUTE);

            //MyUtils.createLog("DUE HOUR "+dueDateHour,"CURRENT HOuR "+currentDateHour+"\t current minutes is "+currentDateMinutes);
            int diff = Math.abs(dueDateHour - currentDateHour);

            //MyUtils.createLog("HOUR DIFF --  "+diff,"24-diff is "+Math.abs(24 - diff));
            if (dueDate.before(currentDate)) {
                currentDate.add(Calendar.HOUR_OF_DAY, Math.abs(24-diff));
                initialDelayMinutes = ((Math.abs(24 - diff)) * 60) +currentDateMinutes;
            }else {
                initialDelayMinutes = 60 - currentDateMinutes;
            }


            createLog("MINUTES "+initialDelayMinutes,"DUE DATE +"+simpleDateFormat.format(currentDate.getTimeInMillis()));

        }catch (Exception ex){
            ex.printStackTrace();
        }
        return initialDelayMinutes;
    }


  /**
     * This method is used to cancel periodic autosync if current time is before/ after the mentioned sync time
     * */
    public static boolean shouldCancelPeriodicAutoSync(String wrokerTAG,Context context) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyy-MM-dd HH:mm:ss");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        int HOUR_OF_DAY = calendar.get(Calendar.HOUR_OF_DAY);
        createLog("HOUR OF DAY","--> "+HOUR_OF_DAY);
        if (HOUR_OF_DAY > ChannelierConstants.AUTO_SYNC_TIMING.DAY_START.getType() && HOUR_OF_DAY < ChannelierConstants.AUTO_SYNC_TIMING.DAY_END.getType()){
            return true;
        }else {
            createLog("Cancelling Periodic Sync ",""+wrokerTAG);
            WorkManager.getInstance(context).cancelUniqueWork(wrokerTAG);
            return false;
        }
    }