Skip to content

Commit 01e93fd

Browse files
authored
[Feature][ios] Allow to define custom task (#331)
* - add try-catch to avoid app fail to function when cannot cancel a task * - [ios] allows to register custom task id * - Remoe unnecessary try-catch - Combinie Info.plist files * - remove PlatformEnabledButton * - disable periodic tasks for iOS * - Add more readme * - move iOS setup to its dedicated file * - upgrade build_runner package * - fix UT failed * - add public API doc comment - revise SETUP note
1 parent 6fc6397 commit 01e93fd

File tree

11 files changed

+203
-225
lines changed

11 files changed

+203
-225
lines changed

IOS_SETUP.md

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,20 @@ This will add the **UIBackgroundModes** key to your project's `Info.plist`:
2222
</array>
2323
```
2424

25-
Additionally, you must configure the background task identifiers. The default identifier is `workmanager.background.task` in the host Apps Info.plist:
25+
You **MUST** amend your `AppDelegate.swift` and `Info.plist` file to register your task ID.
2626

27+
- AppDelegate.swift
28+
``` swift
29+
WorkmanagerPlugin.registerTask(withIdentifier: "task-identifier")
30+
```
31+
32+
- Info.plist
2733
``` xml
2834
<key>BGTaskSchedulerPermittedIdentifiers</key>
29-
<array>
30-
<string>workmanager.background.task</string>
31-
</array>
32-
</plist>
35+
<array>
36+
<string>task-identifier</string>
37+
</array>
38+
</key>
3339
```
3440

3541
And will set the correct *SystemCapabilities* for your target in the `project.pbxproj` file:

README.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ void main() {
3535
callbackDispatcher, // The top level function, aka callbackDispatcher
3636
isInDebugMode: true // If enabled it will post a notification whenever the task is running. Handy for debugging tasks
3737
);
38-
Workmanager().registerOneOffTask("1", "simpleTask"); //Android only (see below)
38+
Workmanager().registerOneOffTask("task-identifier", "simpleTask");
3939
runApp(MyApp());
4040
}
4141
```
@@ -68,7 +68,10 @@ void callbackDispatcher() {
6868
}
6969
```
7070

71-
Android tasks are identified using their `taskName`, whereas two default constants are provided for iOS background operations, depending on whether background fetch or BGTaskScheduler is used: `Workmanager.iOSBackgroundTask` & `Workmanager.iOSBackgroundProcessingTask`.
71+
Android tasks are identified using their `taskName`.
72+
iOS tasks are identitied using their `taskIdentifier`.
73+
74+
However, there is an exception for iOS background fetch: `Workmanager.iOSBackgroundTask`, a constant for iOS background fetch task.
7275

7376
---
7477

@@ -84,13 +87,13 @@ On Android, the `BackoffPolicy` will configure how `WorkManager` is going to ret
8487

8588
Refer to the example app for a successful, retrying and a failed task.
8689

87-
# Customisation (iOS - BGTaskScheduler only)
90+
# iOS speicific setup and note
8891

8992
iOS supports **One off tasks** with a few basic constraints:
9093

9194
```dart
9295
Workmanager().registerOneOffTask(
93-
"1", // Ignored on iOS
96+
"task-identifier",
9497
simpleTaskKey, // Ignored on iOS
9598
initialDelay: Duration(minutes: 30),
9699
constraints: Constraints(
@@ -103,8 +106,6 @@ Workmanager().registerOneOffTask(
103106
);
104107
```
105108

106-
Tasks registered this way will appear in the callback dispatcher using as `Workmanager.iOSBackgroundProcessingTask`.
107-
108109
For more information see the [BGTaskScheduler documentation](https://developer.apple.com/documentation/backgroundtasks).
109110

110111
# Customisation (Android)
@@ -119,14 +120,14 @@ Two kinds of background tasks can be registered :
119120
```dart
120121
// One off task registration
121122
Workmanager().registerOneOffTask(
122-
"1",
123+
"oneoff-task-identifier",
123124
"simpleTask"
124125
);
125126
126127
// Periodic task registration
127128
Workmanager().registerPeriodicTask(
128-
"2",
129-
"simplePeriodicTask",
129+
"periodic-task-identifier",
130+
"simplePeriodicTask",
130131
// When no frequency is provided the default 15 minutes is set.
131132
// Minimum frequency is 15 min. Android will automatically change your frequency to 15 min if you have configured a lower frequency.
132133
frequency: Duration(hours: 1),

example/integration_test/workmanager_integration_test.dart

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,21 @@ void main() {
1818
(WidgetTester tester) async {
1919
final wm = Workmanager();
2020
await wm.initialize(callbackDispatcher);
21-
await wm.registerOneOffTask('taskId', 'taskName');
21+
await wm.registerOneOffTask(
22+
'be.tramckrijte.workmanagerExample.taskId',
23+
'taskName',
24+
);
2225
}, skip: !Platform.isAndroid);
2326

2427
testWidgets('initialize & schedule task - iOS', (WidgetTester tester) async {
2528
final wm = Workmanager();
2629
await wm.initialize(callbackDispatcher);
2730
try {
28-
await wm.registerOneOffTask('taskId', 'taskName');
31+
await wm.registerOneOffTask(
32+
'be.tramckrijte.workmanagerExample.taskId',
33+
'taskName',
34+
);
35+
await wm.cancelAll();
2936
} on PlatformException catch (e) {
3037
if (e.code !=
3138
'bgTaskSchedulingFailed(Error Domain=BGTaskSchedulerErrorDomain Code=1 "(null)") error') {
@@ -52,8 +59,13 @@ void main() {
5259
final wm = Workmanager();
5360
await wm.initialize(callbackDispatcher);
5461
try {
55-
await wm.registerOneOffTask('taskId', 'taskName');
56-
await wm.cancelByUniqueName('taskId');
62+
await wm.registerOneOffTask(
63+
'be.tramckrijte.workmanagerExample.taskId',
64+
'taskName',
65+
);
66+
await wm.cancelByUniqueName(
67+
'be.tramckrijte.workmanagerExample.taskId',
68+
);
5769
} on PlatformException catch (e) {
5870
if (e.code !=
5971
'bgTaskSchedulingFailed(Error Domain=BGTaskSchedulerErrorDomain Code=1 "(null)") error') {

example/ios/Runner.xcodeproj/project.pbxproj

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
4646
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
4747
1D8E96D33387777E764CB962 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
48+
233B458D27A8C7F6008933ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
4849
24469BF6D0EF2BB3720EC4B4 /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
4950
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
5051
57B0832593D65C5496C91850 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
@@ -60,7 +61,6 @@
6061
97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
6162
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
6263
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
63-
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6464
9EA9C43326E8F58700E77F3E /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
6565
9EA9C43526E8F58700E77F3E /* WorkmanagerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WorkmanagerTests.swift; sourceTree = "<group>"; };
6666
9EA9C43726E8F58700E77F3E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@@ -136,10 +136,10 @@
136136
97C146F01CF9000F007C117D /* Runner */ = {
137137
isa = PBXGroup;
138138
children = (
139+
233B458D27A8C7F6008933ED /* Info.plist */,
139140
97C146FA1CF9000F007C117D /* Main.storyboard */,
140141
97C146FD1CF9000F007C117D /* Assets.xcassets */,
141142
97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
142-
97C147021CF9000F007C117D /* Info.plist */,
143143
97C146F11CF9000F007C117D /* Supporting Files */,
144144
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
145145
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
@@ -231,7 +231,7 @@
231231
TargetAttributes = {
232232
97C146ED1CF9000F007C117D = {
233233
CreatedOnToolsVersion = 7.3.1;
234-
DevelopmentTeam = GPGRWN6G4J;
234+
DevelopmentTeam = 6KRGLYTFWP;
235235
LastSwiftMigration = 1110;
236236
};
237237
9EA9C43226E8F58700E77F3E = {
@@ -510,10 +510,7 @@
510510
"$(PROJECT_DIR)/Flutter",
511511
);
512512
INFOPLIST_FILE = Runner/Info.plist;
513-
LD_RUNPATH_SEARCH_PATHS = (
514-
"$(inherited)",
515-
"@executable_path/Frameworks",
516-
);
513+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
517514
LIBRARY_SEARCH_PATHS = (
518515
"$(inherited)",
519516
"$(PROJECT_DIR)/Flutter",
@@ -643,17 +640,14 @@
643640
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
644641
CLANG_ENABLE_MODULES = YES;
645642
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
646-
DEVELOPMENT_TEAM = GPGRWN6G4J;
643+
DEVELOPMENT_TEAM = 6KRGLYTFWP;
647644
ENABLE_BITCODE = NO;
648645
FRAMEWORK_SEARCH_PATHS = (
649646
"$(inherited)",
650647
"$(PROJECT_DIR)/Flutter",
651648
);
652649
INFOPLIST_FILE = Runner/Info.plist;
653-
LD_RUNPATH_SEARCH_PATHS = (
654-
"$(inherited)",
655-
"@executable_path/Frameworks",
656-
);
650+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
657651
LIBRARY_SEARCH_PATHS = (
658652
"$(inherited)",
659653
"$(PROJECT_DIR)/Flutter",
@@ -682,10 +676,7 @@
682676
"$(PROJECT_DIR)/Flutter",
683677
);
684678
INFOPLIST_FILE = Runner/Info.plist;
685-
LD_RUNPATH_SEARCH_PATHS = (
686-
"$(inherited)",
687-
"@executable_path/Frameworks",
688-
);
679+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
689680
LIBRARY_SEARCH_PATHS = (
690681
"$(inherited)",
691682
"$(PROJECT_DIR)/Flutter",
@@ -714,11 +705,7 @@
714705
GCC_C_LANGUAGE_STANDARD = gnu11;
715706
INFOPLIST_FILE = RunnerTests/Info.plist;
716707
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
717-
LD_RUNPATH_SEARCH_PATHS = (
718-
"$(inherited)",
719-
"@executable_path/Frameworks",
720-
"@loader_path/Frameworks",
721-
);
708+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
722709
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
723710
MTL_FAST_MATH = YES;
724711
PRODUCT_BUNDLE_IDENTIFIER = com.fluttercommunity.workmanagerTests;
@@ -746,11 +733,7 @@
746733
GCC_C_LANGUAGE_STANDARD = gnu11;
747734
INFOPLIST_FILE = RunnerTests/Info.plist;
748735
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
749-
LD_RUNPATH_SEARCH_PATHS = (
750-
"$(inherited)",
751-
"@executable_path/Frameworks",
752-
"@loader_path/Frameworks",
753-
);
736+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
754737
MTL_FAST_MATH = YES;
755738
PRODUCT_BUNDLE_IDENTIFIER = com.fluttercommunity.workmanagerTests;
756739
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -775,11 +758,7 @@
775758
GCC_C_LANGUAGE_STANDARD = gnu11;
776759
INFOPLIST_FILE = RunnerTests/Info.plist;
777760
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
778-
LD_RUNPATH_SEARCH_PATHS = (
779-
"$(inherited)",
780-
"@executable_path/Frameworks",
781-
"@loader_path/Frameworks",
782-
);
761+
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
783762
MTL_FAST_MATH = YES;
784763
PRODUCT_BUNDLE_IDENTIFIER = com.fluttercommunity.workmanagerTests;
785764
PRODUCT_NAME = "$(TARGET_NAME)";

example/ios/Runner/AppDelegate.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ import workmanager
2020
GeneratedPluginRegistrant.register(with: registry)
2121
}
2222

23+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.taskId")
24+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.simpleTask")
25+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.rescheduledTask")
26+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.failedTask")
27+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.simpleDelayedTask")
28+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.simplePeriodicTask")
29+
WorkmanagerPlugin.registerTask(withIdentifier: "be.tramckrijte.workmanagerExample.simplePeriodic1HourTask")
30+
2331
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
2432

2533
}

example/ios/Runner/Info.plist

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,13 @@
44
<dict>
55
<key>BGTaskSchedulerPermittedIdentifiers</key>
66
<array>
7-
<string>workmanager.background.task</string>
7+
<string>be.tramckrijte.workmanagerExample.taskId</string>
8+
<string>be.tramckrijte.workmanagerExample.simpleTask</string>
9+
<string>be.tramckrijte.workmanagerExample.rescheduledTask</string>
10+
<string>be.tramckrijte.workmanagerExample.failedTask</string>
11+
<string>be.tramckrijte.workmanagerExample.simpleDelayedTask</string>
12+
<string>be.tramckrijte.workmanagerExample.simplePeriodicTask</string>
13+
<string>be.tramckrijte.workmanagerExample.simplePeriodic1HourTask</string>
814
</array>
915
<key>CFBundleDevelopmentRegion</key>
1016
<string>$(DEVELOPMENT_LANGUAGE)</string>

0 commit comments

Comments
 (0)