Repository: flutter
Issue: Import multiple Flutter modules in a native app
Labels: c: new feature,framework,engine,a: existing-apps,customer: crowd,c: proposal,P3,team-engine,triaged-engine

Hello guys,

I'm Matheus Romão, software engineer at [ArcTouch](https://arctouch.com/). 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](https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps) 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)!