New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reduce friction encountered when adding Flutter to existing apps #14821

Closed
mit-mit opened this Issue Feb 22, 2018 · 63 comments

Comments

@mit-mit
Member

mit-mit commented Feb 22, 2018

Flutter's templates, tooling, and runtime are currently primarily optimized for the use case of creating a new mobile application from scratch. However, several developers have expressed an interest in making it easier to add one or more Flutter "screens" to existing Android and iOS apps.

The present bug tracks reduction of general friction developers encounter when trying to accomplish this integration of Flutter into existing apps.

The detailed work for this effort is tracked in a number of more detailed issues:
https://github.com/flutter/flutter/issues?q=is%3Aopen+is%3Aissue+label%3A%22a%3A+existing-apps%22

The initial documentation for the preview support is available on our Wiki:
https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps

@packouray

This comment has been minimized.

packouray commented Mar 5, 2018

Hello,

Any news about the documentation explaining how to embed flutter views in native apps ?

Thank you very much.

@mit-mit

This comment has been minimized.

Member

mit-mit commented Mar 5, 2018

Sorry, no, not yet

@VincentH-Net

This comment has been minimized.

VincentH-Net commented Mar 5, 2018

@mit-mit My scenario is a variation of the above, aimed at enterprise apps that use .NET (Core): I would like to evaluate whether Flutter can be combined with 'classic' Xamarin.iOS and Xamarin.Android.

Flutter would be used for the UI layer (screens including image resources + navigation); Xamarin for logic, models and services. This could be a more productive alternative to Xamarin Forms.

This should be possible; Flutter can be embedded as a native iOS/Android component and Xamarin can interop with such components through bindings.
In the other direction, Xamarin code can be wrapped as native iOS/Android components with .NET Embedding, and Flutter can interop with such components.

Would the Flutter team consider this use case relevant?
If so, are there contact options to get info on Flutter embedding and interop until the documents are here?

In case anyone would like to give feedback (much appreciated!), this is my idea:

Create a single UI component in Flutter, containing all screens, static image resources, navigation and design data for an app. This component is developed and tested with high productivity in standard Flutter toolchain; and then embedded in the Xamarin apps. The complete app build & publishing would be with Xamarin toolchain.

@passsy

This comment has been minimized.

Contributor

passsy commented Mar 5, 2018

@VincentH-Net Please file a extra ticket for Xamarin interop. This issue is about integrating Flutter in an native iOS/Android app.
If you want to interact with your C# core, better checkout this issue.

@VincentH-Net

This comment has been minimized.

VincentH-Net commented Mar 6, 2018

@passsy thx, I created a new issue #15200

I would need more than interacting with C# core logic; e.g. access native device services, .NET Core NuGet libraries. Basically only the views would be Flutter.

@packouray

This comment has been minimized.

packouray commented Mar 6, 2018

Hello @mit-mit , @passsy ,

I would like to know how to embed Flutter into a native Android project. Do I have to create a Flutter project within the Android project folder and then bind everything ? Or do I have to create a Flutter project, change the android folder with my Android project folder and then bind everything ?

Thank you

@matejthetree

This comment has been minimized.

matejthetree commented Mar 7, 2018

goes as well for adding flutter lib project to existing flutter app

@specneeo

This comment has been minimized.

specneeo commented Mar 16, 2018

#15556 I hava an app which most pages written by native code. Now I want to integrate flutter, in order to write new pages. I have read flutter doc, for example:
Android

public class MainActivity extends FlutterActivity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    GeneratedPluginRegistrant.registerWith(this);
  }
}

this activity run with main.dart automatically.
But if I have mainA.dart and mainB.dart, how to assign mainA.dart to AActivity, assign mainB.dart to BActivity. Or how to specify which dart file to load?

many thanks.

@packouray

This comment has been minimized.

packouray commented Mar 16, 2018

I think you should in your native side keep only one FlutterActivity and send for example a string that correspond to the name of the view that you want to display to your main.dart using the channel.

In the flutter side I think you should implement Routes first and then get the string and use a switch to push the view that corresponds to the string.

@brholmes

This comment has been minimized.

brholmes commented Mar 21, 2018

I have been implementing flutter into my existing android project and am having an issue with FlutterActivity crashing in onCreate.

E/AndroidRuntime: FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.topsection.FlutterActivityCx}: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.flutter.view.ResourceExtractor.waitForCompletion()' on a null object reference
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2927)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2988)
at android.app.ActivityThread.-wrap14(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1631)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6682)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1520)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1410)
Caused by: java.lang.RuntimeException: java.lang.NullPointerException: Attempt to invoke virtual method 'void io.flutter.view.ResourceExtractor.waitForCompletion()' on a null object reference
at io.flutter.view.FlutterMain.ensureInitializationComplete(FlutterMain.java:212)
at io.flutter.app.FlutterActivityDelegate.onCreate(FlutterActivityDelegate.java:150)
at io.flutter.app.FlutterActivity.onCreate(FlutterActivity.java:81)
at com.topsection.FlutterActivityCx.onCreate(FlutterActivityCx.java:21)

This seems similar if not the same to #14423 but I was unsure on the fix. Any help would be greatly appreciated.

@bravekingzhang

This comment has been minimized.

bravekingzhang commented Mar 26, 2018

Could you provide us a plug-in on android studio, to let us simply integration flutter into exist android project. @mit-mit

@FredvanRijswijk

This comment has been minimized.

FredvanRijswijk commented Apr 3, 2018

Still there is no explanation how to integrate in an existing iOS or Android project...

Do you need a new Flutter project and move existing iOS project swift files into the iOS folder and build from Flutter?

We have a big app and want to start with Flutter in that existing app or the best solution is to start over and create a brand new version 100% Flutter project

@tomaszpolanski

This comment has been minimized.

tomaszpolanski commented Apr 6, 2018

I have a similar case as @FredvanRijswijk. With a large project with multiple contributors, it is a big hassle to change the project structure.

Is there a possibility to specify somewhere (e.g. pubspec.yaml) the paths to iOS and Android projects?

Currently, the alternative is (at least for Android) to move all the files to android subfolder and rename the project - that creates inconvenience with git.

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 6, 2018

We are currently experimenting with approaches that would invert that dependency, so that your existing project would include the Flutter project in some form (say, as an Android Activity). We're writing up our experiments and findings as we go along. I'll provide a link here once we have a draft wiki page.

@FredvanRijswijk

This comment has been minimized.

FredvanRijswijk commented Apr 6, 2018

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 6, 2018

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Apr 6, 2018

@tomaszpolanski

This comment has been minimized.

tomaszpolanski commented Apr 6, 2018

Thanks @mravn-google. I've already tried to integrate your solution (with small modifications, had to add FlutterMain.startInitialization) into my legacy Android app, and it works nicely.

@tomaszpolanski

This comment has been minimized.

tomaszpolanski commented Aug 15, 2018

@leemcdole For the last 4 months I've been including Flutter into 4 years old project and it's going fine - already that version is for 1 month in the stores.
But the approach we've taken is to have our iOS and Android repositories as submodules inside android and ios folders. Some work in gradle and iOS scripts were required.
This approach is not as smooth as creating fresh Flutter application but for us, it works and we are gradually adding/replacing pages in our application. Additionally, no modification of the Flutter repository is required to have Flutter embedded.

@cignaCode

This comment has been minimized.

cignaCode commented Aug 15, 2018

@tomaszpolanski not sure if you're up for it but I know me and many others would love to see how you accomplished this. Maybe a short blog post or post your gradle files :)

@koudle

This comment has been minimized.

koudle commented Aug 15, 2018

@mravn-google Have you considered ways to write custom platform-specific code using platform channels? The way in this Add Flutter to existing app is very good,but can't convenient to write MethodChannel。For example, I write a MethodChannel in my Android project,I have to copy the code to Flutter project in order to run successful when in Flutter project.And the dart code is in Flutter project,the code of MethodChannel is in my Android project, it's hard to debug MethodChannel. I hope to receive your reply.

@tomaszpolanski

This comment has been minimized.

tomaszpolanski commented Aug 15, 2018

@cignaCode Actually it's already in the works :). It's won't so short as I want also to share my experience starting from build setup to UI testing with Flutter driver. ETA 2 weeks

@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Aug 15, 2018

@koudle One option might be to extract your channel communication as a Flutter plugin, and create a dependency on that plugin from the Flutter module. But it depends on what you are trying to achieve. Some clarifying questions:

  • Are you using the new Flutter module template (flutter create -t module)?
  • If so, why do you want to run it without the host app? I can think of a few good reasons, but I'm curious about your setup.
  • How tightly coupled is the Android side of channel communication to your Android app? Does it call into your custom code or into Android SDK APIs?
@koudle

This comment has been minimized.

koudle commented Aug 16, 2018

@mravn-google Thanks for your reply.

  • Yes,I use the new Flutter module template (flutter create -t module)
  • Becasuse it can't write and debug the Dart code in the host app,and it can only be debugged in the pure Flutter project. So if I want to debug the Dart code,I have to change the Android library to become an application or copy the Dart code to another Flutter app project.Can use the Dart code as a module to make the host app depend on it?And it's best to write and debug the Dart code.
  • It's very deeply coupled,the MethodChannel depends on my custom code.
@mravn-google

This comment has been minimized.

Contributor

mravn-google commented Aug 16, 2018

@koudle You should be able to use the flutter attach command to connect to the service protocol of the Flutter/Dart portion of a hybrid app. This supports hot reload/restart and debugging. We do not yet have IntelliJ IDE support for this (we are actively working on that), but you can do hot reload/restart from the command line and use the Observatory web ui for debugging.

Suppose you have your Flutter module in some/path/hello and the Android host app in some/path/BigApp. Connect a device or start an emulator (Nexus 5X in my case). Then open a terminal:

$ cd some/path/hello
$ flutter attach
Waiting for a connection from Flutter on Nexus 5X

Launch BigApp in debug mode from Android Studio or using the Gradle CLI --- whatever you'd normally do. Navigate to a Flutter view on the device, then look back at the terminal:

Done.
Syncing files to device Nexus 5X...                          5.1s

🔥  To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".
An Observatory debugger and profiler on Nexus 5X is available at: http://127.0.0.1:59556/
For a more detailed help message, press "h". To quit, press "q".

Copying the URL into a browser leads you to the Dart Observatory UI where you can select a Dart isolate (there will be one per active Flutter view). You can then set breakpoints, evaluate expressions and a lot of other things (memory profiling, heap snapshots etc).

And you can edit your Dart code and press r or R in the terminal to have it hot reloaded or restarted.

@koudle

This comment has been minimized.

koudle commented Aug 16, 2018

@mravn-google Thanks a lot!

@shivam340

This comment has been minimized.

shivam340 commented Aug 18, 2018

I am trying to integrate flutter module inside existing iOS and Android app. For the Android, it is working fine. I am following steps from https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps. But for iOS app When I try to push FlutterViewController I get the following error.

Logs

[VERBOSE-2:engine.cc(112)] Engine run configuration was invalid.
[VERBOSE-2:FlutterViewController.mm(411)] FlutterViewController.mm(411)] Could not launch engine with configuration.

Following is the code that I am using to push flutter view controller

@IBAction func onClickButton(_ sender: Any) {
        print("Tapped on Button");
        let flutterViewController = FlutterViewController()
        navigationController?.pushViewController(flutterViewController, animated: false)
    }

an output of running flutter doctor -v

[✓] Flutter (Channel master, v0.5.9-pre.79, on Mac OS X 10.13.6 17G65, locale en-IN)
    • Flutter version 0.5.9-pre.79 at /Users/shivamgosavi/flutter
    • Framework revision 3a4ae280e3 (5 hours ago), 2018-08-17 15:02:39 -0700
    • Engine revision 4ee648914f
    • Dart version 2.1.0-dev.0.0.flutter-be6309690f

[✓] Android toolchain - develop for Android devices (Android SDK 28.0.2)
    • Android SDK at /Users/shivamgosavi/Library/Android/sdk
    • Android NDK at /Users/shivamgosavi/Library/Android/sdk/ndk-bundle
    • Platform android-28, build-tools 28.0.2
    • ANDROID_HOME = /Users/shivamgosavi/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)
    • All Android licenses accepted.

[✓] iOS toolchain - develop for iOS devices (Xcode 9.4.1)
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Xcode 9.4.1, Build version 9F2000
    • ios-deploy 1.9.2
    • CocoaPods version 1.5.3

[✓] Android Studio (version 3.1)
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin version 26.0.1
    • Dart plugin version 173.4700
    • Java version OpenJDK Runtime Environment (build 1.8.0_152-release-1024-b01)

[✓] IntelliJ IDEA Community Edition (version 2017.2.6)
    • IntelliJ at /Applications/IntelliJ IDEA CE.app
    • Flutter plugin version 21.2.2
    • Dart plugin version 172.4343.25

[✓] Connected devices (1 available)
    • iPhone 8 Plus • 0822DE18-6632-4F22-93F3-46770C82A247 • ios • iOS 11.4 (simulator)

• No issues found!

Please let me know If I am missing anything. And also please update the doc for integrating flutter into existing swift app, currently, the doc is only about ObjectiveC.

I have also created an issue for this #20777 .

@matthew-carroll matthew-carroll added this to To do in Add2App Aug 20, 2018

@matthew-carroll matthew-carroll moved this from To do to To do (Tooling) in Add2App Aug 20, 2018

@Hixie Hixie modified the milestones: Goals, bucket10 Aug 21, 2018

@matthew-carroll matthew-carroll moved this from To do (Tooling) to In progress in Add2App Aug 28, 2018

@matthew-carroll

This comment has been minimized.

Contributor

matthew-carroll commented Sep 13, 2018

I'm going to close this ticket because it doesn't have a clear delivery artifact.

For bugs and feature requests related to adding Flutter to an existing Android or iOS app, please file bugs against the following project:
https://github.com/flutter/flutter/projects/28

Also, if any comments in this thread require their own issues, please file those against the above project as well.

Add2App automation moved this from In progress to Done Sep 13, 2018

@Wanghuayin

This comment has been minimized.

Wanghuayin commented Sep 26, 2018

@tomaszpolanski could you share the experience for how to uses the "Flutter driver" to test the hybrid app?

@tomaszpolanski

This comment has been minimized.

tomaszpolanski commented Sep 27, 2018

@Wanghuayin I don't want to spam this issue. Just find me on twitter and I will be happy to share

@HairLee

This comment has been minimized.

HairLee commented Oct 3, 2018

Hello,

Can I use google map in IOS?

Now I just can be able to use it on Android App

@walterFeng

This comment has been minimized.

walterFeng commented Oct 11, 2018

@matthew-carroll
I am embedding Flutter into an existing project. I know how to use initialRoute to navigate to the specified Flutter page, but how do I put parameters or set arguments to this Flutter page?

For example, the goods list of the native page jumps to the goods details of Flutter, and the goodsID is the parameter that the page needs to load the data. Unfortunately, the Flutter page does not have this parameter when it is render. Should I wait for a channelMessage (include a goodsID) from my native page? This seems unreasonable

Can can help me?

@jonasbark

This comment has been minimized.

jonasbark commented Oct 11, 2018

@walterFeng you could just add the Id in the route name, just like a get parameter in a URL? E.g. "/goods/(Id)" or "/goods?id=(id)".

@walterFeng

This comment has been minimized.

walterFeng commented Oct 11, 2018

@jonasbark It works for me, thank you

@pejalo

This comment has been minimized.

pejalo commented Nov 5, 2018

Add Flutter to existing apps is an awesome resource. When invoking Flutter from within iOS/Android, what is the best way to send data to the Flutter world and then get something back once the Flutter view is dismissed? I don't see any arguments or return values to/from Flutter.createView or FlutterViewController.

Writing custom platform-specific code would do it, but that seems relatively cumbersome. We would have to write a bunch of asynchronous messages between the two worlds, including verifications that the data is ready for the Flutter or native views before they're shown.

@matthew-carroll

This comment has been minimized.

Contributor

matthew-carroll commented Nov 6, 2018

@pejalo would you mind filing a dedicated ticket for your use-case? Then we can address your use-case, specifically. In that ticket, please provide any surrounding details about why you need those particular signals so that we can factor that information into any API changes.

@pejalo

This comment has been minimized.

pejalo commented Nov 7, 2018

@matthew-carroll thanks for your response! I just created this ticket: #24080

@jelenacarnegie

This comment has been minimized.

jelenacarnegie commented Nov 9, 2018

@jonasbark It works for me, thank you

can you provide whole example, please? :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment