Flutter Docs Android
Changes in build.gradle
in the android
directory
and
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
Changes in build.gradle
in the android
directory
and
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
YouTube tutorial (https://www.youtube.com/watch?v=iQOvD0y-xnw)
Install firebase-tools cli if you haven't already.
Login to the Firebase CLI
Activate the flutterfire cli
Configure the project with a firebase project
Add dependencies
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
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
To get debugging certificates SHA-1
to use google sign in when debugging
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.
I was then warned that the min sdk needed to be 23, so I manually set that value from the original flutterMinSdkVersion
To create new project
To check flutters compatibility with all build modes, run
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
provider
package helps to separate the business logic from the widget and provide data to stateless widgets throughout the widget tree
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)
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
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
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
}
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.
After cloning the repository I did need to run
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.
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
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>>
@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.
Getting started page flutter.dev.
Create new project
To run the app
or just hit f5
To perform hot reload simply type
into the terminal.
To create a new Statless Widget, simply type stl
into the editor.
Add font files to /fonts
then edit the pubspec.yaml
file. Refresh the pubspec by entering the following into the cmd
Hit the copy buttuon next to a package (i.e. flutter_svg).
Paste it in the dependencies
section within pubspec.yaml
. Then run
Create a folder /assets
, and within that /assets/icons
.
Then within pubspec.yaml
, uncomment the assets
block and add - assets/icons/
Click on a widget, i.e. Container
, and hit ctr .
. Then you can wrap in widget, then type the widget (i.e. GestureDetector).