diff --git a/android/app/build.gradle b/android/app/build.gradle index 3b2fb467..6b23e376 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -126,6 +126,13 @@ android { // pickFirst 'lib/armeabi-v7a/libc++_shared.so' // pickFirst 'lib/arm64-v8a/libc++_shared.so' // pickFirst '**/*.so' + + + pickFirst 'lib/x86/libc++_shared.so' + pickFirst 'lib/x86_64/libc++_shared.so' + pickFirst 'lib/armeabi-v7a/libc++_shared.so' + pickFirst 'lib/arm64-v8a/libc++_shared.so' + } diff --git a/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift b/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift new file mode 100644 index 00000000..f39ace2e --- /dev/null +++ b/ios/Runner/Helper/HMGPenguinInPlatformBridge.swift @@ -0,0 +1,71 @@ +// +// HMGPenguinInPlatformBridge.swift +// Runner +// +// Created by Haroon Amjad on 13/08/2024. +// + +import Foundation + +var flutterMethodChannelPenguinIn:FlutterMethodChannel? = nil +fileprivate var mainViewController:MainFlutterVC! + +class HMGPenguinInPlatformBridge{ + + private let channelName = "launch_penguin_ui" + private static var shared_:HMGPenguinInPlatformBridge? + + class func initialize(flutterViewController:MainFlutterVC){ + shared_ = HMGPenguinInPlatformBridge() + mainViewController = flutterViewController + shared_?.openChannel() + } + + func shared() -> HMGPenguinInPlatformBridge{ + assert((HMGPenguinInPlatformBridge.shared_ != nil), "HMGPenguinInPlatformBridge is not initialized, call initialize(mainViewController:MainFlutterVC) function first.") + return HMGPenguinInPlatformBridge.shared_! + } + + private func openChannel(){ + flutterMethodChannelPenguinIn = FlutterMethodChannel(name: channelName, binaryMessenger: mainViewController.binaryMessenger) + + flutterMethodChannelPenguinIn?.setMethodCallHandler { (methodCall, result) in + print("Called function \(methodCall.method)") + + if let arguments = methodCall.arguments as Any? { + if methodCall.method == "launchPenguin"{ + self.launchPenguinView(arguments: arguments, result: result) + } + } else { + result(FlutterError(code: "INVALID_ARGUMENT", message: "Storyboard name is required", details: nil)) + } + } + } + + private func launchPenguinView(arguments: Any, result: @escaping FlutterResult) { + let penguinView = PenguinView( + frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height), + viewIdentifier: 0, + arguments: arguments, + binaryMessenger: mainViewController.binaryMessenger + ) + + let penguinUIView = penguinView.view() + penguinUIView.frame = mainViewController.view.bounds + penguinUIView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + + mainViewController.view.addSubview(penguinUIView) + +// if mainViewController?.isMovingFromParent ?? false { +// result(nil) +// } +// if self.isMovingFromParent { +// result?(nil) +// } +// else { result(nil) // Call result to indicate the method was successfully handled +// } + + + + } +} diff --git a/ios/Runner/Penguin/PenguinModel.swift b/ios/Runner/Penguin/PenguinModel.swift new file mode 100644 index 00000000..1676b2f9 --- /dev/null +++ b/ios/Runner/Penguin/PenguinModel.swift @@ -0,0 +1,67 @@ +// +// PenguinModel.swift +// Runner +// +// Created by Amir on 06/08/2024. +// + +import Foundation + +// Define the model class +struct PenguinModel { + let baseURL: String + let dataURL: String + let dataServiceName: String + let positionURL: String + let clientKey: String + let storyboardName: String + let mapBoxKey: String + let clientID: String + let positionServiceName: String + let username: String + let isSimulationModeEnabled: Bool + let isShowUserName: Bool + let isUpdateUserLocationSmoothly: Bool + let isEnableReportIssue: Bool + let languageCode: String + + // Initialize the model from a dictionary + init?(from dictionary: [String: Any]) { + guard + let baseURL = dictionary["baseURL"] as? String, + let dataURL = dictionary["dataURL"] as? String, + let dataServiceName = dictionary["dataServiceName"] as? String, + let positionURL = dictionary["positionURL"] as? String, + let clientKey = dictionary["clientKey"] as? String, + let storyboardName = dictionary["storyboardName"] as? String, + let mapBoxKey = dictionary["mapBoxKey"] as? String, + let clientID = dictionary["clientID"] as? String, + let positionServiceName = dictionary["positionServiceName"] as? String, + let username = dictionary["username"] as? String, + let isSimulationModeEnabled = dictionary["isSimulationModeEnabled"] as? Bool, + let isShowUserName = dictionary["isShowUserName"] as? Bool, + let isUpdateUserLocationSmoothly = dictionary["isUpdateUserLocationSmoothly"] as? Bool, + let isEnableReportIssue = dictionary["isEnableReportIssue"] as? Bool, + let languageCode = dictionary["languageCode"] as? String + else { + return nil + } + + self.baseURL = baseURL + self.dataURL = dataURL + self.dataServiceName = dataServiceName + self.positionURL = positionURL + self.clientKey = clientKey + self.storyboardName = storyboardName + self.mapBoxKey = mapBoxKey + self.clientID = clientID + self.positionServiceName = positionServiceName + self.username = username + self.isSimulationModeEnabled = isSimulationModeEnabled + self.isEnableReportIssue = isEnableReportIssue + self.isShowUserName = isShowUserName + self.isUpdateUserLocationSmoothly = isUpdateUserLocationSmoothly + self.languageCode = languageCode + + } +} diff --git a/ios/Runner/Penguin/PenguinPlugin.swift b/ios/Runner/Penguin/PenguinPlugin.swift new file mode 100644 index 00000000..029bec35 --- /dev/null +++ b/ios/Runner/Penguin/PenguinPlugin.swift @@ -0,0 +1,31 @@ +// +// BlueGpsPlugin.swift +// Runner +// +// Created by Penguin . +// + +//import Foundation +//import Flutter +// +///** +// * A Flutter plugin for integrating Penguin SDK functionality. +// * This class registers a view factory with the Flutter engine to create native views. +// */ +//class PenguinPlugin: NSObject, FlutterPlugin { +// +// /** +// * Registers the plugin with the Flutter engine. +// * +// * @param registrar The [FlutterPluginRegistrar] used to register the plugin. +// * This method is called when the plugin is initialized, and it sets up the communication +// * between Flutter and native code. +// */ +// public static func register(with registrar: FlutterPluginRegistrar) { +// // Create an instance of PenguinViewFactory with the binary messenger from the registrar +// let factory = PenguinViewFactory(messenger: registrar.messenger()) +// +// // Register the view factory with a unique ID for use in Flutter code +// registrar.register(factory, withId: "penguin_native") +// } +//} diff --git a/ios/Runner/Penguin/PenguinView.swift b/ios/Runner/Penguin/PenguinView.swift new file mode 100644 index 00000000..c54ac70a --- /dev/null +++ b/ios/Runner/Penguin/PenguinView.swift @@ -0,0 +1,164 @@ +// +// BlueGpsView.swift +// Runner +// +// Created by Penguin. +// + +import Foundation +import UIKit +import Flutter +import PenNavUI + +import Foundation +import Flutter +import UIKit + +/** + * A custom Flutter platform view for displaying Penguin UI components. + * This class integrates with the Penguin navigation SDK and handles UI events. + */ +class PenguinView: NSObject, FlutterPlatformView, PIEventsDelegate, PenNavInitializationDelegate { + + // The main view displayed within the platform view + private var _view: UIView + private var model: PenguinModel? + + + /** + * Initializes the PenguinView with the provided parameters. + * + * @param frame The frame of the view, specifying its size and position. + * @param viewId A unique identifier for this view instance. + * @param args Optional arguments provided for creating the view. + * @param messenger The [FlutterBinaryMessenger] used for communication with Dart. + */ + init( + frame: CGRect, + viewIdentifier viewId: Int64, + arguments args: Any?, + binaryMessenger messenger: FlutterBinaryMessenger? + ) { + _view = UIView() + super.init() + + // Get the screen's width and height to set the view's frame + let screenWidth = UIScreen.main.bounds.width + let screenHeight = UIScreen.main.bounds.height + + // Uncomment to set the background color of the view + // _view.backgroundColor = UIColor.red + + // Set the frame of the view to cover the entire screen + _view.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight) + print("========Inside Penguin View ========") + print(args) + guard let arguments = args as? [String: Any] else { + print("Error: Arguments are not in the expected format.") + return + } + print("===== i got tha Args=======") + + // Initialize the model from the arguments + if let penguinModel = PenguinModel(from: arguments) { + self.model = penguinModel + initPenguin(args: penguinModel) + } else { + print("Error: Failed to initialize PenguinModel from arguments") + } + // Initialize the Penguin SDK with required configurations + // initPenguin( arguments: args) + } + + /** + * Initializes the Penguin SDK with custom configuration settings. + */ + func initPenguin(args: PenguinModel) { + // Set the initialization delegate to handle SDK initialization events + PenNavUIManager.shared.initializationDelegate = self + // Configure the Penguin SDK with necessary parameters + PenNavUIManager.shared + .setClientKey(args.clientKey) + .setClientID(args.clientID) + .setUsername(args.username) + .setSimulationModeEnabled(isEnable: args.isSimulationModeEnabled) + .setBaseURL(dataURL: args.dataURL, positionURL: args.baseURL) + .setServiceName(dataServiceName: args.dataServiceName, positionServiceName: args.positionServiceName) + .setIsShowUserName(args.isShowUserName) + .setIsUpdateUserLocationSmoothly(args.isUpdateUserLocationSmoothly) + .setEnableReportIssue(enable: args.isEnableReportIssue) + .setLanguage(args.languageCode) + .setBackButtonVisibility(true) + .build() + } + + /** + * Returns the main view associated with this platform view. + * + * @return The UIView instance that represents this platform view. + */ + func view() -> UIView { + return _view + } + + // MARK: - PIEventsDelegate Methods + + /** + * Called when the Penguin UI is dismissed. + */ + func onPenNavUIDismiss() { + // Handle UI dismissal if needed + print("====== onPenNavUIDismiss =========") + + + + self.view().removeFromSuperview() + + + } + + /** + * Called when a report issue is generated. + * + * @param issue The type of issue reported. + */ + func onReportIssue(_ issue: PenNavUI.IssueType) { + // Handle report issue events if needed + print("====== onReportIssueError =========") + } + + /** + * Called when the Penguin UI setup is successful. + */ + func onPenNavSuccess() { + print("====== onPenNavSuccess =========") + // Obtain the FlutterViewController instance + let controller: FlutterViewController = UIApplication.shared.windows.first?.rootViewController as! FlutterViewController + + print("====== after contoller onPenNavSuccess =========") + + // Set the events delegate to handle SDK events + PenNavUIManager.shared.eventsDelegate = self + + print("====== after eventsDelegate onPenNavSuccess =========") + + // Present the Penguin UI on top of the Flutter view controller + PenNavUIManager.shared.present(root: controller, view: _view) + + print("====== after present onPenNavSuccess =========") + } + + /** + * Called when there is an initialization error with the Penguin UI. + * + * @param errorType The type of initialization error. + * @param errorDescription A description of the error. + */ + func onPenNavInitializationError(errorType: PenNavUI.PenNavUIError, errorDescription: String) { + // Handle initialization errors if needed + + print("onPenNavInitializationErrorType: \(errorType.rawValue)") + print("onPenNavInitializationError: \(errorDescription)") + + } +} diff --git a/ios/Runner/Penguin/PenguinViewFactory.swift b/ios/Runner/Penguin/PenguinViewFactory.swift new file mode 100644 index 00000000..a88bb5d0 --- /dev/null +++ b/ios/Runner/Penguin/PenguinViewFactory.swift @@ -0,0 +1,59 @@ +// +// BlueGpsViewFactory.swift +// Runner +// +// Created by Penguin . +// + +import Foundation +import Flutter + +/** + * A factory class for creating instances of [PenguinView]. + * This class implements `FlutterPlatformViewFactory` to create and manage native views. + */ +class PenguinViewFactory: NSObject, FlutterPlatformViewFactory { + + // The binary messenger used for communication with the Flutter engine + private var messenger: FlutterBinaryMessenger + + /** + * Initializes the PenguinViewFactory with the given messenger. + * + * @param messenger The [FlutterBinaryMessenger] used to communicate with Dart code. + */ + init(messenger: FlutterBinaryMessenger) { + self.messenger = messenger + super.init() + } + + /** + * Creates a new instance of [PenguinView]. + * + * @param frame The frame of the view, specifying its size and position. + * @param viewId A unique identifier for this view instance. + * @param args Optional arguments provided for creating the view. + * @return An instance of [PenguinView] configured with the provided parameters. + */ + func create( + withFrame frame: CGRect, + viewIdentifier viewId: Int64, + arguments args: Any? + ) -> FlutterPlatformView { + return PenguinView( + frame: frame, + viewIdentifier: viewId, + arguments: args, + binaryMessenger: messenger) + } + + /** + * Returns the codec used for encoding and decoding method channel arguments. + * This method is required when `arguments` in `create` is not `nil`. + * + * @return A [FlutterMessageCodec] instance used for serialization. + */ + public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { + return FlutterStandardMessageCodec.sharedInstance() + } +}