Skip to content

Import multiple Flutter modules in a native app #39707

Description

@arctouch-matheusromao

Hello guys,

I'm Matheus Romão, software engineer at ArcTouch. Here, we are going with Flutter as the technology choice for an important project but recently hit a major roadblock. The principal difficulty relates to using different Flutter modules on different projects. Further explanation and proposal can be found on this issue.

TL;DR: We would like to import different modules in the same project, so we could reuse them in different projects. Today if we try that, we won't pass from Project Sync on Android or pod install on iOS.

Use case

Following the add-to-app guide we can import a Flutter module to an existing native app. However, there's no way to import multiple modules and access each module unitarily.

For example, if we have the following structure:

- flutter-modules
   - login
   - register
   - (...) other modules/features
 - android-project
 - ios-project
 - (...) other projects 

It would be nice if there were a way to import login and register modules depending on the needs of each project, so we could reuse them.

Android

Following the "depend on the module's source code" method, I was able to "import" both modules (login and register, in the example) leaving one of the include_flutter.groovy script as it is and changing the other, renaming :flutter to :register. I'm no specialist in gradle/groovy, but I'm pretty sure that was a workaround to make the script work in project sync phase because if you change :flutter to another name in both scripts, the project sync won't work, it will raise an exception:

> Failed to notify project evaluation listener.
   > assert flutterProject != null
            |              |
            null           false
[...]

Anyway, the project sync works if you leave one script as it is and change the other. However, if you try to run the app, even without using Flutter inside of it, the build fails with the following exception:

Task :app:mergeDebugNativeLibs FAILED

More than one file was found with OS independent path 'lib/x86/libflutter.so'

Which makes sense for me as I'm trying to import Flutter twice.

If I try to import the modules following the "Depend on the Android Archive (AAR)" method, the project sync works. But when you try to run the app the build fails with the following message:

Execution failed for task ':app:checkDebugDuplicateClasses'.
> 1 exception was raised by workers:
  java.lang.RuntimeException: Duplicate class io.flutter.BuildConfig found in modules flutter.jar (com.arctouch.login:flutter_debug:1.0) and flutter.jar (com.arctouch.register:flutter_debug:1.0)
[...]

Same problem with duplicates.

iOS

I wasn't able to import the modules using a Podfile. First, install_all_flutter_pods accepts only one module and if we try to call that twice in the same target, we get an error:

Invalid `Podfile` file: Script phase with name `Run Flutter Build Script` name already present for target `iOS Native`.

But I went to podhelper.rb to check the reference and found install_flutter_application_pod, so I tried to run the following Podfile:

login = '../flutter_modules/login'
register = '../flutter_modules/register'
load File.join(login, '.ios', 'Flutter', 'podhelper.rb')
load File.join(register, '.ios', 'Flutter', 'podhelper.rb')

target 'iOS Native' do
    install_flutter_engine_pod
    install_flutter_application_pod(login)
    install_flutter_application_pod(register)
end

But I still got the same error "script phase already present for target".

Workaround

At last, discussing all of that with my colleagues, they suggested trying to import all the modules in an umbrella-like project and then import in the native app. So, I tried to import both modules as packages of a third module, here called umbrella:

umbrella/pubspec.yaml:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2
  login:
    path: ../flutter_modules/login
  register:
    path: ../flutter_modules/register

That works, but you have to create the routes in the umbrella module to map the login and register widgets.

Well, clearly this is not desirable and it feels pretty hacky. In addition, it adds one more layer to the import process and depending on the method you use, you'll have to repeat some steps as the need for modules change.

Proposal

We should be able to import each module and access its features individually.

For Android, it would be great if we could import Flutter engine and then the modules:

implementation project(:flutter)
implementation project(:login)
implementation project(:register)

After that, we could specify which module and route we want to use in the Flutter view/fragment/activity (facade or Android embedding). Also, the same idea applies to ".aar" method.

For iOS, we could do something like the Podfile above, calling install_flutter_application_pod for each module we want to import or even use varags to pass an array of modules on install_all_flutter_pods.

Thank you guys for taking your time to read this (sorry for the long issue)!

Activity

  1. added
    c: proposalA detailed proposal for a change to Flutter
    c: new featureNothing broken; request for a new capability
    on Sep 3, 2019
  2. added
    a: existing-appsIntegration with existing apps via the add-to-app flow
    on Sep 9, 2019
  3. jmagman commented on Sep 9, 2019

    @jmagman
    Member
  4. xster commented on Sep 10, 2019

    @xster
    Member

    Thanks for describing in detail. This concept is on our mind but likely not something we'll support in an MVP this year. The main work here is to split our deliverables from being 2 pieces (libflutter.so + libapp.so or Flutter.framework + App.framework) into 3 pieces:

    1- the Flutter C++ engine with small bits in Java/Objective-C (1)
    2- the Flutter Dart framework AOTs (1)
    3- your Flutter module AOT (n)

    and a bunch of tooling dealing with mismatches.

    In the meantime, you'll likely need to create a glue project to bring in all your Flutter modules together in CI or manually before importing like you suggested.

  5. xster commented on Sep 12, 2019

    @xster
    Member

    Copying in from #40343

    From @Vanethos:

    Objective

    Create a native library for iOS and Android that has Flutter bundled in so that native developers can use this library without the need of installing flutter

    Steps taken

    • Create Android Project
    • Create Android library
    • Create Flutter Module
    • Add necessary code to Android Library
    • Try to build project

    This gives the following outcome:

    Could not find com.vanethos.add2appflutter:flutter_debug:1.0.
    Searched in the following locations:
      - https://dl.google.com/dl/android/maven2/com/vanethos/add2appflutter/flutter_debug/1.0/flutter_debug-1.0.pom
      - https://dl.google.com/dl/android/maven2/com/vanethos/add2appflutter/flutter_debug/1.0/flutter_debug-1.0.aar
      - https://jcenter.bintray.com/com/vanethos/add2appflutter/flutter_debug/1.0/flutter_debug-1.0.pom
      - https://jcenter.bintray.com/com/vanethos/add2appflutter/flutter_debug/1.0/flutter_debug-1.0.aar
    Required by:
        project :app > project :flutter_embbebed
    

    The instruction followed were the ones in the following link: adding flutter aar file to an android app

    What is noticed is that if the same steps are used to add flutter to an android host, as is detailed in the guide, then the code can compile and it all works out in an emulator.

    I've also created a repository with a minimal example to reproduce the issue: https://github.com/Vanethos/modulated-add-to-app

    flutter doctor                       
    Doctor summary (to see all details, run flutter doctor -v):
    [✓] Flutter (Channel stable, v1.9.1+hotfix.2, on Mac OS X 10.14.5 18F203, locale en-PT)
     
    [✓] Android toolchain - develop for Android devices (Android SDK version 29.0.0)
    [✓] Xcode - develop for iOS and macOS (Xcode 10.2.1)
    [✓] Android Studio (version 3.4)
    [✓] VS Code (version 1.38.0)
    [✓] Connected device (3 available)
    
    • No issues found!
    

    As requested, I'll tag @blasten in this issue

  6. Vanethos commented on Sep 13, 2019

    @Vanethos
    Contributor

    @xster thank you for merging the issue

    As I understand you said that this will not have any new updates during this year?

  7. xster commented on Sep 17, 2019

    @xster
    Member

    Right. Unless we see signs of this being a more common pattern, there are more pressing issues we're currently focused on this year.

  8. Vanethos commented on Sep 18, 2019

    @Vanethos
    Contributor

    Well, unfortunately, that means that I'll have to port my codebase to native :(

  9. jmagman commented on Sep 18, 2019

    @jmagman
    Member

    Can you accomplish the same thing by creating and re-using Flutter plugins, and importing them into your existing app with a single module?

  10. Vanethos commented on Sep 19, 2019

    @Vanethos
    Contributor

    @jmagman the problem is that we are doing this to create a native library to be used in Android and iOS.

    Our clients don't have flutter installed in their machines and some of them will not be able to. So we need to be able to compile a sort of .aar and pod that has native code, flutter code and the flutter engine

    Since we need this to work before the end of the year, unfortunately, I'm already porting our codebase to swift and kotlin (3 code bases to manage,yay!...)

  11. jmagman commented on Sep 19, 2019

    @jmagman
    Member

    @Vanethos The aar work is done, instructions here: https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps#1-depend-on-the-android-archive-aar
    The iOS framework work is being tracked here: #36968

    @arctouch-matheusromao Could you implement the login and register modules instead with two different plugins? Then you would only need one module per app, and the plugins could be reused between them?

    It looks like this issue may need to have the errors you documented split out into several trackable issues.

  12. arctouch-matheusromao commented on Sep 19, 2019

    @arctouch-matheusromao
    Author

    Hey @jmagman,

    Those modules were here just for the sake of the explanation. Our work environment revolves around various products, some new and other already existent. We would like to be able to share different modules across different projects. Some of those modules could be plugins, but unfortunately, others can't, as they would have UI flows. Actually, we do have a use-case that we could implement plugins and consume that inside one module. But, that's just one module.

    Just to be more clear, let's say we have a restaurant and we already have an Android app for our waiters to handle the orders. But our business is growing and we are already midway through the iOS native app development for our users to pay. Finally, we do have plans to build another app to handle all the back-office operations.

    So, for our restaurant we have three projects:

    • Waiters: existent app in Android
    • Users: only iOS (plans to build an Android app in the future)
    • Managers: Flutter app

    At this point, we already have designs for our brand and we want to preserve that across the apps. So, there are a lot of features that could be shared between those projects. For example, we have login and register that could be reused on the user app (both Android and iOS), but for the manager app we don't need the register module, as we already have the registered users and we don't want any external users accessing this app. Another example would be a news feed. If we ever want to share any news on our platform, that could be made in a module and reused in all apps.

    I hope this example helps to clarify why some business may choose to use Flutter. This would be an incredible opportunity to get work done faster than in any other framework and help a lot of businesses.

  13. Vanethos commented on Sep 20, 2019

    @Vanethos
    Contributor

    @jmagman but, as I have discussed in my issue, my problem is not adding the aar to an app but it is a problem adding an aar to a module.

    Unfortunately the native implementation has already started.. :'(

  14. arctouch-matheusromao commented on Sep 23, 2019

    @arctouch-matheusromao
    Author

    @xster and @matthew-carroll, do you guys know if it's possible to send messages through a Platform Channel between a Flutter module and a Flutter app?

    In our context here (explained in this issue), I'm exposing the umbrella module to an iOS app, which consumes all the events from our modules using a channel. That is working nicely. Now we need to import those modules inside a Flutter app. I fell like I don't need to import the umbrella and just import directly the modules that I need.

    In the example above, say I want to import the login module inside my Flutter app, but the login module already has an implemented channel, which sends user events. How can I listen to that inside the Flutter app?

    I thought I could just do that in the Flutter app:

    final channel = MethodChannel(channelName);
    channel.setMethodCallHandler(_handler)

    Where channelName is the same for the login module.

    However, it doesn't work. Here's the output:

    I/flutter ( 6503): Overflow on channel: flutter/lifecycle.  Messages on this channel are being discarded in FIFO fashion.  The engine may not be running or you need to adjust the buffer size if of the channel.
    E/flutter ( 6503): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: MissingPluginException(No implementation found for method navigateTo on channel [...]
    

    Is there a way that I can use the same binaryMessenger for the app and the module? Or it doesn't matter? Do we have a registrar or something similar to a plugin inside the application? So I can pass the binaryMessenger to the channel creation.

    I know I can just pass a handler method to the module, but that would also mean changes in the implementation inside the module. Right now we are trying to avoid this path.

    Thanks!

  15. 29 remaining items

  16. nailgilaziev commented on Apr 27, 2023

    @nailgilaziev

    met with the same problem. can't add new flutter module to the native project (more precisely, in projects for each platform iOS and Android).
    In my case, the existing native project already has a flutter module that was developed in 2020. This module has been working all these years and for now does not require changes and improvements.

    Now the new part of the project is implemented in a separate new flutter module.
    The team that developed the first module in the past and the team that is currently developing the second module are different people.
    The code is different, the versions of the libraries are different.
    It seems that we will need to update the old module, combine both modules under the umbrella project. and connect this module to projects. are there no other options, right?

    PS Flutter modules are connected to the project as artifacts. If we talk about android, the host project pulls up the repository with aar.

  17. tong-k-k commented on Sep 18, 2023

    @tong-k-k

    May I ask does flutter now still not support adding more than 1 flutter module to native?

    I am just trying to add more than 1 module to ios but it seems I cannot do this in pod file.

    Thanks

  18. AlvBarros commented on Sep 21, 2023

    @AlvBarros

    I think so, @tong-k-k .
    There's a single "Flutter" module and one for every plugin that has native code. And you also have to add them to your GeneratedPluginRegistrant file.

  19. huyphuongas commented on Mar 27, 2024

    @huyphuongas

    Thanks, @matthew-carroll! I went with a hybrid solution, having a package responsible to use channels for the bridge between modules and existent native apps and a Function for the Flutter app.

    About your question, our biggest problem is that each componentized capability has UI flows in Flutter and we need to integrate that in different native apps, that's why we don't use plugins over modules.

    Can you share the solution to do it?
    I want to add flutter module to flutter app but haven't found a solution yet.
    Thanks.

  20. razr130 commented on Jun 11, 2024

    @razr130
  21. added
    customer: crowdAffects or could affect many people, though not necessarily a specific customer.
    on Sep 4, 2024
  22. chan150 commented on Nov 11, 2025

    @chan150

    Any solution is here?
    We want to import aar flutter module into flutter app.

  23. emakar commented on Nov 11, 2025

    @emakar
    Contributor

    Any solution is here? We want to import aar flutter module into flutter app.

    is this related? the issue is about add-to-app (ie. to native app)

    why not add flutter to flutter app as a plugin/module?

  24. chan150 commented on Nov 11, 2025

    @chan150

    @emakar
    We want to serve a package without publishing our code.
    We already have an experienace with add-to-app and it is good solution for native app.

    We tested following environment and it is failed since multiple flutter modules are not supported.
    There is three projects: flutter module(compiled aar), flutter plugin and flutter app.

    • Either flutter app or flutter plugin icludes the flutter module as AAR.
    • flutter app imports the flutter plugin via pubspec.

    Once flutter module is imported then flutter plugin does not work.

  25. emakar commented on Nov 11, 2025

    @emakar
    Contributor

    @chan150 I don't think it's supported - flutter tooling builds single libapp.so
    when not publishing code - the only thing one could publish is libapp.so (aar which contains it)
    but flutter app as well builts into libapp.so, so there is a conflict

    you could likely look into forking libapp load logic though

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Issues that are less important to the Flutter projecta: existing-appsIntegration with existing apps via the add-to-app flowc: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Fluttercustomer: crowdAffects or could affect many people, though not necessarily a specific customer.engineflutter/engine related. See also e: labels.frameworkflutter/packages/flutter repository. See also f: labels.team-engineOwned by Engine teamtriaged-engineTriaged by Engine team

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions