WorkManager 只需要在特定的时间间隔内工作,如何使用工作管理器约束?工作管理器示例
WorkManager need to work only in between particular time interval, how to use work manager constraints ? Work manager example
我是第一次使用 Work Manager,我已经成功实施了它。
我每 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();
}
}
启动工人代码:
PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, repeatInterval, TimeUnit.MINUTES)
.addTag("Location")
.build();
WorkManager.getInstance().enqueueUniquePeriodicWork("Location", ExistingPeriodicWorkPolicy.REPLACE, periodicWork);
每天晚上有什么特别的方法可以停止吗?
我们将不胜感激。
如果您想在特定时间执行某项操作,您可以像这样使用 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
class :
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);
}
}
并且不要忘记在清单中添加接收器(在应用程序标签内):
<receiver android:name=".AutoLogoutIntentReceiver" />
有关警报管理器的更多信息,请查看此 link
希望对您有所帮助!
您不能暂停 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();
}
我会使用两个 Worker。首先是管理,其次是获取位置。首先会定期工作——每 24 小时在晚上工作。它会停止 LocationService 并延迟再次调用它。
您可以每天早上启动 OneTimeRequest worker,这会触发您的 LocationGathering 的 PeriodicWorkRequest。并添加时间检查
//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;
}
还检查 periodicWorkRequest 的状态,如果未安排则触发/运行 在 OneTimeRequest doWork()
最后但并非最不重要的一点是检查 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;
}
}
我是第一次使用 Work Manager,我已经成功实施了它。
我每 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();
}
}
启动工人代码:
PeriodicWorkRequest periodicWork = new PeriodicWorkRequest.Builder(MyWorker.class, repeatInterval, TimeUnit.MINUTES)
.addTag("Location")
.build();
WorkManager.getInstance().enqueueUniquePeriodicWork("Location", ExistingPeriodicWorkPolicy.REPLACE, periodicWork);
每天晚上有什么特别的方法可以停止吗?
我们将不胜感激。
如果您想在特定时间执行某项操作,您可以像这样使用 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
class :
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);
}
}
并且不要忘记在清单中添加接收器(在应用程序标签内):
<receiver android:name=".AutoLogoutIntentReceiver" />
有关警报管理器的更多信息,请查看此 link
希望对您有所帮助!
您不能暂停 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();
}
我会使用两个 Worker。首先是管理,其次是获取位置。首先会定期工作——每 24 小时在晚上工作。它会停止 LocationService 并延迟再次调用它。
您可以每天早上启动 OneTimeRequest worker,这会触发您的 LocationGathering 的 PeriodicWorkRequest。并添加时间检查
//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;
}
还检查 periodicWorkRequest 的状态,如果未安排则触发/运行 在 OneTimeRequest doWork()
最后但并非最不重要的一点是检查 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;
}
}