Skip to content

Flutter

Flutter Docs Android

Changes in build.gradle in the android directory

ext.kotlin_version = '1.8.10' 

and

classpath 'com.android.tools.build:gradle:8.1.0'

I also changed the gradle-wrapper.properties to version 8.1

I also manually set the JDK version to 17 (default 21) in gradle.properties

org.gradle.java.home=/Library/Java/JavaVirtualMachines/amazon-corretto-17.jdk/Contents/Home

Flutter Firebase Tutorial

YouTube tutorial (https://www.youtube.com/watch?v=iQOvD0y-xnw)

Install firebase-tools cli if you haven't already.

npm install -g firebase-tools

Login to the Firebase CLI

firebase login

Activate the flutterfire cli

flutter pub global activate flutterfire_cli

Configure the project with a firebase project

flutterfire configure

Add dependencies

flutter pub add firebase_core

I had an issue with cocopods, fixed it by reinstalling with brew (https://stackoverflow.com/questions/62593939/cocoapods-not-installed-or-not-in-valid-state)

sudo gem uninstall cocoapods
brew install cocoapods
brew link --overwrite cocoapods
brew unlink cocoapods && brew link cocoapods
fire_base core error

Error: The pod "Firebase/CoreOnly" required by the plugin "firebase_core" requires a higher minimum iOS deployment version than the plugin's reported minimum version. To build, remove the plugin "firebase_core", or contact the plugin's developers for assistance. Error running pod install

Open the ios/PodFile and uncomment the platform line, change to version '13.0'

Add firestore dependency for firestore database

flutter pub add cloud_firestore

To get debugging certificates SHA-1 to use google sign in when debugging

cd android/
./gradlew signingReport

I followed the instructions for setting up android, and ended up getting an error;

Following this stackoverflow (https://stackoverflow.com/questions/74226250/error-member-not-found-firebaseappplatform-verifyextends) this seemed to fix it.

flutter pub upgrade --major-versions

I was then warned that the min sdk needed to be 23, so I manually set that value from the original flutterMinSdkVersion

Fireship.io tutorial

To create new project

flutter create --org com.wildetechsolutions myapp

To check flutters compatibility with all build modes, run

flutter doctor --verbose

Can write flutter widgets in the browser at https://dartpad.dev/

Most basic element is a Container, like a div in html.

Right click on widget, refactor to another type of widget.

Flutter provides row and column widgets.

Stack widget, like a StackPane.

Hero widget can animate between pages.

Future one-teim async value (single doc read) Stream multipel async values (listen to real-time updates)

Stateful widget cons

  • sharing data with children
  • mixing logic with UI

provider package helps to separate the business logic from the widget and provide data to stateless widgets throughout the widget tree

Setup

So the Firebase setup video does seem a bit out of date, the code is very different than the setup provided at (https://firebase.flutter.dev/docs/overview/). In fact, the setup seems a lot more similar to the process followed on my 12-14 blog post.

Flutter gives two options for routing:

Navigator 1.0 (push and pop screens to a stack)

and

Navigator 2.0 (hasn't been well received)

Theming

This has changed a bit from the tutorial and some of it is deprecated. Concepts make sense though in defining custom theme in theme.dart

Home Login

Using a stream building, we can allow the authentication state dictate where the app goes from our default home.dart path

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return StreamBuilder(
      stream: AuthService().userStream,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Text("loading");
        } else if (snapshot.hasError) {
          return const Center(
            child: Text("error"),
          );
        } else if (snapshot.hasData) {
          return const TopicsScreen();
        } else {
          return const LoginScreen();
        }
      },
    );
  }
}

With our initial auth service, the user will not be logged in, and therefore routed to the LoginScreen

auth.dart
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
class AuthService {
  final userStream = FirebaseAuth.instance.authStateChanges(); // asynchronous stream to listen to the user's authentication state
  final user = FirebaseAuth.instance.currentUser; // synchronous method to get the current user
}

Authentication

In the firebase console, go to the project then go to Authentcation. Hi getting started. Go to sign-in method and enable Anonymous as a provider. This will allow a user to use the app without being registed and we'll still get a user id for them.

Add Google Sign in as a provider on firebase. It will then give you an updated json file to include in the android project. I needed to stop the app, and start it again for the json file to take effect. Hot restart did't work initially. However, after starting the app, the google sign in did work.

Going to skip Apple auth until I set it up on the mac. Note that Apple Auth is required if other social login methods are included.

Database data population

After cloning the repository I did need to run

npm install @google-cloud/firestore

in order for the node scripts to work.

Creating the FireStore database was kind of glossed over. But simply go to the FireStore database and hit create database, I set it to production mode. The node.js project to populate data worked as expected.

Models

Bring in json_serializeable, build_runner dependency into dev_dependencies which facilitates serializing/deserializing objects to json. Also bring json_annotation dependency into the normal dependencies section.

I added dependency and running flutter pub upgrade --major-versions to get it up to date (json_serializable: ^6.8.0 at the time of writing)

For each class you'll want to add this code

factory Topic.fromJson(Map<String, dynamic> json) => _$TopicFromJson(json);
Map<String, dynamic> toJson() => _$TopicToJson(this);

Now from the terminal you can just run the following to generate the mappers

flutter pub run build_runner build

Building UI

For dynamic UI rendering based on a returned api response, we can use FutureBuilder which takes the future as an argument and then a builder function which can return the widget based on the result of the future. You can also strongly type the FutureBuilder, i.e. FutureBuilder<List<Topic>>

Topics Screen build function
@override
  Widget build(BuildContext context) {
    return FutureBuilder<List<Topic>>(
      future: FirestoreService().getTopics(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const LoadingScreen();
        } else if (snapshot.hasError) {
          return Center(
            child: ErrorMessage(message: snapshot.error.toString()),
          );
        } else if (snapshot.hasData) {
          var topics = snapshot.data!;

          return ...[widget];
        } else {
          return const Text('No topics found in Firestore. Check database');
        }
      },
    );
  }

Navigator does not necessarily have to navigate to a route, it can navigate to a widget as well

Navigator.of(context).push(
              MaterialPageRoute(
                builder: (BuildContext context) => TopicScreen(topic: topic),
              ),
            );

Provider

Provider is a very popoluate flutter library, easier to share values throughout the widget tree. We'll want this to listen to the report stream from multiple widgets. We could listen to it with a StreamBuilder for every page/widget, but that wouldn't be very efficient.

2024 07 27 Flutter

Getting started page flutter.dev.

Create new project

flutter create myapp

Flutter choose device VS Code

To run the app

flutter run

or just hit f5

To perform hot reload simply type

r

into the terminal.

To create a new Statless Widget, simply type stl into the editor.

Fonts

Add font files to /fonts then edit the pubspec.yaml file. Refresh the pubspec by entering the following into the cmd

flutter pub get

Flutter packages

https://pub.dev/

Hit the copy buttuon next to a package (i.e. flutter_svg).

Paste it in the dependencies section within pubspec.yaml. Then run

flutter pub get

SVG Icons

Create a folder /assets, and within that /assets/icons.

Then within pubspec.yaml, uncomment the assets block and add - assets/icons/

Refactoring Widgets

Click on a widget, i.e. Container, and hit ctr .. Then you can wrap in widget, then type the widget (i.e. GestureDetector).