Antidote/Antidote/AppDelegate.swift

331 lines
13 KiB
Swift

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
import UIKit
import UserNotifications
import os
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
let gcmMessageIDKey = "gcm.message_id"
var coordinator: AppCoordinator!
let callManager = CallManager()
lazy var providerDelegate: ProviderDelegate = ProviderDelegate(callManager: self.callManager)
var backgroundTask: UIBackgroundTaskIdentifier = UIBackgroundTaskInvalid
var gps_was_stopped_by_forground: Bool = false
static var lastStartGpsTS: Int64 = 0
static var location_sharing_contact_pubkey: String = "-1"
class var shared: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
func displayIncomingCall(uuid: UUID, handle: String, hasVideo: Bool = false, completion: ((NSError?) -> Void)?) {
providerDelegate.reportIncomingCall(uuid: uuid, handle: handle, hasVideo: hasVideo, completion: completion)
}
func endIncomingCalls() {
providerDelegate.endIncomingCalls()
}
func applicationWillEnterForeground(_ application: UIApplication) {
os_log("AppDelegate:applicationWillEnterForeground")
UIApplication.shared.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
gps_was_stopped_by_forground = true
let gps = LocationManager.shared
if !gps.isHasAccess() {
os_log("AppDelegate:applicationWillEnterForeground:gps:no_access")
} else if gps.state == .Monitoring {
os_log("AppDelegate:applicationWillEnterForeground:gps:STOP")
gps.stopMonitoring()
}
os_log("AppDelegate:applicationWillEnterForeground:DidEnterBackground:2:END")
}
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame:UIScreen.main.bounds)
print("didFinishLaunchingWithOptions")
os_log("AppDelegate:didFinishLaunchingWithOptions:start")
if ProcessInfo.processInfo.arguments.contains("UI_TESTING") {
// Speeding up animations for UI tests.
window!.layer.speed = 1000
}
configureLoggingStuff()
coordinator = AppCoordinator(window: window!)
coordinator.startWithOptions(nil)
if let notification = launchOptions?[UIApplicationLaunchOptionsKey.localNotification] as? UILocalNotification {
coordinator.handleLocalNotification(notification)
}
window?.backgroundColor = UIColor.white
window?.makeKeyAndVisible()
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
if granted {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
print("Permission for push notifications denied.")
}
}
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self
let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
UNUserNotificationCenter.current().requestAuthorization(
options: authOptions,
completionHandler: { _, _ in }
)
} else {
let settings: UIUserNotificationSettings =
UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
application.registerUserNotificationSettings(settings)
}
application.registerForRemoteNotifications()
// HINT: try to go online every 5 minutes
let bgfetchInterval: TimeInterval = 5 * 60
application.setMinimumBackgroundFetchInterval(bgfetchInterval);
os_log("AppDelegate:didFinishLaunchingWithOptions:end")
return true
}
func applicationWillTerminate(_ application: UIApplication) {
print("WillTerminate")
os_log("AppDelegate:applicationWillTerminate")
}
func applicationDidReceiveMemoryWarning(_ application: UIApplication) {
print("DidReceiveMemoryWarning")
os_log("AppDelegate:applicationDidReceiveMemoryWarning")
}
func applicationDidEnterBackground(_ application: UIApplication) {
print("DidEnterBackground")
os_log("AppDelegate:applicationDidEnterBackground:start")
backgroundTask = UIApplication.shared.beginBackgroundTask (expirationHandler: { [unowned self] in
UIApplication.shared.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
os_log("AppDelegate:applicationDidEnterBackground:3:expirationHandler:END")
})
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 15) {
if (UserDefaultsManager().LongerbgMode == true) {
os_log("AppDelegate:applicationDidEnterBackground:PushSelf:start")
let coord = self.coordinator.activeCoordinator
let runcoord = coord as! RunningCoordinator
} else {
os_log("AppDelegate:applicationDidEnterBackground:PushSelf:longer-bg-mode not active in settings")
}
}
gps_was_stopped_by_forground = false
let gps = LocationManager.shared
if gps.isHasAccess() {
AppDelegate.lastStartGpsTS = Date().millisecondsSince1970
gps.startMonitoring()
os_log("AppDelegate:applicationDidEnterBackground:gps:START")
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + (3 * 60)) {
os_log("AppDelegate:applicationDidEnterBackground:4:gps:finishing")
let gps = LocationManager.shared
if !gps.isHasAccess() {
os_log("AppDelegate:applicationDidEnterBackground:4:gps:no_access")
} else if gps.state == .Monitoring {
if (self.gps_was_stopped_by_forground == false) {
let diffTime = Date().millisecondsSince1970 - AppDelegate.lastStartGpsTS
os_log("AppDelegate:applicationDidEnterBackground:4:gps:Tlast=%ld", AppDelegate.lastStartGpsTS)
os_log("AppDelegate:applicationDidEnterBackground:4:gps:Tnow=%ld", Date().millisecondsSince1970)
os_log("AppDelegate:applicationDidEnterBackground:4:gps:Tdiff=%ld", diffTime)
if (diffTime > (((3 * 60) - 4) * 1000))
{
os_log("AppDelegate:applicationDidEnterBackground:4:gps:STOP")
gps.stopMonitoring()
} else {
os_log("AppDelegate:applicationDidEnterBackground:4:gps:STOP skipped, must be an old timer")
}
} else {
os_log("AppDelegate:applicationDidEnterBackground:4:gps:was stopped by forground, skipping")
}
} else {
os_log("AppDelegate:applicationDidEnterBackground:4:gps:STOP skipped, gps was stopped already")
}
}
} else {
os_log("AppDelegate:applicationDidEnterBackground:gps:no_access")
}
DispatchQueue.main.asyncAfter(wallDeadline: DispatchWallTime.now() + 25) {
UIApplication.shared.endBackgroundTask(self.backgroundTask)
self.backgroundTask = UIBackgroundTaskInvalid
os_log("AppDelegate:applicationDidEnterBackground:1:END")
}
}
func application(_ application: UIApplication, performFetchWithCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
print("performFetchWithCompletionHandler:start")
os_log("AppDelegate:performFetchWithCompletionHandler:start")
// HINT: we have 30 seconds here. use 25 of those 30 seconds to be on the safe side
DispatchQueue.main.asyncAfter(deadline: .now() + 25) { [weak self] in
completionHandler(UIBackgroundFetchResult.newData)
print("performFetchWithCompletionHandler:end")
os_log("AppDelegate:performFetchWithCompletionHandler:end")
}
}
func application(_ application: UIApplication, didReceive notification: UILocalNotification) {
coordinator.handleLocalNotification(notification)
}
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any]) -> Bool {
coordinator.handleInboxURL(url)
return true
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
coordinator.handleInboxURL(url)
return true
}
// Device received notification (legacy callback)
//
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any]) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
}
// tells the app that a remote notification arrived that indicates there is data to be fetched.
// ios 7+
//
func application(_ application: UIApplication,
didReceiveRemoteNotification userInfo: [AnyHashable: Any],
fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult)
-> Void) {
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
os_log("AppDelegate:didReceiveRemoteNotification:start")
// HINT: we have 30 seconds here. use 25 of those 30 seconds to be on the safe side
DispatchQueue.main.asyncAfter(deadline: .now() + 25) { [weak self] in
completionHandler(UIBackgroundFetchResult.newData)
os_log("AppDelegate:didReceiveRemoteNotification:start")
}
}
// APNs failed to register the device for push notifications
//
func application(_ application: UIApplication,
didFailToRegisterForRemoteNotificationsWithError error: Error) {
print("Unable to register for remote notifications: \(error.localizedDescription)")
}
func application(_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let token = deviceToken.map { String(format: "%02.2hhx", $0) }.joined()
// TODO(Tha_14): Save the token in db.
print("Device Token: \(token)")
print("APNs token retrieved: \(deviceToken)")
os_log("AppDelegate:didRegisterForRemoteNotificationsWithDeviceToken")
}
}
@available(iOS 10, *)
extension AppDelegate: UNUserNotificationCenterDelegate {
// determine what to do if app is in foreground when a notification is coming
// ios 10+ UNUserNotificationCenterDelegate method
//
func userNotificationCenter(_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: @escaping (UNNotificationPresentationOptions)
-> Void) {
let userInfo = notification.request.content.userInfo
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
completionHandler([[.alert, .sound]])
}
// Process and handle the user's response to a delivered notification.
// ios 10+ UNUserNotificationCenterDelegate method
//
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse,
withCompletionHandler completionHandler: @escaping () -> Void) {
let userInfo = response.notification.request.content.userInfo
if let messageID = userInfo[gcmMessageIDKey] {
print("Message ID: \(messageID)")
}
completionHandler()
}
}
private extension AppDelegate {
func configureLoggingStuff() {
DDLog.add(DDASLLogger.sharedInstance())
// DDLog.add(DDTTYLogger.sharedInstance())
}
}
//extension AppDelegate: MessagingDelegate {
// func messaging(_ messaging: Messaging, didReceiveRegistrationToken fcmToken: String?) {
// print("Firebase registration token: \(String(describing: fcmToken))")
//
// let dataDict: [String: String] = ["token": fcmToken ?? ""]
// NotificationCenter.default.post(
// name: Notification.Name("FCMToken"),
// object: nil,
// userInfo: dataDict
// )
// }
//}
// Convenience AppWide Simple Alert
extension AppDelegate {
func alert(_ title: String, _ msg: String? = nil) {
os_log("AppDelegate:alert")
let cnt = UIAlertController(title: title, message: msg, preferredStyle: .alert)
cnt.addAction(UIAlertAction(title: "Ok", style: .default, handler: { [weak cnt] act in
cnt?.dismiss(animated: true, completion: nil)
}))
// guard let vc = AppDelegate.topViewController() else { return }
// vc.present(cnt, animated: true, completion: nil)
}
}
extension Date {
var millisecondsSince1970: Int64 {
Int64((self.timeIntervalSince1970 * 1000.0).rounded())
}
init(milliseconds: Int64) {
self = Date(timeIntervalSince1970: TimeInterval(milliseconds) / 1000)
}
}