0
Обложка: Как интегрировать Flutter в действующий нативный Android-проект

Как интегрировать Flutter в действующий нативный Android-проект

В статье хочу поделиться своим опытом интеграции Flutter-модуля в действующий нативный Android-проект. После интеграции мы запустим Flutter-модуль.

Интеграция нужна, если вы хотите перейти на Flutter и писать код сразу для двух платформ: Android и iOS. Чтобы оценить и понять, как будет себя вести модуль в существующем проекте, не переписывая проект полностью.

Учитывайте, что на момент написания статьи я использую Android Studio Bumblebee 2021.1.1. Думаю, это важно: год назад я пробовал добавить Flatter модульно, и тогда в Android Studio всё было по-другому. Для примера сделаю раздел FAQ в текущем нативном приложении и перенесу его во Flutter.

Создаем Flutter-модуль

Для начала нужно создать проект-модуль. Чтобы это сделать, есть два способа:

1) Вызвать через терминал команду

% flutter create -t module --org com.example my_flutter

2) С помощью меню самой Android Studio

File → New → New Flutter Project… → выбрать Flutter (если не выбран) → Next → выбрать в разделе Project Type: Module → Finish

Также перед добавлением модуля необходимо добавить в проекте app build.gradle в блок android { }

android {
  //...
  compileOptions {
    sourceCompatibility 1.8
    targetCompatibility 1.8
  }
}

И обязательно во Flutter-модуле добавляем в MaterialApp, в атрибут routes, нужную страницу. В моем случае это FAQScreen. Я уже его подготовил.

Формируем модуль

Добавляем Flutter-модуль в существующее приложение. Для этого понадобится сформировать файл AAR и добавить зависимость в Gradle. AAR файл можно сформировать двумя способами:

1) вызвать команду с помощью терминала

% flutter build aar

2) с помощью Android Studio, нажав в меню Build → Flutter → Build AAR

В обоих случаях появится вот такая инструкция. В ней описано, что нужно сделать далее, как и куда добавить зависимости:

Consuming the Module
1. Open <host>/app/build.gradle
2. Ensure you have the repositories configured, otherwise add them:
String storageUrl = System.env.FLUTTER_STORAGE_BASE_URL ?: "https://storage.googleapis.com"
  repositories {
    maven {
      url '/Users/my_flutter/build/host/outputs/repo'
    }
    maven {
    url "$storageUrl/download.flutter.io"
    }
  }
3. Make the host app depend on the Flutter module:
   dependencies {
     debugImplementation 'com.example.my_flutter:flutter_debug:1.0'
      profileImplementation 'com.example.my_flutter:flutter_profile:1.0'
      releaseImplementation 'com.example.my_flutter:flutter_release:1.0'
   }
4. Add the `profile` build type:
  android {
    buildTypes {
      profile {
          initWith debug
      }
    }
  }

Добавляем AAR-файл в нативный проект

В официальной инструкции написано, что нужно добавить три разных зависимости, но я добавил к себе в проект, как обычно, только «flutter_release». Мы ведь хотим, чтобы тест работал быстро, но для просмотра логов нужно добавлять «flutter_debug«.

implementation 'com.example.my_flutter:flutter_release:1.0'

Сформированные AAR-файлы будут находиться тут:

build/host/outputs/repo
└── com
    └── example
        └── my_flutter
            ├── flutter_release
            │   ├── 1.0
            │   │  ├── flutter_release-1.0.aar
            │   │  ├── flutter_release-1.0.aar.md5
            │   │  ├── flutter_release-1.0.aar.sha1
            │   │  ├── flutter_release-1.0.pom
            │   │  ├── flutter_release-1.0.pom.md5
            │   │  └── flutter_release-1.0.pom.sha1
            │   ├── maven-metadata.xml
            │   ├── maven-metadata.xml.md5
            │   └── maven-metadata.xml.sha1
            ├── flutter_profile
            │   ├── ...
            └── flutter_debug
                └── …

Чтобы запустить Flutter-модуль, используем startActivity. Для этого пишем FlutterActivity.withNewEngine().

Помните, мы добавляли «/faqroute»: () => FAQScreen()? Теперь добавим в initialRoute название роута «/faq_route». Теперь при открытии модуля будет открываться наш FAQScreen().

startActivity(
    FlutterActivity.withNewEngine()
        .initialRoute("/faq_route")
        .build(this)
)

Результат

Запускаем и видим, что у нас получилось.

Переходим в пункт «Частые вопросы (FAQ)».

Я считаю, что это очень классная фича Flutter, особенно для существующих проектов. Можно постепенно переписывать приложение, сразу интегрировать фичу и выпускать в релиз, а не писать приложение нуля и до конца.