Skip to content

Commit

Permalink
feat: add flex interval on periodic work request(only android) (#537)
Browse files Browse the repository at this point in the history
* feat: (Only Android) add flex interval

* feat: (Only Android) add flex interval

* feat: (Only Android) add flex interval

---------

Co-authored-by: renan.mirand <[email protected]>
Co-authored-by: Sebastian Roth <[email protected]>
  • Loading branch information
3 people authored Apr 8, 2024
1 parent b783000 commit f470883
Show file tree
Hide file tree
Showing 6 changed files with 58 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.KEYS.REGIST
import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.KEYS.REGISTER_TASK_PAYLOAD_KEY
import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.KEYS.REGISTER_TASK_TAG_KEY
import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.KEYS.REGISTER_TASK_UNIQUE_NAME_KEY
import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.PeriodicTask.KEYS.PERIODIC_FLEX_INTERVAL_SECONDS_KEY
import dev.fluttercommunity.workmanager.WorkManagerCall.RegisterTask.PeriodicTask.KEYS.PERIODIC_TASK_FREQUENCY_SECONDS_KEY
import io.flutter.plugin.common.MethodCall
import kotlin.math.max
Expand All @@ -44,6 +45,8 @@ const val defaultInitialDelaySeconds = 0L
const val defaultRequestedBackoffDelay = 0L
const val defaultPeriodicRefreshFrequencyInSeconds =
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS / 1000
const val defaultFlexIntervalInSeconds =
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS / 1000
const val logTag = "Extractor"

data class BackoffPolicyTaskConfig(
Expand Down Expand Up @@ -114,6 +117,7 @@ sealed class WorkManagerCall {
override val tag: String? = null,
val existingWorkPolicy: ExistingPeriodicWorkPolicy,
val frequencyInSeconds: Long,
val flexIntervalInSeconds: Long,
override val initialDelaySeconds: Long,
override val constraintsConfig: Constraints,
val backoffPolicyConfig: BackoffPolicyTaskConfig?,
Expand All @@ -122,6 +126,7 @@ sealed class WorkManagerCall {
) : RegisterTask() {
companion object KEYS {
const val PERIODIC_TASK_FREQUENCY_SECONDS_KEY = "frequency"
const val PERIODIC_FLEX_INTERVAL_SECONDS_KEY = "flexInterval"
}
}
}
Expand Down Expand Up @@ -210,6 +215,7 @@ object Extractor {
taskName = call.argument<String>(REGISTER_TASK_NAME_VALUE_KEY)!!,
frequencyInSeconds = extractFrequencySecondsFromCall(call),
tag = call.argument<String>(REGISTER_TASK_TAG_KEY),
flexIntervalInSeconds =extractFlexIntervalSecondsFromCall(call) ,
existingWorkPolicy = extractExistingPeriodicWorkPolicyFromCall(call),
initialDelaySeconds = extractInitialDelayFromCall(call),
constraintsConfig = extractConstraintConfigFromCall(call),
Expand Down Expand Up @@ -259,6 +265,10 @@ object Extractor {
call.argument<Int>(PERIODIC_TASK_FREQUENCY_SECONDS_KEY)?.toLong()
?: defaultPeriodicRefreshFrequencyInSeconds

private fun extractFlexIntervalSecondsFromCall(call: MethodCall) =
call.argument<Int>(PERIODIC_FLEX_INTERVAL_SECONDS_KEY)?.toLong()
?: defaultFlexIntervalInSeconds

private fun extractInitialDelayFromCall(call: MethodCall) =
call.argument<Int>(REGISTER_TASK_INITIAL_DELAY_SECONDS_KEY)?.toLong()
?: defaultInitialDelaySeconds
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ private object RegisterTaskHandler : CallHandler<WorkManagerCall.RegisterTask> {
uniqueName = convertedCall.uniqueName,
dartTask = convertedCall.taskName,
tag = convertedCall.tag,
flexIntervalInSeconds = convertedCall.flexIntervalInSeconds,
frequencyInSeconds = convertedCall.frequencyInSeconds,
isInDebugMode = convertedCall.isInDebugMode,
existingWorkPolicy = convertedCall.existingWorkPolicy,
Expand Down Expand Up @@ -220,6 +221,7 @@ object WM {
payload: String? = null,
tag: String? = null,
frequencyInSeconds: Long = defaultPeriodicRefreshFrequencyInSeconds,
flexIntervalInSeconds:Long = defaultFlexIntervalInSeconds,
isInDebugMode: Boolean = false,
existingWorkPolicy: ExistingPeriodicWorkPolicy = defaultPeriodExistingWorkPolicy,
initialDelaySeconds: Long = defaultInitialDelaySeconds,
Expand All @@ -231,6 +233,8 @@ object WM {
PeriodicWorkRequest.Builder(
BackgroundWorker::class.java,
frequencyInSeconds,
TimeUnit.SECONDS,
flexIntervalInSeconds,
TimeUnit.SECONDS
)
.setInputData(buildTaskInputData(dartTask, isInDebugMode, payload))
Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ class _MyAppState extends State<MyApp> {
Workmanager().registerPeriodicTask(
simplePeriodic1HourTask,
simplePeriodic1HourTask,
flexInterval: Duration(minutes: 15),
frequency: Duration(hours: 1),
);
}
Expand Down
8 changes: 8 additions & 0 deletions lib/src/workmanager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ class Workmanager {
/// The [taskName] is the value that will be returned in the [BackgroundTaskHandler], ignored on iOS where you should use [uniqueName].
/// a [frequency] is not required and will be defaulted to 15 minutes if not provided.
/// a [frequency] has a minimum of 15 min. Android will automatically change your frequency to 15 min if you have configured a lower frequency.
/// the [flexInterval] If the nature of the work is time-sensitive, you can configure the PeriodicWorkRequest to run in a flexible period at each interval.
/// https://developer.android.com/develop/background-work/background-tasks/persistent/getting-started/define-work?hl=pt-br#flexible_run_intervals
/// The [inputData] is the input data for task. Valid value types are: int, bool, double, String and their list
/// Unlike Android, you cannot set [frequency] for iOS here rather you have to set in `AppDelegate.swift` while registering the task.
/// The [inputData] is the input data for task. Valid value types are: int, bool, double, String and their list. It is not supported on iOS.
///
Expand All @@ -242,6 +246,7 @@ class Workmanager {
final String uniqueName,
final String taskName, {
final Duration? frequency,
final Duration? flexInterval,
final String? tag,
final ExistingWorkPolicy? existingWorkPolicy,
final Duration initialDelay = Duration.zero,
Expand All @@ -258,6 +263,7 @@ class Workmanager {
uniqueName: uniqueName,
taskName: taskName,
frequency: frequency,
flexInterval: flexInterval,
tag: tag,
existingWorkPolicy: existingWorkPolicy,
initialDelay: initialDelay,
Expand Down Expand Up @@ -371,6 +377,7 @@ class JsonMapperHelper {
final String? uniqueName,
final String? taskName,
final Duration? frequency,
final Duration? flexInterval,
final String? tag,
final ExistingWorkPolicy? existingWorkPolicy,
final Duration? initialDelay,
Expand Down Expand Up @@ -406,6 +413,7 @@ class JsonMapperHelper {
"taskName": taskName,
"tag": tag,
"frequency": frequency?.inSeconds,
"flexInterval":flexInterval?.inSeconds,
"existingWorkPolicy": _enumToString(existingWorkPolicy),
"initialDelaySeconds": initialDelay?.inSeconds,
"networkType": _enumToString(constraints?.networkType),
Expand Down
18 changes: 18 additions & 0 deletions test/json_mapper_helper_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ void main() {
'uniqueName': 'uniqueName',
'taskName': 'taskName',
'tag': null,
'flexInterval':null,
'frequency': null,
'existingWorkPolicy': null,
'initialDelaySeconds': null,
Expand Down Expand Up @@ -79,6 +80,7 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,
'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': null,
Expand Down Expand Up @@ -111,6 +113,7 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,
'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': null,
Expand All @@ -132,6 +135,7 @@ void main() {
uniqueName: "uniqueName",
taskName: "taskName",
frequency: Duration(seconds: 1),
flexInterval: Duration(seconds: 1),
tag: "tag",
existingWorkPolicy: ExistingWorkPolicy.replace,
initialDelay: Duration(seconds: 2),
Expand All @@ -152,6 +156,7 @@ void main() {
'taskName': 'taskName',
'tag': 'tag',
'frequency': 1,
'flexInterval': 1,
'existingWorkPolicy': 'replace',
'initialDelaySeconds': 2,
'networkType': 'connected',
Expand Down Expand Up @@ -183,6 +188,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': 'connected',
Expand Down Expand Up @@ -210,6 +217,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': 'metered',
Expand All @@ -231,6 +240,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': 'metered',
Expand Down Expand Up @@ -258,6 +269,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': 'not_roaming',
Expand Down Expand Up @@ -285,6 +298,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': 'unmetered',
Expand Down Expand Up @@ -338,6 +353,8 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,

'existingWorkPolicy': existingWorkPolicy[1],
'initialDelaySeconds': 1,
'networkType': null,
Expand Down Expand Up @@ -374,6 +391,7 @@ void main() {
'taskName': 'taskName',
'tag': null,
'frequency': null,
'flexInterval': null,
'existingWorkPolicy': null,
'initialDelaySeconds': 1,
'networkType': null,
Expand Down
36 changes: 17 additions & 19 deletions test/workmanager_test.mocks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,13 @@ class MockWorkmanager extends _i1.Mock implements _i2.Workmanager {

@override
void executeTask(_i2.BackgroundTaskHandler? backgroundTask) =>
super.noSuchMethod(Invocation.method(#executeTask, [backgroundTask]),
returnValueForMissingStub: null);
super.noSuchMethod(Invocation.method(#executeTask, [backgroundTask]), returnValueForMissingStub: null);

@override
_i3.Future<void> initialize(Function? callbackDispatcher,
{bool? isInDebugMode = false}) =>
(super.noSuchMethod(
Invocation.method(#initialize, [callbackDispatcher],
{#isInDebugMode: isInDebugMode}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);
_i3.Future<void> initialize(Function? callbackDispatcher, {bool? isInDebugMode = false}) =>
(super.noSuchMethod(Invocation.method(#initialize, [callbackDispatcher], {#isInDebugMode: isInDebugMode}),
returnValue: Future<void>.value(), returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);

@override
_i3.Future<void> registerOneOffTask(String? uniqueName, String? taskName,
{String? tag,
Expand All @@ -63,9 +60,11 @@ class MockWorkmanager extends _i1.Mock implements _i2.Workmanager {
}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);

@override
_i3.Future<void> registerPeriodicTask(String? uniqueName, String? taskName,
{Duration? frequency,
Duration? flexInterval,
String? tag,
_i4.ExistingWorkPolicy? existingWorkPolicy,
Duration? initialDelay = Duration.zero,
Expand All @@ -91,19 +90,18 @@ class MockWorkmanager extends _i1.Mock implements _i2.Workmanager {
}),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);

@override
_i3.Future<void> cancelByUniqueName(String? uniqueName) =>
(super.noSuchMethod(Invocation.method(#cancelByUniqueName, [uniqueName]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);
_i3.Future<void> cancelByUniqueName(String? uniqueName) => (super.noSuchMethod(Invocation.method(#cancelByUniqueName, [uniqueName]),
returnValue: Future<void>.value(), returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);

@override
_i3.Future<void> cancelByTag(String? tag) =>
(super.noSuchMethod(Invocation.method(#cancelByTag, [tag]),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);
(super.noSuchMethod(Invocation.method(#cancelByTag, [tag]), returnValue: Future<void>.value(), returnValueForMissingStub: Future<void>.value())
as _i3.Future<void>);

@override
_i3.Future<void> cancelAll() =>
(super.noSuchMethod(Invocation.method(#cancelAll, []),
returnValue: Future<void>.value(),
returnValueForMissingStub: Future<void>.value()) as _i3.Future<void>);
(super.noSuchMethod(Invocation.method(#cancelAll, []), returnValue: Future<void>.value(), returnValueForMissingStub: Future<void>.value())
as _i3.Future<void>);
}

0 comments on commit f470883

Please sign in to comment.