Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add background workers functionality and notification background support #645

Merged
merged 32 commits into from
Mar 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
3afff39
Add WorkManager as a dependency for UNI
LuisDuarte1 Nov 11, 2022
34f6b35
Add initial support for background workers
LuisDuarte1 Nov 12, 2022
1b26440
enabling ios
thePeras Nov 23, 2022
bf87eb0
Add one off task when running in ios to guarrentee that notifications…
LuisDuarte1 Nov 23, 2022
7204020
work manager
thePeras Nov 23, 2022
92f181f
Add a notification timeout to prevent spam
LuisDuarte1 Nov 30, 2022
4ade643
Guarentee that the notifiction will be ran at least one when the app …
LuisDuarte1 Dec 5, 2022
4f660de
Add flutter local notifications (bump compile sdk to 33)
LuisDuarte1 Dec 5, 2022
832e4c9
Add tutionNotification
LuisDuarte1 Dec 7, 2022
bad271a
Fix notification timeout
LuisDuarte1 Dec 7, 2022
b9f5f90
Notification icon works on android
LuisDuarte1 Dec 28, 2022
65c9651
Add ios support
LuisDuarte1 Dec 28, 2022
1d7dc0c
Add notification toggle for tuitions
LuisDuarte1 Dec 28, 2022
ee42370
fix notification timeout storage
LuisDuarte1 Dec 28, 2022
a877a21
Fix typos and rename functions for better readbility
LuisDuarte1 Jan 25, 2023
0a75148
Merge branch 'develop' into feature/background-workers
LuisDuarte1 Jan 25, 2023
a870d3b
Change compile sdk version
LuisDuarte1 Jan 25, 2023
50b6a0e
Move notification initialization when the app is logged in and make i…
LuisDuarte1 Jan 29, 2023
1a23908
ios files
Jan 29, 2023
a4f6281
Add delay to the initalization of notifications
LuisDuarte1 Jan 30, 2023
8c86044
Minor fixes to the display text and change frequency on android
LuisDuarte1 Jan 31, 2023
184871c
Merge branch 'develop' into feature/background-workers
thePeras Feb 8, 2023
bb3e87c
Rename workers folder and make perdiodic in main isolate in iOS
thePeras Feb 8, 2023
69740d1
Merge branch 'develop' into feature/background-workers
LuisDuarte1 Feb 12, 2023
24ef1fa
Merge branch 'develop' into feature/background-workers
thePeras Feb 19, 2023
090ff01
changes to allow for better readability
LuisDuarte1 Feb 24, 2023
c4c0ef5
Merge branch 'develop' into feature/background-workers
LuisDuarte1 Mar 9, 2023
d2b38e7
Readd switch for notifications and silently return on failure (androi…
LuisDuarte1 Mar 9, 2023
e161bea
fix linting
LuisDuarte1 Mar 9, 2023
4907d46
format and make code more readable
LuisDuarte1 Mar 15, 2023
3522393
Merge branch 'develop' into feature/background-workers
LuisDuarte1 Mar 15, 2023
775ea04
Merge branch 'develop' into feature/background-workers
thePeras Mar 16, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion uni/android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ if (keystorePropertiesFile.exists()) {
}

android {
compileSdkVersion 33
compileSdkVersion 33
ndkVersion flutter.ndkVersion

compileOptions {
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion uni/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
<string>11.0</string>
</dict>
</plist>
75 changes: 74 additions & 1 deletion uni/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objectVersion = 51;
objects = {

/* Begin PBXBuildFile section */
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
95F65346A056DDFB0CCCED79 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 65A7FEFFF94135D00ABAE9B9 /* Pods_Runner.framework */; };
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
Expand All @@ -29,9 +30,13 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
116479123E23B6BA4733EC22 /* 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>"; };
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
1946AAAAFCF4B47B8541DAAE /* 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>"; };
34F7CD5BD9DE233CE39A0794 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
65A7FEFFF94135D00ABAE9B9 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
Expand All @@ -49,12 +54,23 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
95F65346A056DDFB0CCCED79 /* Pods_Runner.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
227A5121A8917F9CC04F8063 /* Pods */ = {
isa = PBXGroup;
children = (
116479123E23B6BA4733EC22 /* Pods-Runner.debug.xcconfig */,
1946AAAAFCF4B47B8541DAAE /* Pods-Runner.release.xcconfig */,
34F7CD5BD9DE233CE39A0794 /* Pods-Runner.profile.xcconfig */,
);
path = Pods;
sourceTree = "<group>";
};
9740EEB11CF90186004384FC /* Flutter */ = {
isa = PBXGroup;
children = (
Expand All @@ -72,6 +88,8 @@
9740EEB11CF90186004384FC /* Flutter */,
97C146F01CF9000F007C117D /* Runner */,
97C146EF1CF9000F007C117D /* Products */,
227A5121A8917F9CC04F8063 /* Pods */,
DCEE3166979EF19DFB76E949 /* Frameworks */,
);
sourceTree = "<group>";
};
Expand All @@ -98,19 +116,29 @@
path = Runner;
sourceTree = "<group>";
};
DCEE3166979EF19DFB76E949 /* Frameworks */ = {
isa = PBXGroup;
children = (
65A7FEFFF94135D00ABAE9B9 /* Pods_Runner.framework */,
);
name = Frameworks;
sourceTree = "<group>";
};
/* End PBXGroup section */

/* Begin PBXNativeTarget section */
97C146ED1CF9000F007C117D /* Runner */ = {
isa = PBXNativeTarget;
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
buildPhases = (
AD47D7787757870A61A69CBD /* [CP] Check Pods Manifest.lock */,
9740EEB61CF901F6004384FC /* Run Script */,
97C146EA1CF9000F007C117D /* Sources */,
97C146EB1CF9000F007C117D /* Frameworks */,
97C146EC1CF9000F007C117D /* Resources */,
9705A1C41CF9048500538489 /* Embed Frameworks */,
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
B72AED15C931F2FF135F33E9 /* [CP] Embed Pods Frameworks */,
);
buildRules = (
);
Expand Down Expand Up @@ -197,6 +225,45 @@
shellPath = /bin/sh;
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
};
AD47D7787757870A61A69CBD /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
"${PODS_ROOT}/Manifest.lock",
);
name = "[CP] Check Pods Manifest.lock";
outputFileListPaths = (
);
outputPaths = (
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
showEnvVarsInLog = 0;
};
B72AED15C931F2FF135F33E9 /* [CP] Embed Pods Frameworks */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Embed Pods Frameworks";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0;
};
/* End PBXShellScriptBuildPhase section */

/* Begin PBXSourcesBuildPhase section */
Expand Down Expand Up @@ -288,8 +355,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ADS6V5HXNQ;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down Expand Up @@ -416,8 +485,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ADS6V5HXNQ;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand All @@ -438,8 +509,10 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
DEVELOPMENT_TEAM = ADS6V5HXNQ;
ENABLE_BITCODE = NO;
INFOPLIST_FILE = Runner/Info.plist;
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
Expand Down
3 changes: 3 additions & 0 deletions uni/ios/Runner.xcworkspace/contents.xcworkspacedata

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions uni/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import UIKit
import Flutter
import workmanager
import flutter_local_notifications

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
Expand All @@ -8,6 +10,16 @@ import Flutter
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
WorkmanagerPlugin.registerTask(withIdentifier:"pt.up.fe.ni.uni.notificationworker")
UIApplication.shared.setMinimumBackgroundFetchInterval(TimeInterval(60*15))
//in case we have a notification with actions
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}

if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
14 changes: 14 additions & 0 deletions uni/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>BGTaskSchedulerPermittedIdentifiers</key>
<array>
<string>pt.up.fe.ni.uni.notificationworker</string>
</array>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>CFBundleDevelopmentRegion</key>
Expand Down Expand Up @@ -40,6 +44,16 @@
<true/>
<key>NSCalendarsUsageDescription</key>
<string>Exportar exames e eventos para o calendário</string>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UISceneConfigurations</key>
<dict/>
</dict>
<key>UIBackgroundModes</key>
<array>
<string>fetch</string>
<string>processing</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
Expand Down
42 changes: 42 additions & 0 deletions uni/lib/controller/background_workers/background_callback.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import 'package:logger/logger.dart';
import 'package:tuple/tuple.dart';
import 'package:uni/controller/background_workers/notifications.dart';
import 'package:workmanager/workmanager.dart';

/// This map contains the functions that a certain task type will run.
/// the bool is all functions that are ran by backgroundfetch in iOS
/// (they must not take any arguments, not checked)
const taskMap = {
"pt.up.fe.ni.uni.notificationworker":
Tuple2(NotificationManager.updateAndTriggerNotifications, true)
};

@pragma('vm:entry-point')
// This function is android only and only executes when the app is complety terminated
void workerStartCallback() async {
Workmanager().executeTask((taskName, inputData) async {
try {
Logger().d("""[$taskName]: Start executing job...""");

//iOSBackgroundTask is a special task, that iOS runs whenever it deems necessary
//and will run all tasks with the flag true
//NOTE: keep the total execution time under 30s to avoid being punished by the iOS scheduler.
if (taskName == Workmanager.iOSBackgroundTask) {
taskMap.forEach((key, value) async {
if (value.item2) {
Logger().d("""[$key]: Start executing job...""");
await value.item1();
}
});
return true;
}
//try to keep the usage of this function BELOW +-30 seconds
//to not be punished by the scheduler in future runs.
await taskMap[taskName]!.item1();
} catch (err, stackstrace) {
Logger().e("Error while running $taskName job:", err, stackstrace);
return false;
}
return true;
});
}
Loading