diff --git a/android/app/build.gradle b/android/app/build.gradle index 0f7185a..2c8f670 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -1,10 +1,11 @@ plugins { id "com.android.application" id "org.jetbrains.kotlin.android" + // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id "dev.flutter.flutter-gradle-plugin" - // Apply React Native plugin + // React Native plugin // See: https://github.com/react-native-community/template/blob/main/template/android/app/build.gradle id 'com.facebook.react' } @@ -31,7 +32,11 @@ android { namespace = "com.example.flutter_brownfield_app" buildToolsVersion rootProject.ext.buildToolsVersion + + // React Native and Flutter share the same compileSdkVersion = 34 compileSdk rootProject.ext.compileSdkVersion // flutter.compileSdkVersion = 34 + + // Using React Native NDK version ndkVersion rootProject.ext.ndkVersion // flutter.ndkVersion = "23.1.7779620 compileOptions { @@ -67,12 +72,12 @@ flutter { source = "../.." } -// React Native setup +// React Native: dependencies // See: https://github.com/react-native-community/template/blob/main/template/android/app/build.gradle dependencies { - implementation 'com.facebook.react:react-android' + implementation 'com.facebook.react:react-android' implementation 'com.facebook.react:hermes-android' } -// Enable React Native autolinking +// React Native: enable autolinking apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project) \ No newline at end of file diff --git a/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainActivity.kt b/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainActivity.kt index f18f47d..f4b24d1 100644 --- a/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainActivity.kt +++ b/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainActivity.kt @@ -10,7 +10,9 @@ import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugin.common.MethodChannel /** - * Basic FlutterActivity extended with React Native lifecycle hooks/ + * Basic FlutterActivity extended with React Native lifecycle hooks. + * + * This is hosting Flutter application as well as can draw React Native views using ReactView. * * See: * - https://reactnative.dev/docs/integration-with-existing-apps @@ -39,7 +41,7 @@ class MainActivity: FlutterActivity(), DefaultHardwareBackBtnHandler { .registry .registerViewFactory("react_view", ReactViewFactory()) - // Register MethodChannel, so we can call it from Flutter code. + // Register MethodChannel, so we can call it from Flutter code from native. MethodChannel(flutterEngine.dartExecutor.binaryMessenger, FLUTTER_CHANNEL).setMethodCallHandler { call, result -> if (call.method == "navigateToReactNative") { @@ -52,6 +54,8 @@ class MainActivity: FlutterActivity(), DefaultHardwareBackBtnHandler { } } + // This is used to start React Native component in a separate Activity for usage with React Navigation. + // Do not use this if you just want to embed ReactView in Flutter screen. private fun startReactNativeActivity(moduleName: String) { val intent = Intent(this, ReactActivity::class.java).apply { putExtra("moduleName", moduleName) diff --git a/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainApplication.kt b/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainApplication.kt index 37bf7a4..f453448 100644 --- a/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainApplication.kt +++ b/android/app/src/main/kotlin/com/example/flutter_brownfield_app/MainApplication.kt @@ -8,6 +8,7 @@ import com.facebook.react.defaults.DefaultReactNativeHost import com.facebook.soloader.SoLoader class MainApplication: Application(), ReactApplication { + // React Native runtime override val reactNativeHost = object : DefaultReactNativeHost(this) { override fun getPackages(): List { diff --git a/android/build.gradle b/android/build.gradle index 7bee559..6d41cff 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -28,15 +28,15 @@ buildscript { ndkVersion = "26.1.10909125" kotlinVersion = "1.9.22" } - repositories { - google() - mavenCentral() - } - dependencies { + repositories { + google() + mavenCentral() + } + dependencies { classpath("com.android.tools.build:gradle") classpath("com.facebook.react:react-native-gradle-plugin") classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") - } + } } apply plugin: "com.facebook.react.rootproject" \ No newline at end of file diff --git a/android/settings.gradle b/android/settings.gradle index 6344c9a..a29e2b3 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -20,13 +20,13 @@ plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" id "com.android.application" version '8.2.2' apply false - // Plugin version matching React Native config: + // Kotlin plugin version needs to match React Native config: // https://github.com/react-native-community/template/blob/main/template/android/settings.gradle id "org.jetbrains.kotlin.android" version "1.9.22" apply false } include ":app" -// Configure React Native auto-linking +// React Native: configure autolinking includeBuild('../node_modules/@react-native/gradle-plugin') apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) \ No newline at end of file diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index df1833f..56fd133 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -8,6 +8,7 @@ import UIKit _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { + // Register MethodChannel, so we can call it from Flutter code from native. let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let channel = FlutterMethodChannel( name: "flutter-brownfield/native", @@ -21,6 +22,7 @@ import UIKit } switch call.method { + // Trigger navigation to separate React Native ViewController for usage with React Navigation case "navigateToReactNative": let args = call.arguments as! [String: Any]; let moduleName = args["moduleName"] as! String; @@ -44,6 +46,7 @@ import UIKit withId: "react_view" ) + // Load React Native to BridgeManager holder. BridgeManager.shared.loadReactNative(launchOptions: launchOptions) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } @@ -56,12 +59,14 @@ import UIKit func presentReactNativeViewController( moduleName: String ) { - let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios")! + guard let bridge = BridgeManager.shared.bridge else { + fatalError("BridgeManager.shared.bridge is nil. Make sure to call BridgeManager.shared.loadReactNative() before calling presentReactNativeViewController.") + } + let rootView = RCTRootView( - bundleURL: jsCodeLocation, + bridge: bridge, moduleName: moduleName, - initialProperties: [:] as [NSObject : AnyObject], - launchOptions: nil + initialProperties: [:] ) let viewController = UIViewController()