From 4e80f9e9ea03649c0f8410a16611fa4d5a625aa7 Mon Sep 17 00:00:00 2001 From: Muhammad Amin <105256309+MuhammedAm1n@users.noreply.github.com> Date: Tue, 6 May 2025 11:18:09 +0300 Subject: [PATCH 1/2] Update to Flutter Plugin V2 embedding; deprecate old methods for background execution --- CHANGELOG.md | 6 ++ README.md | 24 ++++- .../BackgroundLocationTrackerPlugin.kt | 94 ++++++++----------- .../flutter/FlutterBackgroundManager.kt | 6 +- .../android/app/src/main/AndroidManifest.xml | 2 +- .../kotlin/com/example/example/Application.kt | 24 +++++ example/ios/Runner/AppDelegate.swift | 4 + ios/Classes/BackgroundLocationTrackerPlugin.m | 2 + ios/Classes/ForegroundChannel.swift | 9 +- ...SwiftBackgroundLocationTrackerPlugin.swift | 13 ++- 10 files changed, 113 insertions(+), 71 deletions(-) create mode 100644 example/android/app/src/main/kotlin/com/example/example/Application.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 16ddecb..701133f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.0 - 2024-XX-XX +- Updated to use the modern FlutterPlugin.FlutterPluginBinding pattern +- Deprecated Registrar, PluginRegistrantCallback, and ShimPluginRegistry usage +- Added backward compatibility for older Flutter versions +- Improved handling of plugin registration in background execution + ## 1.5.0 - 2025-01-29 - Updated gradle dependencies diff --git a/README.md b/README.md index 35abef4..252df3d 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,6 @@ Or add the info to the Info.plist ### Update the AppDelegate -Make sure you call the `setPluginRegistrantCallback` so other plugins can be accessed in the background. - ``` import UIKit import Flutter @@ -65,6 +63,8 @@ import background_location_tracker override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GeneratedPluginRegistrant.register(with: self) + // Register plugins for background execution - this method is deprecated + // but kept for backward compatibility BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in GeneratedPluginRegistrant.register(with: registry) } @@ -124,7 +124,21 @@ Future stopLocationTracking() async { ``` 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 +- Android: This plugin now uses Flutter's Plugin V2 embedding pattern (FlutterPluginBinding) so you don't need to set a manual plugin registrant callback. +- iOS: For compatibility with older Flutter versions, the setPluginRegistrantCallback is still available but will be removed in a future version. + +If you're using Flutter 1.12 or later, the plugin should work out of the box with the V2 embedding. ``` + +## Migration Guide + +### Upgrading from older versions + +This plugin has been updated to use the modern Flutter Plugin V2 embedding pattern with FlutterPluginBinding. If you're using Flutter 1.12 or later, you don't need to make any changes to your app's code. + +For backward compatibility, the older methods are still available but marked as deprecated: + +- `BackgroundLocationTrackerPlugin.setPluginRegistrantCallback` on Android +- `BackgroundLocationTrackerPlugin.setPluginRegistrantCallback` on iOS + +These methods will be removed in a future version of the plugin. diff --git a/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt b/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt index d3cffa3..0b6593a 100644 --- a/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt +++ b/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt @@ -19,17 +19,29 @@ import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.embedding.engine.FlutterEngine class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { private var lifecycle: Lifecycle? = null private var methodCallHelper: MethodCallHelper? = null - - override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { - registerBackgroundLocationManager(binding.binaryMessenger, binding.applicationContext) + private var channel: MethodChannel? = null + private var applicationContext: Context? = null + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + applicationContext = binding.applicationContext + channel = MethodChannel(binding.binaryMessenger, FOREGROUND_CHANNEL_NAME) + channel?.setMethodCallHandler(this) + + if (methodCallHelper == null) { + methodCallHelper = MethodCallHelper.getInstance(binding.applicationContext) + } } - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + channel?.setMethodCallHandler(null) + channel = null + applicationContext = null } override fun onMethodCall(call: MethodCall, result: Result) { @@ -38,10 +50,7 @@ class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, Activi override fun onAttachedToActivity(binding: ActivityPluginBinding) { lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding) - if (methodCallHelper == null) { - ActivityCounter.attach(binding.activity) - methodCallHelper = MethodCallHelper.getInstance(binding.activity.applicationContext) - } + ActivityCounter.attach(binding.activity) methodCallHelper?.let { lifecycle?.removeObserver(it) lifecycle?.addObserver(it) @@ -50,67 +59,42 @@ class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, Activi override fun onDetachedFromActivity() {} - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {} + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + onAttachedToActivity(binding) + } - override fun onDetachedFromActivityForConfigChanges() {} + override fun onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity() + } companion object { private const val TAG = "FBLTPlugin" private const val FOREGROUND_CHANNEL_NAME = "com.icapps.background_location_tracker/foreground_channel" - var pluginRegistryCallback: PluginRegistry.PluginRegistrantCallback? = null + // New static properties for background execution + private var flutterEngine: FlutterEngine? = null - @JvmStatic - private fun registerBackgroundLocationManager(messenger: BinaryMessenger, ctx: Context) { - val channel = MethodChannel(messenger, FOREGROUND_CHANNEL_NAME) - channel.setMethodCallHandler(BackgroundLocationTrackerPlugin().apply { - if (methodCallHelper == null) { - methodCallHelper = MethodCallHelper.getInstance(ctx) - } - methodCallHelper?.let { - lifecycle?.removeObserver(it) - lifecycle?.addObserver(it) - } - }) - } + // For compatibility with older plugins + @Deprecated("Use FlutterEngine's plugin registry instead") + private var pluginRegistrantCallback: ((FlutterEngine) -> Unit)? = null @JvmStatic - fun registerWith(registrar: PluginRegistry.Registrar) { - val activity = registrar.activity() - if (activity == null) { - Logger.debug(TAG, "Activity should not be null while registering this plugin") - return - } - - val lifecycle: Lifecycle = if (activity is LifecycleOwner) { - (activity as LifecycleOwner).lifecycle - } else { - Logger.debug(TAG, "Your activity has not implemented a lifecycle owner. We will create one for you.") - @Suppress("DEPRECATION") - ProxyLifecycleProvider(activity).lifecycle - } - - ActivityCounter.attach(activity) - val channel = MethodChannel(registrar.messenger(), FOREGROUND_CHANNEL_NAME) - channel.setMethodCallHandler(BackgroundLocationTrackerPlugin().apply { - if (methodCallHelper == null) { - methodCallHelper = MethodCallHelper.getInstance(registrar.activeContext()) - } - methodCallHelper?.let { - lifecycle.removeObserver(it) - lifecycle.addObserver(it) - } - }) + @Deprecated("Use the Android embedding v2 instead") + fun setPluginRegistrantCallback(callback: ((FlutterEngine) -> Unit)) { + pluginRegistrantCallback = callback } - @Deprecated(message = "Use the Android v2 embedding method.") + // Method to get or create the Flutter engine for background execution @JvmStatic - fun setPluginRegistrantCallback(pluginRegistryCallback: PluginRegistry.PluginRegistrantCallback) { - BackgroundLocationTrackerPlugin.pluginRegistryCallback = pluginRegistryCallback + fun getFlutterEngine(context: Context): FlutterEngine { + return flutterEngine ?: FlutterEngine(context).also { + flutterEngine = it + pluginRegistrantCallback?.invoke(it) + } } } - @Deprecated(message = "Use the Android v2 embedding method.") + @Deprecated("Use the Android embedding v2 instead") private class ProxyLifecycleProvider internal constructor(activity: Activity) : Application.ActivityLifecycleCallbacks, LifecycleOwner { override val lifecycle = LifecycleRegistry(this) private val registrarActivityHashCode: Int = activity.hashCode() diff --git a/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt b/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt index b378e4a..0f64dfa 100644 --- a/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt +++ b/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt @@ -11,7 +11,6 @@ import com.icapps.background_location_tracker.utils.SharedPrefsUtil import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.embedding.engine.loader.FlutterLoader -import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.view.FlutterCallbackInformation @@ -24,10 +23,7 @@ internal object FlutterBackgroundManager { private fun getInitializedFlutterEngine(ctx: Context): FlutterEngine { Logger.debug("BackgroundManager", "Creating new engine") - val engine = FlutterEngine(ctx) - //Backwards compatibility with v1. We register all the user's plugins. - BackgroundLocationTrackerPlugin.pluginRegistryCallback?.registerWith(ShimPluginRegistry(engine)) - return engine + return BackgroundLocationTrackerPlugin.getFlutterEngine(ctx) } fun sendLocation(ctx: Context, location: Location) { diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 74a78b9..40b3c14 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + // In a modern plugin using FlutterPluginBinding, plugins are automatically + // registered through the FlutterEngine's plugin registry + GeneratedPluginRegistrant.registerWith(engine) + } + } +} \ No newline at end of file diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 3316712..6205f4d 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -9,9 +9,13 @@ import background_location_tracker didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) + + // Register plugins for background execution - this call is kept for backward compatibility + // With modern Flutter versions (1.12+), this is not required as the plugin uses FlutterPluginBinding BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in GeneratedPluginRegistrant.register(with: registry) } + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } diff --git a/ios/Classes/BackgroundLocationTrackerPlugin.m b/ios/Classes/BackgroundLocationTrackerPlugin.m index bc23b12..d53c728 100644 --- a/ios/Classes/BackgroundLocationTrackerPlugin.m +++ b/ios/Classes/BackgroundLocationTrackerPlugin.m @@ -14,6 +14,8 @@ + (void)registerWithRegistrar:(NSObject*)registrar { [SwiftBackgroundLocationTrackerPlugin registerWithRegistrar:registrar]; } +// This method is deprecated and will be removed in a future version +// Use the iOS embedding v2 method instead + (void)setPluginRegistrantCallback:(FlutterPluginRegistrantCallback)callback { [SwiftBackgroundLocationTrackerPlugin setPluginRegistrantCallback:callback]; } diff --git a/ios/Classes/ForegroundChannel.swift b/ios/Classes/ForegroundChannel.swift index 07c59da..eb2fa35 100644 --- a/ios/Classes/ForegroundChannel.swift +++ b/ios/Classes/ForegroundChannel.swift @@ -25,8 +25,15 @@ public class ForegroundChannel : NSObject { private let userDefaults = UserDefaults.standard + // This method is kept for backwards compatibility but marked as deprecated + @available(*, deprecated, message: "Use createMethodChannel(binaryMessenger:) instead") public static func getMethodChannel(with registrar: FlutterPluginRegistrar) -> FlutterMethodChannel { - return FlutterMethodChannel(name: FOREGROUND_CHANNEL_NAME, binaryMessenger: registrar.messenger()) + return createMethodChannel(binaryMessenger: registrar.messenger()) + } + + // New method that works with FlutterBinaryMessenger directly + public static func createMethodChannel(binaryMessenger: FlutterBinaryMessenger) -> FlutterMethodChannel { + return FlutterMethodChannel(name: FOREGROUND_CHANNEL_NAME, binaryMessenger: binaryMessenger) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { diff --git a/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift b/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift index 2391e5e..fb1e4da 100644 --- a/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift +++ b/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift @@ -17,7 +17,8 @@ public class SwiftBackgroundLocationTrackerPlugin: FlutterPluginAppLifeCycleDele private static var initializedBackgroundCallbacksStarted = false private static var locationData: [String: Any]? = nil - private static var flutterPluginRegistrantCallback: FlutterPluginRegistrantCallback? + // This will store the plugin that registered engines + private static var pluginRegistrants: [(FlutterEngine) -> Void] = [] private let locationManager = LocationManager.shared() @@ -27,12 +28,13 @@ extension SwiftBackgroundLocationTrackerPlugin: FlutterPlugin { @objc public static func setPluginRegistrantCallback(_ callback: @escaping FlutterPluginRegistrantCallback) { - flutterPluginRegistrantCallback = callback + // Store the callback in our new pluginRegistrants array + pluginRegistrants.append(callback) } public static func register(with registrar: FlutterPluginRegistrar) { foregroundChannel = ForegroundChannel() - let methodChannel = ForegroundChannel.getMethodChannel(with: registrar) + let methodChannel = ForegroundChannel.createMethodChannel(binaryMessenger: registrar.messenger()) let instance = SwiftBackgroundLocationTrackerPlugin() registrar.addMethodCallDelegate(instance, channel: methodChannel) registrar.addApplicationDelegate(instance) @@ -61,7 +63,10 @@ extension SwiftBackgroundLocationTrackerPlugin: FlutterPlugin { CustomLogger.log(message: "FlutterEngine.run returned `\(success)`") if success { - SwiftBackgroundLocationTrackerPlugin.flutterPluginRegistrantCallback?(flutterEngine) + // Run all the registered plugin registrants + for registrant in pluginRegistrants { + registrant(flutterEngine) + } self.flutterEngine = flutterEngine } else { CustomLogger.log(message: "FlutterEngine.run returned `false` we will cleanup the flutterEngine") From 545336c4c588821701240edd7135f17791541c7d Mon Sep 17 00:00:00 2001 From: Muhammad Amin <105256309+MuhammedAm1n@users.noreply.github.com> Date: Tue, 6 May 2025 11:18:09 +0300 Subject: [PATCH 2/2] Update to Flutter Plugin V2 embedding; deprecate old methods for background execution --- CHANGELOG.md | 6 ++ README.md | 24 ++++- .../BackgroundLocationTrackerPlugin.kt | 94 ++++++++----------- .../flutter/FlutterBackgroundManager.kt | 6 +- .../android/app/src/main/AndroidManifest.xml | 2 +- .../kotlin/com/example/example/Application.kt | 24 +++++ example/ios/Runner/AppDelegate.swift | 4 + ios/Classes/BackgroundLocationTrackerPlugin.m | 2 + ios/Classes/ForegroundChannel.swift | 9 +- ...SwiftBackgroundLocationTrackerPlugin.swift | 13 ++- 10 files changed, 113 insertions(+), 71 deletions(-) create mode 100644 example/android/app/src/main/kotlin/com/example/example/Application.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 16ddecb..2e89801 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 1.6.0 - 2025-05-06 +- Updated to use the modern FlutterPlugin.FlutterPluginBinding pattern +- Deprecated Registrar, PluginRegistrantCallback, and ShimPluginRegistry usage +- Added backward compatibility for older Flutter versions +- Improved handling of plugin registration in background execution + ## 1.5.0 - 2025-01-29 - Updated gradle dependencies diff --git a/README.md b/README.md index 35abef4..252df3d 100644 --- a/README.md +++ b/README.md @@ -53,8 +53,6 @@ Or add the info to the Info.plist ### Update the AppDelegate -Make sure you call the `setPluginRegistrantCallback` so other plugins can be accessed in the background. - ``` import UIKit import Flutter @@ -65,6 +63,8 @@ import background_location_tracker override func application(_ application: UIApplication,didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { GeneratedPluginRegistrant.register(with: self) + // Register plugins for background execution - this method is deprecated + // but kept for backward compatibility BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in GeneratedPluginRegistrant.register(with: registry) } @@ -124,7 +124,21 @@ Future stopLocationTracking() async { ``` 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 +- Android: This plugin now uses Flutter's Plugin V2 embedding pattern (FlutterPluginBinding) so you don't need to set a manual plugin registrant callback. +- iOS: For compatibility with older Flutter versions, the setPluginRegistrantCallback is still available but will be removed in a future version. + +If you're using Flutter 1.12 or later, the plugin should work out of the box with the V2 embedding. ``` + +## Migration Guide + +### Upgrading from older versions + +This plugin has been updated to use the modern Flutter Plugin V2 embedding pattern with FlutterPluginBinding. If you're using Flutter 1.12 or later, you don't need to make any changes to your app's code. + +For backward compatibility, the older methods are still available but marked as deprecated: + +- `BackgroundLocationTrackerPlugin.setPluginRegistrantCallback` on Android +- `BackgroundLocationTrackerPlugin.setPluginRegistrantCallback` on iOS + +These methods will be removed in a future version of the plugin. diff --git a/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt b/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt index d3cffa3..0b6593a 100644 --- a/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt +++ b/android/src/main/kotlin/com/icapps/background_location_tracker/BackgroundLocationTrackerPlugin.kt @@ -19,17 +19,29 @@ import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler import io.flutter.plugin.common.MethodChannel.Result -import io.flutter.plugin.common.PluginRegistry +import io.flutter.embedding.engine.plugins.FlutterPlugin.FlutterPluginBinding +import io.flutter.embedding.engine.FlutterEngine class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, ActivityAware { private var lifecycle: Lifecycle? = null private var methodCallHelper: MethodCallHelper? = null - - override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) { - registerBackgroundLocationManager(binding.binaryMessenger, binding.applicationContext) + private var channel: MethodChannel? = null + private var applicationContext: Context? = null + + override fun onAttachedToEngine(binding: FlutterPluginBinding) { + applicationContext = binding.applicationContext + channel = MethodChannel(binding.binaryMessenger, FOREGROUND_CHANNEL_NAME) + channel?.setMethodCallHandler(this) + + if (methodCallHelper == null) { + methodCallHelper = MethodCallHelper.getInstance(binding.applicationContext) + } } - override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) { + override fun onDetachedFromEngine(binding: FlutterPluginBinding) { + channel?.setMethodCallHandler(null) + channel = null + applicationContext = null } override fun onMethodCall(call: MethodCall, result: Result) { @@ -38,10 +50,7 @@ class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, Activi override fun onAttachedToActivity(binding: ActivityPluginBinding) { lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding) - if (methodCallHelper == null) { - ActivityCounter.attach(binding.activity) - methodCallHelper = MethodCallHelper.getInstance(binding.activity.applicationContext) - } + ActivityCounter.attach(binding.activity) methodCallHelper?.let { lifecycle?.removeObserver(it) lifecycle?.addObserver(it) @@ -50,67 +59,42 @@ class BackgroundLocationTrackerPlugin : FlutterPlugin, MethodCallHandler, Activi override fun onDetachedFromActivity() {} - override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {} + override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) { + onAttachedToActivity(binding) + } - override fun onDetachedFromActivityForConfigChanges() {} + override fun onDetachedFromActivityForConfigChanges() { + onDetachedFromActivity() + } companion object { private const val TAG = "FBLTPlugin" private const val FOREGROUND_CHANNEL_NAME = "com.icapps.background_location_tracker/foreground_channel" - var pluginRegistryCallback: PluginRegistry.PluginRegistrantCallback? = null + // New static properties for background execution + private var flutterEngine: FlutterEngine? = null - @JvmStatic - private fun registerBackgroundLocationManager(messenger: BinaryMessenger, ctx: Context) { - val channel = MethodChannel(messenger, FOREGROUND_CHANNEL_NAME) - channel.setMethodCallHandler(BackgroundLocationTrackerPlugin().apply { - if (methodCallHelper == null) { - methodCallHelper = MethodCallHelper.getInstance(ctx) - } - methodCallHelper?.let { - lifecycle?.removeObserver(it) - lifecycle?.addObserver(it) - } - }) - } + // For compatibility with older plugins + @Deprecated("Use FlutterEngine's plugin registry instead") + private var pluginRegistrantCallback: ((FlutterEngine) -> Unit)? = null @JvmStatic - fun registerWith(registrar: PluginRegistry.Registrar) { - val activity = registrar.activity() - if (activity == null) { - Logger.debug(TAG, "Activity should not be null while registering this plugin") - return - } - - val lifecycle: Lifecycle = if (activity is LifecycleOwner) { - (activity as LifecycleOwner).lifecycle - } else { - Logger.debug(TAG, "Your activity has not implemented a lifecycle owner. We will create one for you.") - @Suppress("DEPRECATION") - ProxyLifecycleProvider(activity).lifecycle - } - - ActivityCounter.attach(activity) - val channel = MethodChannel(registrar.messenger(), FOREGROUND_CHANNEL_NAME) - channel.setMethodCallHandler(BackgroundLocationTrackerPlugin().apply { - if (methodCallHelper == null) { - methodCallHelper = MethodCallHelper.getInstance(registrar.activeContext()) - } - methodCallHelper?.let { - lifecycle.removeObserver(it) - lifecycle.addObserver(it) - } - }) + @Deprecated("Use the Android embedding v2 instead") + fun setPluginRegistrantCallback(callback: ((FlutterEngine) -> Unit)) { + pluginRegistrantCallback = callback } - @Deprecated(message = "Use the Android v2 embedding method.") + // Method to get or create the Flutter engine for background execution @JvmStatic - fun setPluginRegistrantCallback(pluginRegistryCallback: PluginRegistry.PluginRegistrantCallback) { - BackgroundLocationTrackerPlugin.pluginRegistryCallback = pluginRegistryCallback + fun getFlutterEngine(context: Context): FlutterEngine { + return flutterEngine ?: FlutterEngine(context).also { + flutterEngine = it + pluginRegistrantCallback?.invoke(it) + } } } - @Deprecated(message = "Use the Android v2 embedding method.") + @Deprecated("Use the Android embedding v2 instead") private class ProxyLifecycleProvider internal constructor(activity: Activity) : Application.ActivityLifecycleCallbacks, LifecycleOwner { override val lifecycle = LifecycleRegistry(this) private val registrarActivityHashCode: Int = activity.hashCode() diff --git a/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt b/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt index b378e4a..0f64dfa 100644 --- a/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt +++ b/android/src/main/kotlin/com/icapps/background_location_tracker/flutter/FlutterBackgroundManager.kt @@ -11,7 +11,6 @@ import com.icapps.background_location_tracker.utils.SharedPrefsUtil import io.flutter.embedding.engine.FlutterEngine import io.flutter.embedding.engine.dart.DartExecutor import io.flutter.embedding.engine.loader.FlutterLoader -import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.view.FlutterCallbackInformation @@ -24,10 +23,7 @@ internal object FlutterBackgroundManager { private fun getInitializedFlutterEngine(ctx: Context): FlutterEngine { Logger.debug("BackgroundManager", "Creating new engine") - val engine = FlutterEngine(ctx) - //Backwards compatibility with v1. We register all the user's plugins. - BackgroundLocationTrackerPlugin.pluginRegistryCallback?.registerWith(ShimPluginRegistry(engine)) - return engine + return BackgroundLocationTrackerPlugin.getFlutterEngine(ctx) } fun sendLocation(ctx: Context, location: Location) { diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml index 74a78b9..40b3c14 100644 --- a/example/android/app/src/main/AndroidManifest.xml +++ b/example/android/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ + // In a modern plugin using FlutterPluginBinding, plugins are automatically + // registered through the FlutterEngine's plugin registry + GeneratedPluginRegistrant.registerWith(engine) + } + } +} \ No newline at end of file diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift index 3316712..6205f4d 100644 --- a/example/ios/Runner/AppDelegate.swift +++ b/example/ios/Runner/AppDelegate.swift @@ -9,9 +9,13 @@ import background_location_tracker didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { GeneratedPluginRegistrant.register(with: self) + + // Register plugins for background execution - this call is kept for backward compatibility + // With modern Flutter versions (1.12+), this is not required as the plugin uses FlutterPluginBinding BackgroundLocationTrackerPlugin.setPluginRegistrantCallback { registry in GeneratedPluginRegistrant.register(with: registry) } + return super.application(application, didFinishLaunchingWithOptions: launchOptions) } } diff --git a/ios/Classes/BackgroundLocationTrackerPlugin.m b/ios/Classes/BackgroundLocationTrackerPlugin.m index bc23b12..d53c728 100644 --- a/ios/Classes/BackgroundLocationTrackerPlugin.m +++ b/ios/Classes/BackgroundLocationTrackerPlugin.m @@ -14,6 +14,8 @@ + (void)registerWithRegistrar:(NSObject*)registrar { [SwiftBackgroundLocationTrackerPlugin registerWithRegistrar:registrar]; } +// This method is deprecated and will be removed in a future version +// Use the iOS embedding v2 method instead + (void)setPluginRegistrantCallback:(FlutterPluginRegistrantCallback)callback { [SwiftBackgroundLocationTrackerPlugin setPluginRegistrantCallback:callback]; } diff --git a/ios/Classes/ForegroundChannel.swift b/ios/Classes/ForegroundChannel.swift index 07c59da..eb2fa35 100644 --- a/ios/Classes/ForegroundChannel.swift +++ b/ios/Classes/ForegroundChannel.swift @@ -25,8 +25,15 @@ public class ForegroundChannel : NSObject { private let userDefaults = UserDefaults.standard + // This method is kept for backwards compatibility but marked as deprecated + @available(*, deprecated, message: "Use createMethodChannel(binaryMessenger:) instead") public static func getMethodChannel(with registrar: FlutterPluginRegistrar) -> FlutterMethodChannel { - return FlutterMethodChannel(name: FOREGROUND_CHANNEL_NAME, binaryMessenger: registrar.messenger()) + return createMethodChannel(binaryMessenger: registrar.messenger()) + } + + // New method that works with FlutterBinaryMessenger directly + public static func createMethodChannel(binaryMessenger: FlutterBinaryMessenger) -> FlutterMethodChannel { + return FlutterMethodChannel(name: FOREGROUND_CHANNEL_NAME, binaryMessenger: binaryMessenger) } public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { diff --git a/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift b/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift index 2391e5e..fb1e4da 100644 --- a/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift +++ b/ios/Classes/SwiftBackgroundLocationTrackerPlugin.swift @@ -17,7 +17,8 @@ public class SwiftBackgroundLocationTrackerPlugin: FlutterPluginAppLifeCycleDele private static var initializedBackgroundCallbacksStarted = false private static var locationData: [String: Any]? = nil - private static var flutterPluginRegistrantCallback: FlutterPluginRegistrantCallback? + // This will store the plugin that registered engines + private static var pluginRegistrants: [(FlutterEngine) -> Void] = [] private let locationManager = LocationManager.shared() @@ -27,12 +28,13 @@ extension SwiftBackgroundLocationTrackerPlugin: FlutterPlugin { @objc public static func setPluginRegistrantCallback(_ callback: @escaping FlutterPluginRegistrantCallback) { - flutterPluginRegistrantCallback = callback + // Store the callback in our new pluginRegistrants array + pluginRegistrants.append(callback) } public static func register(with registrar: FlutterPluginRegistrar) { foregroundChannel = ForegroundChannel() - let methodChannel = ForegroundChannel.getMethodChannel(with: registrar) + let methodChannel = ForegroundChannel.createMethodChannel(binaryMessenger: registrar.messenger()) let instance = SwiftBackgroundLocationTrackerPlugin() registrar.addMethodCallDelegate(instance, channel: methodChannel) registrar.addApplicationDelegate(instance) @@ -61,7 +63,10 @@ extension SwiftBackgroundLocationTrackerPlugin: FlutterPlugin { CustomLogger.log(message: "FlutterEngine.run returned `\(success)`") if success { - SwiftBackgroundLocationTrackerPlugin.flutterPluginRegistrantCallback?(flutterEngine) + // Run all the registered plugin registrants + for registrant in pluginRegistrants { + registrant(flutterEngine) + } self.flutterEngine = flutterEngine } else { CustomLogger.log(message: "FlutterEngine.run returned `false` we will cleanup the flutterEngine")