DEV Community

Yevhen Beshkarov
Yevhen Beshkarov

Posted on Originally published at saymyframe.com on

SMF 0.8: Flutter flavors, CI and a REST client

Say My Frame (SMF) generates Flutter apps from independent modules. Version 0.8 is out on pub.dev, and it covers what an app needs before it goes to the stores: Flutter flavors, CI, a REST client, and an icon and a splash screen that are not the ones of Flutter.

dart pub global activate smf_flutter_cli
smf create my_app -m home,bottom_tabs,material_theme,gen_l10n,dio,github_actions,launcher_icons,native_splash

Enter fullscreen mode Exit fullscreen mode

smf create in a terminal: it asks for the app name and the modules, among them the REST client, the app icon, the splash screen and GitHub Actions, adds the modules that the chosen ones need, makes the app icon and the splash screen, and generates a Flutter app

As before, you get a regular Flutter project with no SMF package in its dependencies, and SMF never touches it again.

Flutter flavors in every app

Every app now has dev, staging and prod. You don't ask for them, and no package stands behind them: they are plain Gradle and Xcode settings. Each flavor has its own id and its own name, so all three sit next to each other on one phone.

The home screen of an iPhone simulator with three apps of one project: My App, My App Dev and My App Staging, each with the default icon of SMF

flutter run builds dev. So does any other flutter command without --flavor, in release mode too, which means flutter build appbundle gives you a release of your dev app. A build for a store always names the flavor. In an app with values in .env, it takes those too:

flutter build appbundle --flavor prod --dart-define-from-file=.env

Enter fullscreen mode Exit fullscreen mode

With firebase_core, each flavor has its own Firebase apps, in one project or in several. In a terminal, smf create configures dev, and each other flavor takes one command:

dart tool/configure_firebase.dart staging --project=my-app-staging

Enter fullscreen mode Exit fullscreen mode

.env is the one thing that does not follow the flavor. There is one file, and a command takes what the file has when it runs. On your machine you change the values by hand, and in CI the job writes the file for the environment that it builds. The guide to flavors has the rest, such as adding a fourth flavor.

CI on GitHub Actions

github_actions adds .github/workflows/ci.yml. Each push to a branch checks the format and runs the analyzer and the tests, with nothing to set up first.

A build of the Android app runs on request, for the environment that you pick, with the values of .env from the variables of that environment on GitHub:

gh workflow run ci.yml -f environment=staging

Enter fullscreen mode Exit fullscreen mode

The CI guide lists the commands and where the variables go.

A REST client with its address in .env

dio gives the app appRest, a client that reads the address of your API from REST_BASE_URL in .env:

final response = await appRest.get('notes', query: {'page': '1'});

Enter fullscreen mode Exit fullscreen mode

No screen of the app makes a request on its own, since the client is there for the code that you add. What it does for that code is the part I didn't want to leave to each app:

  • GET and HEAD repeat after a connection that failed and after 429, 502, 503 and 504. Other methods never repeat, since a repeated POST may do its work twice.
  • In an app with sign-in, the client adds the token of the user, gets a new one once after a 401, and takes the token away on a redirect to another origin.
  • A call fails only with a RestFailure, which has a closed set of reasons.

The REST guide covers the rest.

An app icon and a splash screen

launcher_icons and native_splash replace the logo of Flutter and the white launch screen with the mark of SMF, and the splash screen has a variant for the dark mode of the device. To use your own, replace the images in assets/branding/ and run:

dart tool/update_app_icon.dart
dart run flutter_native_splash:create

Enter fullscreen mode Exit fullscreen mode

The guide to the icon and the splash screen gives the sizes of the images.

Upgrading from 0.7

  • Apps generated by 0.7 stay as they are, since SMF generates an app once.
  • If you write modules, smf_contracts changed: a provider of the app entry writes the flavors into its native projects, and a provider of sign-in implements userToken.
  • A module that reads lib/firebase_options.dart needs an update, since each flavor now has lib/firebase_options_<flavor>.dart.

The full list is in the release notes of SMF 0.8.0 on GitHub.

What comes next

Next on my list are the rating of the app in the stores, reviews, remote config and ads. There are no dates: SMF is a side project. If you have a module in mind, tell me on Discord or in GitHub Issues.

SMF generates Android and iOS apps for Flutter 3.44 or newer and Dart 3.12 or newer. The documentation starts with installation and your first app, and the code is on GitHub.

Top comments (0)