From 40c9bdd364c1e111783b104bac11f2503a08e7bc Mon Sep 17 00:00:00 2001 From: Koen Van Looveren Date: Wed, 23 Dec 2020 14:34:43 +0100 Subject: [PATCH 1/3] #8 Fixed the issue where the plugins were not yet registered --- ios/Classes/BackgroundLocationTrackerPlugin.m | 6 ++++++ lib/src/background_location_tracker_manager.dart | 3 +-- lib/src/channel/background_channel.dart | 10 +++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/ios/Classes/BackgroundLocationTrackerPlugin.m b/ios/Classes/BackgroundLocationTrackerPlugin.m index 909c4b2..bc23b12 100644 --- a/ios/Classes/BackgroundLocationTrackerPlugin.m +++ b/ios/Classes/BackgroundLocationTrackerPlugin.m @@ -9,7 +9,13 @@ #endif @implementation BackgroundLocationTrackerPlugin + + (void)registerWithRegistrar:(NSObject*)registrar { [SwiftBackgroundLocationTrackerPlugin registerWithRegistrar:registrar]; } + ++ (void)setPluginRegistrantCallback:(FlutterPluginRegistrantCallback)callback { + [SwiftBackgroundLocationTrackerPlugin setPluginRegistrantCallback:callback]; +} + @end diff --git a/lib/src/background_location_tracker_manager.dart b/lib/src/background_location_tracker_manager.dart index b16ebea..b817374 100644 --- a/lib/src/background_location_tracker_manager.dart +++ b/lib/src/background_location_tracker_manager.dart @@ -6,10 +6,9 @@ import 'package:background_location_tracker/src/model/background_location_update import 'package:background_location_tracker/src/model/config/background_location_tracker_config.dart'; import 'package:background_location_tracker/src/util/logger.dart'; -typedef LocationUpdateCallback = void Function(BackgroundLocationUpdateData data); +typedef LocationUpdateCallback = Future Function(BackgroundLocationUpdateData data); class BackgroundLocationTrackerManager { - static Future initialize(Function callback, {BackgroundLocationTrackerConfig config}) { final pluginConfig = config ??= const BackgroundLocationTrackerConfig(); BackgroundLocationTrackerLogger.enableLogging = pluginConfig.loggingEnabled; diff --git a/lib/src/channel/background_channel.dart b/lib/src/channel/background_channel.dart index 448011b..8e167d0 100644 --- a/lib/src/channel/background_channel.dart +++ b/lib/src/channel/background_channel.dart @@ -13,10 +13,9 @@ class BackgroundChannel { ..setMethodCallHandler((call) async { switch (call.method) { case 'onLocationUpdate': - await handleLocationUpdate(call, callback, enableLogging: enableLogging); - break; + return handleLocationUpdate(call, callback, enableLogging: enableLogging); default: - break; + return false; } }) ..invokeMethod( @@ -24,13 +23,14 @@ class BackgroundChannel { ); } - static Future handleLocationUpdate(MethodCall call, LocationUpdateCallback callback, {bool enableLogging = false}) async { + static Future handleLocationUpdate(MethodCall call, LocationUpdateCallback callback, {bool enableLogging = false}) async { final data = call.arguments as Map; // ignore: avoid_as final isLoggingEnabled = data['logging_enabled'] as bool; // ignore: avoid_as BackgroundLocationTrackerLogger.enableLogging = isLoggingEnabled; BackgroundLocationTrackerLogger.log('locationUpdate: ${call.arguments}'); final lat = data['lat'] as double; // ignore: avoid_as final lon = data['lon'] as double; // ignore: avoid_as - callback(BackgroundLocationUpdateData(lat: lat, lon: lon)); + await callback(BackgroundLocationUpdateData(lat: lat, lon: lon)); + return true; } } From 37308218cccdc00def9307775efed18308b64327 Mon Sep 17 00:00:00 2001 From: Koen Van Looveren Date: Wed, 23 Dec 2020 14:53:03 +0100 Subject: [PATCH 2/3] Fixed analyzer --- example/lib/main.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index be24a60..cbf4ed0 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -4,7 +4,7 @@ import 'package:background_location_tracker/background_location_tracker.dart'; import 'package:flutter/material.dart'; import 'package:permission_handler/permission_handler.dart'; -void _backgroundCallback() => BackgroundLocationTrackerManager.handleBackgroundUpdated((data) => Repo().update(data)); +void _backgroundCallback() => BackgroundLocationTrackerManager.handleBackgroundUpdated((data) async => Repo().update(data)); Future main() async { WidgetsFlutterBinding.ensureInitialized(); From bb66e77cb5e517f91193c44fc97cf5d53b438c4b Mon Sep 17 00:00:00 2001 From: Koen Van Looveren Date: Wed, 23 Dec 2020 16:10:48 +0100 Subject: [PATCH 3/3] #8 Updated the example to show push notification from the background. & fixed the set plugin registrant callback --- README.md | 82 +++++++++++++++++++++++++++- example/ios/Podfile.lock | 8 ++- example/ios/Runner/AppDelegate.swift | 11 +++- example/lib/main.dart | 51 ++++++++++++++++- example/pubspec.lock | 28 ++++++++++ example/pubspec.yaml | 1 + 6 files changed, 176 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index cfed2e0..ba4cd71 100644 --- a/README.md +++ b/README.md @@ -3,4 +3,84 @@ A new Flutter plugin that allows you to track the background location for Android & iOS [![Build Status](https://travis-ci.com/icapps/flutter-background-location-tracker.svg?branch=master)](https://travis-ci.com/icapps/flutter-background-location-tracker) -[![Coverage Status](https://coveralls.io/repos/github/icapps/flutter-background-location-tracker/badge.svg?branch=master)](https://coveralls.io/github/icapps/flutter-background-location-tracker?branch=master) \ No newline at end of file +[![Coverage Status](https://coveralls.io/repos/github/icapps/flutter-background-location-tracker/badge.svg?branch=master)](https://coveralls.io/github/icapps/flutter-background-location-tracker?branch=master) + +## Android Config + +### Update compile sdk + +Compile sdk should be at 29 at least. +``` +android { + ... + compileSdkVersion 29 + ... + + defaultConfig { + ... + targetSdkVersion 29 + ... + } + ... +} +``` + +## iOS Configuration + +### Update Info.plist + +Add the correct permission descriptions +``` + NSLocationAlwaysAndWhenInUseUsageDescription + Your description why you should use NSLocationAlwaysAndWhenInUseUsageDescription + NSLocationAlwaysUsageDescription + Your description why you should use NSLocationAlwaysAndWhenInUseUsageDescription + NSLocationWhenInUseUsageDescription + Your description why you should use NSLocationAlwaysAndWhenInUseUsageDescription +``` + +Add the background location updates in xcode + +Or add the info to the Info.plist + +``` + UIBackgroundModes + + location + +``` + +### Update the AppDelegate + +Make sure you call the `setPluginRegistrantCallback` so other plugins can be accessed in the background. + +``` +import UIKit +import Flutter +import background_location_tracker + +@UIApplicationMain +@objc class AppDelegate: FlutterAppDelegate { + override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + GeneratedPluginRegistrant.register(with: self) + + BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in + GeneratedPluginRegistrant.register(with: registry) + } + + return super.application(application, didFinishLaunchingWithOptions: launchOptions) + } +} +``` + + +FAQ: + +#### I get a Unhandled Exception: MissingPluginException(No implementation found for method .... on channel ...) + +``` +This is mostly caused by a misconfiguration of the plugin: +Android Pre v2 embedding: make sure the plugin registrant callback is set +Android v2 embedding: Log a new github issues. This +iOS: make sure the plugin registrant callback is set +``` diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index bcb4e04..ec60fe1 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -2,12 +2,15 @@ PODS: - background_location_tracker (0.0.1): - Flutter - Flutter (1.0.0) + - flutter_local_notifications (0.0.1): + - Flutter - "permission_handler (5.0.1+1)": - Flutter DEPENDENCIES: - background_location_tracker (from `.symlinks/plugins/background_location_tracker/ios`) - Flutter (from `Flutter`) + - flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`) - permission_handler (from `.symlinks/plugins/permission_handler/ios`) EXTERNAL SOURCES: @@ -15,14 +18,17 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/background_location_tracker/ios" Flutter: :path: Flutter + flutter_local_notifications: + :path: ".symlinks/plugins/flutter_local_notifications/ios" permission_handler: :path: ".symlinks/plugins/permission_handler/ios" SPEC CHECKSUMS: background_location_tracker: 3f0954d5a839b9bfffbdc887e679d183a7bbc1c9 Flutter: 0e3d915762c693b495b44d77113d4970485de6ec + flutter_local_notifications: 0c0b1ae97e741e1521e4c1629a459d04b9aec743 permission_handler: eac8e15b4a1a3fba55b761d19f3f4e6b005d15b6 PODFILE CHECKSUM: aafe91acc616949ddb318b77800a7f51bffa2a4c -COCOAPODS: 1.9.1 +COCOAPODS: 1.10.0 diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 351bd4c..3a465c4 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -1,11 +1,20 @@ import UIKit import Flutter +import background_location_tracker @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GeneratedPluginRegistrant.register(with: self) - + + if #available(iOS 10.0, *) { + UNUserNotificationCenter.current().delegate = self + } + + BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in + GeneratedPluginRegistrant.register(with: registry) + } + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } diff --git a/example/lib/main.dart b/example/lib/main.dart index cbf4ed0..5d7cca2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,10 @@ import 'dart:async'; +import 'dart:io'; +import 'dart:math'; import 'package:background_location_tracker/background_location_tracker.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; import 'package:permission_handler/permission_handler.dart'; void _backgroundCallback() => BackgroundLocationTrackerManager.handleBackgroundUpdated((data) async => Repo().update(data)); @@ -13,7 +16,6 @@ Future main() async { config: const BackgroundLocationTrackerConfig( androidConfig: AndroidConfig( notificationIcon: 'explore', - enableCancelTrackingAction: false, ), ), ); @@ -50,6 +52,15 @@ class _MyAppState extends State { child: const Text('Request location permission'), onPressed: _requestLocationPermission, ), + if (Platform.isIOS) + MaterialButton( + child: const Text('Request Notification permission'), + onPressed: _requestNotificationPermission, + ), + MaterialButton( + child: const Text('Send notification'), + onPressed: () => sendNotification('Hallokes'), + ), if (isTracking != null) ...[ MaterialButton( child: const Text('Start Tracking'), @@ -90,6 +101,15 @@ class _MyAppState extends State { print('NOT GRANTED'); // ignore: avoid_print } } + + Future _requestNotificationPermission() async { + final result = await Permission.notification.request(); + if (result == PermissionStatus.granted) { + print('GRANTED'); // ignore: avoid_print + } else { + print('NOT GRANTED'); // ignore: avoid_print + } + } } class Repo { @@ -99,5 +119,32 @@ class Repo { factory Repo() => _instance ??= Repo._(); - void update(BackgroundLocationUpdateData data) => print('Location Update: Lat: ${data.lat} Lon: ${data.lon}'); // ignore: avoid_print + void update(BackgroundLocationUpdateData data) { + final text = 'Location Update: Lat: ${data.lat} Lon: ${data.lon}'; + print(text); // ignore: avoid_print + sendNotification(text); + } +} + +void sendNotification(String text) { + const settings = InitializationSettings( + android: AndroidInitializationSettings('app_icon'), + iOS: IOSInitializationSettings( + requestAlertPermission: false, + requestBadgePermission: false, + requestSoundPermission: false, + ), + ); + FlutterLocalNotificationsPlugin().initialize(settings, onSelectNotification: (data) async { + print('ON CLICK $data'); // ignore: avoid_print + }); + FlutterLocalNotificationsPlugin().show( + Random().nextInt(9999), + 'Title', + text, + const NotificationDetails( + android: AndroidNotificationDetails('test_notification', 'Test', 'Test'), + iOS: IOSNotificationDetails(), + ), + ); } diff --git a/example/pubspec.lock b/example/pubspec.lock index bd93d52..3709258 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -62,6 +62,20 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_local_notifications: + dependency: "direct main" + description: + name: flutter_local_notifications + url: "https://pub.dartlang.org" + source: hosted + version: "3.0.2" + flutter_local_notifications_platform_interface: + dependency: transitive + description: + name: flutter_local_notifications_platform_interface + url: "https://pub.dartlang.org" + source: hosted + version: "2.0.0+1" flutter_test: dependency: "direct dev" description: flutter @@ -102,6 +116,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "2.0.1" + platform: + dependency: transitive + description: + name: platform + url: "https://pub.dartlang.org" + source: hosted + version: "2.2.1" plugin_platform_interface: dependency: transitive description: @@ -156,6 +177,13 @@ packages: url: "https://pub.dartlang.org" source: hosted version: "0.2.19-nullsafety.2" + timezone: + dependency: transitive + description: + name: timezone + url: "https://pub.dartlang.org" + source: hosted + version: "0.5.9" typed_data: dependency: transitive description: diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 07db537..efb644f 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -11,6 +11,7 @@ dependencies: background_location_tracker: path: ../ permission_handler: ^5.0.1+1 + flutter_local_notifications: ^3.0.2 dev_dependencies: flutter_test: