# First Look at AWS Amplify Flutter (Developer Preview)

Original: https://swyx.io/amplify-flutter
Published: 2020-08-25

> AWS Amplify launched a Flutter Integration, so I thought I would record a quick video and blogpost

[Flutter](https://flutter.dev/) is Google’s UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase, and is one of the fastest growing mobile frameworks in 2020. [AWS Amplify recently announced Flutter support](https://aws.amazon.com/blogs/mobile/announcing-aws-amplify-flutter-developer-preview/) in Developer Preview, meaning it's not officially launched yet, but we can start trying it out now.

Here's my log from getting a simple Photo-Sharing app going with Authentication and Storage (example is in Android, but should work for iOS and web too).

## Explained In 100 Seconds

- YouTube: https://youtu.be/0NgR-Qa5GPE
- Twitter: https://twitter.com/swyx/status/1298349861696282625?s=20
- Dev.to Embed: {% youtube 0NgR-Qa5GPE %}

## Start a new Flutter App

Assuming you've [set up all the prerequisites for Flutter](https://flutter.dev/setup) (including setting up an [Android Virtual Device](https://developer.android.com/studio/run/managing-avds) and [accepting the Android SDK licenses](https://stackoverflow.com/questions/39760172/you-have-not-accepted-the-license-agreements-of-the-following-sdk-components), you can head to **File -> New -> New Flutter Project** and pick the basic Flutter Application starter.

We'll need to add the new Amplify flutter libraries, so be sure to add them in `pubspec.yaml` and `Pub get` to download:

```yaml
dependencies:
  flutter:
    sdk: flutter


  # new
  amplify_core: '<1.0.0'
  amplify_auth_cognito: '<1.0.0'
  amplify_storage_s3: '<1.0.0'

  # we happen to also use this in our demo
  file_picker: ^1.13.3

  ## this is also available if you want analytics but not covered in this post
  # amplify_analytics_pinpoint: '<1.0.0'
```

## Initialize an Amplify project

Note: If you're reading this in late August 2020, be aware that you'll need a special version of the CLI because it is still in developer preview:

```bash
npm i -g @aws-amplify/cli@4.26.1-flutter-preview.0
```

We then follow the standard Amplify setup instructions (assuming [CLI is installed and configured](https://docs.amplify.aws/lib/project-setup/prereq/q/platform/flutter)). 

```bash
# command
amplify init

# prompts
? Enter a name for the environment
    `dev`
? Choose your default editor:
    `IntelliJ IDEA`
? Choose the type of app that you're building: 
    'flutter'
⚠️  Flutter project support in the Amplify CLI is in DEVELOPER PREVIEW.
Only the following categories are supported:
 * Auth
 * Analytics
 * Storage
? Where do you want to store your configuration file? 
    ./lib/
? Do you want to use an AWS profile?
    `Yes`
? Please choose the profile you want to use
    `default`
```

Notice that you will see a configuration file created in `./lib/` called `amplifyconfiguration.dart`. This is a static file you can import that holds all your public facing Amplify data, but most people will only use it in `amplify.configure(amplifyconfig)`.

We're going to want to set up storage for our photo app, which requires authentication. Fortunately the CLI sets up both at once for us:


```bash
# command
amplify add storage

# prompts
? Please select from one of the below mentioned services:
    `Content (Images, audio, video, etc.)`
? You need to add auth (Amazon Cognito) to your project in order to add storage for user files. Do you want to add auth now?
    `Yes`
? Do you want to use the default authentication and security configuration?
    `Default configuration`
? How do you want users to be able to sign in?
    `Username`
? Do you want to configure advanced settings?
    `No, I am done.`
? Please provide a friendly name for your resource that will be used to label this category in the project:
    `S3friendlyName`
? Please provide bucket name:
    `storagebucketname`
? Who should have access:
    `Auth and guest users`
? What kind of access do you want for Authenticated users?
    `create/update, read, delete`
? What kind of access do you want for Guest users?
    `create/update, read, delete`
? Do you want to add a Lambda Trigger for your S3 Bucket?
    `No`
```

When you've set up whatever else you might need, you can push to the cloud to kick off the provisioning:

```bash
amplify push --y
```

This process takes a while to provision all the resources for you, so while that's going we can set up our code first.

## Diving into Flutter code

Inside of `./lib/main.dart`, we can import everything we will need:

```dart
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';
import 'amplifyconfiguration.dart';
// etc
```

Then inside of our main page we can write the Amplify config code:

```dart
// inside of some class for the page
  Amplify amplify = Amplify();
  bool _isAmplifyConfigured = false;

  @override
  initState() {
    super.initState();
    _initAmplifyFlutter();
  }

  void _initAmplifyFlutter() async {
    AmplifyAuthCognito auth = AmplifyAuthCognito();
    AmplifyStorageS3 storage = AmplifyStorageS3();
    amplify.addPlugin(
        authPlugins: [auth],
        storagePlugins: [storage],
    );
    await amplify.configure(amplifyconfig);

    setState(() {
      _isAmplifyConfigured = true;
    });
  }
```

This way we are able to add a little loading screen based on `_isAmplifyConfigured` if we wish.

For the rest of the app, you will have to write up the Flutter UI experience yourself, but the hard part is over from writing Amplify code.

### Using Amplify Auth in a Widget

Call the appropriate functions ([docs here](https://docs.amplify.aws/lib/auth/signin/q/platform/flutter)) as needed. Here's how we sign a user in:

```dart
import 'package:amplify_auth_cognito/amplify_auth_cognito.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:flutter/material.dart';

class SignInView extends StatefulWidget {
  @override
  _SignInViewState createState() => _SignInViewState();
}

class _SignInViewState extends State<SignInView> {
  final usernameController = TextEditingController();
  final passwordController = TextEditingController();

  String _signUpError = "";
  List<String> _signUpExceptions = [];

  @override
  void initState() {
    super.initState();
  }

  void _signIn() async {
    // Sign out before in case a user is already signed in
    // If a user is already signed in - Amplify.Auth.signIn will throw an exception
    try {
      await Amplify.Auth.signOut();
    } on AuthError catch (e) {
      print(e);
    }

    try {
      SignInResult res = await Amplify.Auth.signIn(
          username: usernameController.text.trim(),
          password: passwordController.text.trim());
      Navigator.pop(context, true);
    } on AuthError catch (e) {
      setState(() {
        _signUpError = e.cause;
        _signUpExceptions.clear();
        e.exceptionList.forEach((el) {
          _signUpExceptions.add(el.exception);
        });
      });
    }
  }

// etc for the Widget build
```

### Using Amplify Storage in a Widget


Call the appropriate functions ([docs here](https://docs.amplify.aws/lib/storage/overview/q/platform/flutter)) as needed. Here's how we upload a new picture:

```dart
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:amplify_core/amplify_core.dart';
import 'package:amplify_storage_s3/amplify_storage_s3.dart';

class ImageUploader extends StatelessWidget {
  void _upload(BuildContext context) async {
    try {
      print('In upload');
      // Uploading the file with options
      File local = await FilePicker.getFile(type: FileType.image);
      local.existsSync();
      final key = new DateTime.now().toString();
      Map<String, String> metadata = <String, String>{};
      metadata['name'] = 'filename';
      metadata['desc'] = 'A test file';
      S3UploadFileOptions options = S3UploadFileOptions(
          accessLevel: StorageAccessLevel.guest, metadata: metadata);
      UploadFileResult result = await Amplify.Storage.uploadFile(
          key: key, local: local, options: options);

      print('File uploaded.  Key: ' + result.key);
      Navigator.pop(context, result.key);
    } catch (e) {
      print('UploadFile Err: ' + e.toString());
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(children: [
      RaisedButton(
        child: Text("Upload Image"),
        onPressed: () {
          _upload(context);
        },
      )
    ]);
  }
}
```

## Full Demo App

If you would like to see a demo app with all this setup, head to the `amplify-flutter` example repo: https://github.com/aws-amplify/amplify-flutter/tree/master/example

(and give it a ⭐ - it really helps!)

## What's Next?

Being a new SDK, the Flutter Developer Preview is definitely lacking feature parity with the JS/Android/iOS SDK's. Here's what's coming in the next few months:

- API (REST/GraphQL): The API category provides an interface for retrieving and persisting your data, using GraphQL backed by AWS AppSync or REST APIs and handlers using Amazon API Gateway and AWS Lambda.
- DataStore: Amplify DataStore provides a programming model for leveraging shared and distributed data without writing additional code for offline and online scenarios, which makes working with distributed, cross-user data just as simple as working with local-only data.
- Predictions: The Predictions category enables AI/ML use cases on the frontend such as translating text, converting text to speech, and recognizing text, labels and faces in images.
- Auth: We will extend the Auth category with social sign in with Web UI
- Storage: We will extend the Storage category with the ability to track Upload and Download Progress
- Escape Hatches: We will add support for ‘escape hatches’, enabling developers to more easily use the low-level generated iOS and Android AWS Mobile SDKs for additional use cases.
