Flutter applications

Flutter is Google’s open source toolkit for creating applications for mobile, web and desktop platforms.

Snapcraft can be used to package and distribute Flutter applications in a way that enables convenient installation by users.

The process of creating a snap for a Flutter application builds on standard Flutter development and packaging tools, making it possible to adapt or integrate an application’s existing packaging into the snap building process.

Getting started

Snaps are defined in a single snapcraft.yaml file placed in a snap folder at the root of your project. This YAML file describes the application, its dependencies and how it should be built.

The following shows the relevant parts of the snapcraft.yaml file for a simple template project, my-flutter-app:

name: my-flutter-app
version: '1.0'
summary: An example Flutter snap
description: |
  An example showing how Flutter programs can be packaged as snaps.

base: core22
confinement: strict
grade: stable

apps:
  my-flutter-app:
    command: my_flutter_app
    extensions: [gnome]

parts:
  my-flutter-app:
    source: .
    plugin: flutter
    flutter-target: lib/main.dart

We’ll break this file down into its components in the following sections.

Metadata

The snapcraft.yaml file starts with a small amount of human-readable metadata, which is often already available in the project’s own packaging metadata or README.md file. This data is used in the presentation of the application in the Snap Store.

name: my-flutter-app
version: '1.0'
summary: An example Flutter snap
description: |
  An example showing how Flutter programs can be packaged as snaps.

The name must be unique in the Snap Store. Valid snap names consist of lower-case alphanumeric characters and hyphens. They cannot be all numbers and they also cannot start or end with a hyphen.

The version string can be an arbitrary version, such as 1.0 in our example, or keywords such as git, to import a version string from a git tag or commit, for instance. Versions carry no semantic meaning in snaps.

The summary can not exceed 79 characters. You can use a chevron ‘>’ in the description key to declare a multi-line description.

Base

The base keyword declares which base snap to use with your project. A base snap is a special kind of snap that provides a run-time environment alongside a minimal set of libraries that are common to most applications:

base: core22

In this example, core12 is used as the base for snap building, and is based on Ubuntu 22.04 LTS.

See Base snaps for more details.

Security model

Snaps are containerised to ensure more predictable application behaviour and greater security. The general level of access a snap has to the user’s system depends on its level of confinement.

The next section of the snapcraft.yaml file describes the level of confinement applied to the running application:

confinement: strict

It is usually best to start creating a snap with a confinement level that provides warnings for confinement issues by specifying a confinement value of devmode. In this example, the strict mode is used instead, indicating that run-time confinement issues should not occur.

Specifying strict confinement enables the grade of the snap to be marked as stable and published to a stable channel in the Snap Store.

Parts

Parts define what sources are needed to build your application. Parts can be anything: programs, libraries, or other needed assets, but for this example, we only need to use one part for the my-flutter-app source code:

parts:
  my-flutter-app:
    source: .
    plugin: flutter
    flutter-target: lib/main.dart

The source keyword points to the project source code, which can be a local directory or remote Git repository. In this case, it refers to the main project repository.

The plugin keyword is used to select a language or technology-specific plugin that knows how to perform the build steps for the project. In this example, the :ref:flutter plugin <the-flutter-plugin> is used to build the project.

The flutter-target keyword is used to tell the plugin where the main application code is located in the project.

Apps

Apps are the commands and services that the snap provides to users. Each key under apps is the name of a command or service that should be made available on users’ systems.

apps:
  my-flutter-app:
    command: my_flutter_app
    extensions: [gnome]

The command specifies the path to the application binary that the user can run. This is resolved relative to the root of the snap contents.

If your command name matches the snap name, users will be able run the command directly.

If the command name matches the name of the snap specified in the top-level name keyword (see Metadata above), the binary file will be given the same name as the snap, as in this example. If the names differ, the binary file name will be prefixed with the snap name to avoid naming conflicts between installed snaps. An example of this would be my-flutter-app.some-command.

The extensions keyword is used in this example to access GUI toolkit features that the application needs. See Snapcraft extensions for further details.

Building the snap

First, make sure you’ve installed Snapcraft and create a new directory for your Flutter project.

Inside that directory, type snapcraft init. This creates an additional subdirectory, called snap containing a template snapcraft.yaml file.

Edit the created snapcraft.yaml to contain the Flutter example shown earlier.

After you’ve created the snapcraft.yaml, you can build the snap by simply executing the snapcraft command in the project directory:

$ snapcraft
Executed: pull gnome/sdk
Executed: pull my-flutter-app
Executed: build gnome/sdk
Executed: build my-flutter-app
Executed: stage gnome/sdk
Executed: stage my-flutter-app
Executed: prime gnome/sdk
Executed: prime my-flutter-app
Executed parts lifecycle
Generated snap metadata
Created snap package my-flutter-app_1.0_amd64.snap

The build process may take some time as both Flutter and the Dart SDK from Flutter are downloaded and installed into the build environment, but they won’t be downloaded again with subsequent builds unless the environment is reset.

The resulting snap can be installed locally. This requires the --dangerous flag because the snap is not signed by the Snap Store, or if you’re testing pre-confinement, the --devmode flag acknowledges that you are installing an unconfined application:

sudo snap install my-flutter-app_1.0_amd64.snap --dangerous

You can then try it out:

my-flutter-app

Running the example Flutter application

Removing the snap is simple too:

sudo snap remove my-flutter-app

You now have a snap you can deploy and upload to the Snap Store. See Releasing your app for more details, and to get a deeper insight into the snap building process, start with the Snapcraft checklist.

1 Like

My application is in review for the last one week and I didn’t hear back from snapcraft manual review so far.

I have built a note taking app using flutter. I want it to be totally sandboxed and have not chosen the classic. I have added dbus dependency as mentioned in flutter documentation. But the app went for a manual review and it is pending for over a week.

human review required due to 'deny-connection' constraint (interface attributes) declaration-snap-v2_slots_connection (dbus-ideasdump, dbus)

Please help review faster so that I can make the latest app available to my users.
Thanks.

@degville Are there plans to support core20? My app is using dart:ffi and tries to find glibc>=2.29 at runtime which fails on core18. Or is there another workaround?

I’ll have a look into it and get back to you - I’ve got a few of my own Flutter snaps I need to test. As far as I’m aware, updates to the Flutter extension are very much on the roadmap.

This page does not appear to cover the newer core22 Flutter plugin.

There doesn’t seem to be an accompanying core22 extension yet:

❯ snap info snapcraft | tail -1; snapcraft list-extensions
installed:          7.3.1                               (8931) 66MB classic
Extension name    Supported bases
----------------  ----------------------
flutter-beta      core18
flutter-dev       core18
flutter-master    core18
flutter-stable    core18
gnome             core22
gnome-3-28        core18
gnome-3-34        core18
gnome-3-38        core20
kde-neon          core18, core20, core22
ros1-noetic       core20
ros2-foxy         core20
ros2-humble       core22 

There is no core22 extension for flutter, but there is a core22 plugin; that is what is not mentioned here.

…in combination with the extension:

All of those flutter extensions are for core18 only, I have no idea what would happen if you tried to use them with core20 or core22.

I did try. Snapcraft complains the extensions don’t exist.

I guess we need an updated page for core22.

There’s no mention of the new core22 flutter plugin; that might need a separate page somewhere.

I think we need to experiment and see how feasible it is to update this to use the gnome extension with the flutter plugin instead (I’ve not tried it yet).

The workshops snap, https://github.com/canonical/workshops, seems to build and run just fine as a PoC; that’s the example I’m going to use.

1 Like

The example snapcraft.yaml file also doesn’t match the snippet in the Parts section. I’ll fix it shortly.

1 Like

Hi, thanks for the documentation.

But I have a problem with flutter plugin and accessing extra files with system-files interface. If the application is running when I’m executing the snap connect for the plug then the the app is not able to access anymore the flutter_assets folder. Do you know of any issues with this?

I’ve wrote some more info into Flutter app and snapcracft UNIX socket access

Thanks