--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/app/pages/login-page/login-page.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { ComponentFixture, TestBed } from '@angular/core/testing';
2 |
3 | import { LoginPageComponent } from './login-page.component';
4 |
5 | describe('LoginPageComponent', () => {
6 | let component: LoginPageComponent;
7 | let fixture: ComponentFixture;
8 |
9 | beforeEach(() => {
10 | TestBed.configureTestingModule({
11 | declarations: [LoginPageComponent]
12 | });
13 | fixture = TestBed.createComponent(LoginPageComponent);
14 | component = fixture.componentInstance;
15 | fixture.detectChanges();
16 | });
17 |
18 | it('should create', () => {
19 | expect(component).toBeTruthy();
20 | });
21 | });
22 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/app/pages/login-page/login-page.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, inject } from '@angular/core';
2 | import { ChatService } from 'src/app/services/chat.service';
3 |
4 | @Component({
5 | selector: 'app-login-page',
6 | templateUrl: './login-page.component.html',
7 | styleUrls: ['./login-page.component.css'],
8 | standalone: true,
9 | })
10 | export class LoginPageComponent {
11 | chatService = inject(ChatService);
12 | user$ = this.chatService.user$;
13 | }
14 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/app/services/chat.service.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed } from '@angular/core/testing';
2 |
3 | import { ChatService } from './chat.service';
4 |
5 | describe('ChatService', () => {
6 | let service: ChatService;
7 |
8 | beforeEach(() => {
9 | TestBed.configureTestingModule({});
10 | service = TestBed.inject(ChatService);
11 | });
12 |
13 | it('should be created', () => {
14 | expect(service).toBeTruthy();
15 | });
16 | });
17 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/app/services/chat.service.ts:
--------------------------------------------------------------------------------
1 | import { inject, Injectable } from '@angular/core';
2 | import {
3 | Auth,
4 | authState,
5 | signInWithPopup,
6 | GoogleAuthProvider,
7 | signOut,
8 | user,
9 | getAuth,
10 | User,
11 | } from '@angular/fire/auth';
12 | import { map, switchMap, firstValueFrom, filter, Observable, Subscription } from 'rxjs';
13 | import {
14 | doc,
15 | docData,
16 | DocumentReference,
17 | Firestore,
18 | getDoc,
19 | setDoc,
20 | updateDoc,
21 | collection,
22 | addDoc,
23 | deleteDoc,
24 | collectionData,
25 | Timestamp,
26 | serverTimestamp,
27 | query,
28 | orderBy,
29 | limit,
30 | onSnapshot,
31 | DocumentData,
32 | FieldValue,
33 | } from '@angular/fire/firestore';
34 | import {
35 | Storage,
36 | getDownloadURL,
37 | ref,
38 | uploadBytesResumable,
39 | } from '@angular/fire/storage';
40 | import { getToken, Messaging, onMessage } from '@angular/fire/messaging';
41 | import { Router } from '@angular/router';
42 |
43 | type ChatMessage = {
44 | name: string | null,
45 | profilePicUrl: string | null,
46 | timestamp: FieldValue,
47 | uid: string | null,
48 | text?: string,
49 | imageUrl?: string
50 | };
51 |
52 |
53 | @Injectable({
54 | providedIn: 'root',
55 | })
56 | export class ChatService {
57 | firestore: Firestore = inject(Firestore);
58 | auth: Auth = inject(Auth);
59 | storage: Storage = inject(Storage);
60 | messaging: Messaging = inject(Messaging);
61 | router: Router = inject(Router);
62 | private provider = new GoogleAuthProvider();
63 | LOADING_IMAGE_URL = 'https://www.google.com/images/spin-32.gif?a';
64 |
65 | // observable that is updated when the auth state changes
66 | user$ = user(this.auth);
67 | currentUser: User | null = this.auth.currentUser;
68 | userSubscription: Subscription;
69 |
70 | constructor() {
71 | this.userSubscription = this.user$.subscribe((aUser: User | null) => {
72 | this.currentUser = aUser;
73 | });
74 | }
75 |
76 | // Login Friendly Chat.
77 | login() {}
78 |
79 | // Logout of Friendly Chat.
80 | logout() {}
81 |
82 | // Adds a text or image message to Cloud Firestore.
83 | addMessage = async (
84 | textMessage: string | null,
85 | imageUrl: string | null
86 | ): Promise> => {};
87 |
88 | // Saves a new message to Cloud Firestore.
89 | saveTextMessage = async (messageText: string) => {
90 | return this.addMessage(messageText, null);
91 | };
92 |
93 | // Loads chat messages history and listens for upcoming ones.
94 | loadMessages = () => {
95 | return null as unknown;
96 | };
97 |
98 | // Saves a new message containing an image in Firebase.
99 | // This first saves the image in Firebase storage.
100 | saveImageMessage = async (file: any) => {};
101 |
102 | async updateData(path: string, data: any) {}
103 |
104 | async deleteData(path: string) {}
105 |
106 | getDocData(path: string) {}
107 |
108 | getCollectionData(path: string) {}
109 |
110 | async uploadToStorage(
111 | path: string,
112 | input: HTMLInputElement,
113 | contentType: any
114 | ) {
115 | return null;
116 | }
117 | // Requests permissions to show notifications.
118 | requestNotificationsPermissions = async () => {};
119 |
120 | saveMessagingDeviceToken = async () => {};
121 | }
122 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlychat-web/steps/src/assets/.gitkeep
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/FriendlyChatLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlychat-web/steps/src/assets/FriendlyChatLogo.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/Google.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlychat-web/steps/src/assets/Google.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/WithFirebase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlychat-web/steps/src/assets/WithFirebase.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/add.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
13 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/menu.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/assets/send.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | firebase: {
3 | apiKey: 'API_KEY',
4 | authDomain: 'PROJECT_ID.firebaseapp.com',
5 | databaseURL: 'https://PROJECT_ID.firebaseio.com',
6 | projectId: 'PROJECT_ID',
7 | storageBucket: 'PROJECT_ID.appspot.com',
8 | messagingSenderId: 'SENDER_ID',
9 | appId: 'APP_ID',
10 | measurementId: 'G-MEASUREMENT_ID',
11 | },
12 | };
13 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlychat-web/steps/src/favicon.ico
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Friendlychat
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/main.ts:
--------------------------------------------------------------------------------
1 | import { bootstrapApplication } from '@angular/platform-browser';
2 | import { AppComponent } from './app/app.component';
3 | import { appConfig } from './app/app.config';
4 |
5 | bootstrapApplication(AppComponent, appConfig).catch((err) =>
6 | console.error(err)
7 | );
8 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/src/styles.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/storage.rules:
--------------------------------------------------------------------------------
1 | rules_version = '2';
2 |
3 | // Craft rules based on data in your Firestore database
4 | // allow write: if firestore.get(
5 | // /databases/(default)/documents/users/$(request.auth.uid)).data.isAdmin;
6 | service firebase.storage {
7 | match /b/{bucket}/o {
8 | match /{allPaths=**} {
9 | allow read, write: if false;
10 | }
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/tailwind.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: ["./src/app/*.{html,ts}", "./src/app/***/**/*.{html,ts}", "./src/app/**/*.{html,ts}", "./src/*.{html,ts}"],
4 | theme: {
5 | extend: {
6 | colors: {
7 | 'navy': {
8 | 10: '#F6F7F9',
9 | 20: '#E5EAF0',
10 | 30: '#D4DCE7',
11 | 40: '#C3CFDD',
12 | 50: '#B2C1D4',
13 | 100: '#8EA1B9',
14 | 200: '#6B829D',
15 | 300: '#476282',
16 | 400: '#385574',
17 | 500: '#2A4865',
18 | 600: '#1B3A57',
19 | 700: '#0C2D48',
20 | 800: '#051E34',
21 | 900: '#031525',
22 | },
23 | 'amber': {
24 | 50: '#FFF8E1',
25 | 100: '#FFECB3',
26 | 200: '#FFE082',
27 | 300: '#FFD54F',
28 | 400: '#FFCA28',
29 | 500: '#FFC107',
30 | 600: '#FFB300',
31 | 700: '#FFA000',
32 | 800: '#FF8F00',
33 | 900: '#FF6F00',
34 | A100: '#FFE57F',
35 | A200: '#FFD740',
36 | A400: '#FFC400',
37 | A700: '#FFAB00',
38 | }
39 | },
40 | },
41 | },
42 | plugins: [],
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/app",
6 | "types": []
7 | },
8 | "files": [
9 | "src/main.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/tsconfig.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "compileOnSave": false,
4 | "compilerOptions": {
5 | "baseUrl": "./",
6 | "outDir": "./dist/out-tsc",
7 | "forceConsistentCasingInFileNames": true,
8 | "strict": true,
9 | "noImplicitOverride": true,
10 | "noPropertyAccessFromIndexSignature": true,
11 | "noImplicitReturns": true,
12 | "noFallthroughCasesInSwitch": true,
13 | "sourceMap": true,
14 | "declaration": false,
15 | "downlevelIteration": true,
16 | "experimentalDecorators": true,
17 | "moduleResolution": "node",
18 | "importHelpers": true,
19 | "target": "ES2022",
20 | "module": "ES2022",
21 | "useDefineForClassFields": false,
22 | "lib": [
23 | "ES2022",
24 | "dom"
25 | ]
26 | },
27 | "angularCompilerOptions": {
28 | "enableI18nLegacyMessageIdFormat": false,
29 | "strictInjectionParameters": true,
30 | "strictInputAccessModifiers": true,
31 | "strictTemplates": true
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlychat-web/steps/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | /* To learn more about this file see: https://angular.io/config/tsconfig. */
2 | {
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "outDir": "./out-tsc/spec",
6 | "types": [
7 | "jasmine"
8 | ]
9 | },
10 | "include": [
11 | "src/**/*.spec.ts",
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/1129441c6ebb5eaf.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/1129441c6ebb5eaf.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/4c68c6654f4168ad.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/4c68c6654f4168ad.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/67898572a35672a5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/67898572a35672a5.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/73d151ed16016421.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/73d151ed16016421.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/78fa16cdf8ef435a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/78fa16cdf8ef435a.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/7a67a8a400c80c50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/7a67a8a400c80c50.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/95691e9b71ba55e3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/95691e9b71ba55e3.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/9d2f625aebcab6af.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/9d2f625aebcab6af.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/9e45f40faefce5d0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/9e45f40faefce5d0.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/a670188398c3c59.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/a670188398c3c59.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/de06424023ffb4b9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/de06424023ffb4b9.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/emulators-auth.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/emulators-auth.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/emulators-firebase.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/emulators-firebase.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/f9e670f40bd615b0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/f9e670f40bd615b0.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-android/steps/img/sign-in-providers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-android/steps/img/sign-in-providers.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/.gitignore:
--------------------------------------------------------------------------------
1 | firestore-web
2 | !firestore-web/.firebaserc
3 | !firestore-web/firebase.json
4 |
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img1.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img2.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img3.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img4.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img5.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img6.png
--------------------------------------------------------------------------------
/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/firebase/firebase-docs/1f7c41f79f538686773a23cb869b7ac209575acb/codelabs/codelab-friendlyeats-web/vanilla-js/steps/img/img7.png
--------------------------------------------------------------------------------
/docs/flutter/README.md:
--------------------------------------------------------------------------------
1 | # Flutter docs on firebase.google.com
2 |
3 | This directory contains the source of the Flutter documentation on
4 | https://firebase.google.com/docs/.
5 |
6 | We welcome your corrections and improvements! If you're interested in
7 | contributing, see [`CONTRIBUTING.md`](../CONTRIBUTING.md) for general
8 | guidelines.
9 |
10 | This file has some information on how our documentation is organized and some
11 | non-standard extensions we use.
12 |
13 | ## Where are the Firestore docs?
14 |
15 | Only the code snippets are on GitHub. You can find them in the
16 | [`firebase/snippets-flutter`][snippets-repo] repository.
17 |
18 | ## Standalone files vs. page fragments
19 |
20 | There are two kinds of source file for our docs:
21 |
22 | - **Standalone files** map one-to-one to a single page on firebase.google.com.
23 | These files are mostly-standard Markdown with filenames that correspond with
24 | the URL at which they're eventually published.
25 |
26 | For example, the file [`read-and-write.md`](/docs/database/read-and-write.md)
27 | is published to https://firebase.google.com/docs/database/flutter/read-and-write.
28 |
29 | Standalone pages must have filenames that don't begin with an
30 | underscore (`_`).
31 |
32 | - **Page fragments** are included in other pages. We use page fragments either
33 | to include common text in multiple pages or to help organize large pages.
34 | Like standalone files, page fragments are also mostly-standard Markdown, but
35 | their filenames often don't correspond with the URL at which they're
36 | eventually published.
37 |
38 | For example, the file [`_deobfuscated.md`](/docs/crashlytics/_deobfuscated.md)
39 | is published to https://firebase.google.com/docs/crashlytics/get-deobfuscated-reports?platform=flutter.
40 |
41 | Page fragments almost always have filenames that begin with an underscore
42 | (`_`).
43 |
44 | ## Non-standard Markdown
45 |
46 | ### File includes
47 |
48 | > Probably not useful to you as a contributor, but documented FYI.
49 |
50 | We use double angle brackets to include content from another file:
51 |
52 | ```
53 | <>
54 | ```
55 |
56 | Note that the path is based on our internal directory structure, and not the
57 | layout on GitHub. Also note that we sometimes use this to include non-Flutter
58 | related content that's not on GitHub.
59 |
60 | ### Page metadata
61 |
62 | > Probably not useful to you as a contributor, but documented FYI.
63 |
64 | Every standalone page begins with the following header:
65 |
66 | ```
67 | Project: /docs/_project.yaml
68 | Book: /docs/_book.yaml
69 | ```
70 |
71 | These are non-standard metadata declarations used by our internal publishing
72 | system. There's nothing you can really do with this, but it has to be on every
73 | standalone page.
74 |
75 | ## Non-standard Jinja
76 |
77 | ### includecode
78 |
79 | Code snippets are included from standalone Dart files, which helps facilitate
80 | automated testing. The following custom Jinja tag includes a code snippet into
81 | a file:
82 |
83 | ```
84 | {% includecode github_path="organization/repository/path/to/file" region_tag="tag_name" %}
85 | ```
86 |
87 | For example, the file [`firestore.dart`][firestore-snippets] in the
88 | [`firebase/snippets-flutter`][snippets-repo] repository contains a passage like
89 | this:
90 |
91 | ```dart
92 | void addData_addADocument() {
93 | // [START add_data_add_a_document]
94 | db.collection("cities").doc("new-city-id").set({"name": "Chicago"});
95 | // [END add_data_add_a_document]
96 | }
97 | ```
98 |
99 | To include the line between the `START` and `END` tags in a page, do the
100 | following:
101 |
102 | ```
103 | {% includecode
104 | github_path="firebase/snippets-flutter/packages/firebase_snippets_app/lib/snippets/firestore.dart"
105 | region_tag="add_data_add_a_document"
106 | adjust_indentation="auto" %}
107 | ```
108 |
109 | To update a snippet, submit a PR to the [`snippets-flutter` repo][snippets-repo].
110 |
111 | [firestore-snippets]: https://github.com/firebase/snippets-flutter/blob/main/packages/firebase_snippets_app/lib/snippets/firestore.dart
112 | [snippets-repo]: https://github.com/firebase/snippets-flutter/
113 |
--------------------------------------------------------------------------------
/docs/flutter/analytics/_events.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/analytics/events?platform=flutter #}
3 |
4 | Analytics automatically logs some
5 | [events](https://support.google.com/analytics/answer/9234069) for you; you don't
6 | need to add any code to receive them. If your app needs to collect additional
7 | data, you can log up to 500 different Analytics Event *types* in your app.
8 | There is no limit on the total volume of events your app logs. Note that event
9 | names are case-sensitive and that logging two events whose names differ only in
10 | case will result in two distinct events.
11 |
12 | ## Before you begin
13 |
14 | Make sure that you've set up your project and can access Analytics as
15 | described in [Get Started with Analytics](get-started).
16 |
17 | ## Log events
18 |
19 | After you have created a `FirebaseAnalytics` instance, you can use it to log
20 | events with the library's `log`- methods.
21 |
22 | ### Predefined events
23 |
24 | To help you get started, the Analytics SDK defines a number of
25 | recommended events that are common among different types of apps, including
26 | retail and ecommerce, travel, and gaming apps. To learn more
27 | [about these events](https://support.google.com/analytics/answer/9322688)
28 | and when to use them, see
29 | [Recommended events](https://support.google.com/analytics/answer/9267735).
30 |
31 | Note: To get the maximum detail in reports, log the recommended events that make
32 | sense for your app and their prescribed parameters. This also ensures that you
33 | benefit from the latest Google Analytics features as
34 | they become available.
35 |
36 | You can find the log methods for the recommended event types in the
37 | [API reference](https://pub.dev/documentation/firebase_analytics/latest/firebase_analytics/FirebaseAnalytics-class.html).
38 |
39 | The following example demonstrates how to log a `select_content` event:
40 |
41 | ```dart
42 | await FirebaseAnalytics.instance.logSelectContent(
43 | contentType: "image",
44 | itemId: itemId,
45 | );
46 | ```
47 |
48 | Alternatively, you can log the same event using `logEvent()`:
49 |
50 | ```dart
51 | await FirebaseAnalytics.instance.logEvent(
52 | name: "select_content",
53 | parameters: {
54 | "content_type": "image",
55 | "item_id": itemId,
56 | },
57 | );
58 | ```
59 |
60 | This can be useful if you want to specify additional parameters other than the
61 | prescribed (required) parameters. You can add the following parameters
62 | to any event:
63 |
64 | * Custom parameters: Custom parameters can be used as
65 | [dimensions or metrics](https://support.google.com/analytics/answer/10075209)
66 | in [Analytics reports](https://support.google.com/analytics/answer/9212670).
67 | You can use custom dimensions for non-numerical event parameter data and
68 | custom metrics for any parameter data better represented numerically. After
69 | you've logged a custom parameter using the SDK, register the dimension or
70 | metric to ensure those custom parameters appear in Analytics
71 | reports. Do this using *Analytics > Events > Manage Custom Definitions >
72 | Create Custom Dimensions*.
73 |
74 | Custom parameters can be used in
75 | [audience](https://support.google.com/firebase/answer/6317509)
76 | definitions that may be applied to every report.
77 | Custom parameters are also included in data
78 | [exported to BigQuery](https://support.google.com/firebase/answer/7030014)
79 | if your app is linked to a BigQuery project. Find sample queries and much more
80 | at [Google Analytics 4 BigQuery Export](https://developers.google.com/analytics/bigquery).
81 |
82 | * `value` parameter: a general purpose parameter
83 | that is useful for accumulating a key metric that pertains to an
84 | event. Examples include revenue, distance, time, and points.
85 | * Parameter names can be up to 40 characters long and must start with an alphabetic
86 | character and contain only alphanumeric characters and underscores. String and num
87 | types are supported. String parameter values can be up to 100 characters long.
88 | The "firebase_", "google_" and "ga_" prefixes are reserved and shouldn't be
89 | used for parameter names.
90 |
91 | ### Custom events
92 |
93 | If your application has specific needs not covered by a recommended
94 | event type, you can log your own custom events as shown in this example:
95 |
96 | ```dart
97 | await FirebaseAnalytics.instance.logEvent(
98 | name: "share_image",
99 | parameters: {
100 | "image_name": name,
101 | "full_text": text,
102 | },
103 | );
104 | ```
105 |
106 | ## Set default event parameters
107 |
108 | You can log parameters across events using `setDefaultEventParameters()`.
109 | Default parameters are associated with all future events that are logged.
110 |
111 | As with custom parameters, register the default event parameters to ensure they
112 | appear in Analytics reports.
113 |
114 | Valid parameter values are String and num. Setting a key's value to `null`
115 | clears that parameter. Passing in a null value clears all parameters.
116 |
117 | ```dart
118 | // Not supported on web
119 | await FirebaseAnalytics.instance
120 | .setDefaultEventParameters({
121 | version: '1.2.3'
122 | });
123 | ```
124 |
125 | If a parameter is specified in the `logEvent()` or `log`-
126 | method, that value is used instead of the default.
127 |
128 | To clear a default parameter, call the `setDefaultEventParameters()`
129 | method with the parameter set to `null`.
130 |
--------------------------------------------------------------------------------
/docs/flutter/analytics/_get-started.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/analytics/get-started?platform=flutter #}
3 |
4 | Google Analytics collects usage and behavior data for your app. The SDK
5 | logs two primary types of information:
6 |
7 | * **Events:** What is happening in your app, such as user actions, system
8 | events, or errors.
9 | * **User properties:** Attributes you define to describe segments of your
10 | user base, such as language preference or geographic location.
11 |
12 | Analytics automatically logs some
13 | [events](https://support.google.com/analytics/answer/9234069) and
14 | [user properties](https://support.google.com/analytics/answer/9268042);
15 | you don't need to add any code to enable them.
16 |
17 | ## Before you begin
18 |
19 | 1. [Install `firebase_core`](/docs/flutter/setup) and add the initialization code
20 | to your app if you haven't already.
21 | 1. Add your app to your Firebase project in the
22 | [Firebase console](https://console.firebase.google.com).
23 |
24 | ## Add the Analytics SDK to your app {:#add-sdk}
25 |
26 | 1. From the root of your Flutter project, run the following command to install the plugin:
27 |
28 | ```bash {5}
29 | flutter pub add firebase_analytics
30 | ```
31 |
32 | 1. Once complete, rebuild your Flutter application:
33 |
34 | ```bash
35 | flutter run
36 | ```
37 |
38 | 1. Once installed, you can access the `firebase_analytics`
39 | plugin by importing it in your Dart code:
40 |
41 | ```dart
42 | import 'package:firebase_analytics/firebase_analytics.dart';
43 | ```
44 |
45 | 1. Create a new Firebase Analytics instance by accessing the
46 | `instance` property on
47 | `FirebaseAnalytics`:
48 |
49 | ```dart
50 | FirebaseAnalytics analytics = FirebaseAnalytics.instance;
51 | ```
52 |
53 |
54 | ## Start logging events
55 |
56 | After you have created a `FirebaseAnalytics` instance, you can begin to log
57 | events with the library's `log`- methods.
58 |
59 | Certain events are
60 | [recommended for all apps](https://support.google.com/analytics/answer/9267735);
61 | others are recommended for specific business types or verticals. You should send
62 | recommended events along with their prescribed parameters, to ensure maximum
63 | available detail in your reports and to benefit from future features and
64 | integrations as they become available. This section demonstrates logging a
65 | predefined event, for more information on logging events, see
66 | [Log events](events).
67 |
68 | The following code logs a checkout event:
69 |
70 | ```dart
71 | await FirebaseAnalytics.instance
72 | .logBeginCheckout(
73 | value: 10.0,
74 | currency: 'USD',
75 | items: [
76 | AnalyticsEventItem(
77 | itemName: 'Socks',
78 | itemId: 'xjw73ndnw',
79 | price: '10.0'
80 | ),
81 | ],
82 | coupon: '10PERCENTOFF'
83 | );
84 | ```
85 |
86 | ## Next steps
87 |
88 | * Use the [DebugView](/docs/analytics/debugview) to verify your events.
89 | * Explore your data in the [Firebase console](https://console.firebase.google.com/project/_/analytics/).
90 | * Explore the guides on [events](events) and
91 | [user properties](user-properties).
92 | * Learn how to export your data to [BigQuery](https://support.google.com/firebase/answer/7030014).
93 |
--------------------------------------------------------------------------------
/docs/flutter/analytics/_user-properties.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/analytics/user-properties?platform=flutter #}
3 |
4 | {# TODO(markarndt): Sync all this content up with Analytics content
5 | consolidation plan. #}
6 |
7 | ## Before you begin
8 |
9 | Make sure that you've set up your project and can access {{analytics}} as
10 | described in [Get Started with {{analytics}}](get-started).
11 |
12 | ## Set user properties
13 |
14 | You can set {{ analytics }} user properties to describe the users of your app.
15 | You can make use of user properties by creating custom definitions, then using
16 | them to apply comparisons in your reports or as audience evaluation criteria.
17 |
18 | To set a user property, follow these steps:
19 |
20 | 1. Create a custom definition for the user property in the
21 | [**Custom Definitions** page](https://console.firebase.google.com/project/_/analytics/userproperty){: .external}
22 | of _{{analytics}}_ in the {{name_appmanager}}. For more information, see
23 | [Custom dimensions and metrics](https://support.google.com/analytics/answer/10075209).
24 | 1. Set a user property in your app with the `setUserProperty()` method.
25 |
26 | The following example adds a hypothetical favorite food property, which
27 | assigns the value in `favoriteFood` to the active user:
28 |
29 | ```dart
30 | await FirebaseAnalytics.instance
31 | .setUserProperty({
32 | name: 'favorite_food',
33 | value: favoriteFood,
34 | });
35 | ```
36 |
--------------------------------------------------------------------------------
/docs/flutter/app-check/custom-resource.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Protect non-Firebase resources with App Check
7 |
8 | You can protect your app's non-Firebase resources, such as self-hosted backends,
9 | with App Check. To do so, you will need to do both of the following:
10 |
11 | - Modify your app client to send an App Check token along with each request
12 | to your backend, as described on this page.
13 | - Modify your backend to require a valid App Check token with every request,
14 | as described in [Verify App Check tokens from a custom backend](/docs/app-check/custom-resource-backend).
15 |
16 | ## Before you begin
17 |
18 | Add App Check to your app, using the [default providers](default-providers).
19 |
20 | ## Send App Check tokens with backend requests
21 |
22 | To ensure your backend requests include a valid, unexpired, App Check token,
23 | precede each request with a call to `getToken()`. The App Check library
24 | will refresh the token if necessary.
25 |
26 | Once you have a valid token, send it along with the request to your backend. The
27 | specifics of how you accomplish this are up to you, but _don't send
28 | App Check tokens as part of URLs_, including in query parameters, as this
29 | makes them vulnerable to accidental leakage and interception. The recommended
30 | approach is to send the token in a custom HTTP header.
31 |
32 | For example:
33 |
34 | ```dart
35 | void callApiExample() async {
36 | final appCheckToken = await FirebaseAppCheck.instance.getToken();
37 | if (appCheckToken != null) {
38 | final response = await http.get(
39 | Uri.parse("https://yourbackend.example.com/yourExampleEndpoint"),
40 | headers: {"X-Firebase-AppCheck": appCheckToken},
41 | );
42 | } else {
43 | // Error: couldn't get an App Check token.
44 | }
45 | }
46 | ```
47 |
--------------------------------------------------------------------------------
/docs/flutter/app-check/debug-provider.md:
--------------------------------------------------------------------------------
1 | Project: /docs/app-check/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 | {% include "docs/app-check/_local_variables.html" %}
6 | {% include "_shared/firebase/_snippet_include_comment.html" %}
7 |
8 | # Use App Check with the debug provider with Flutter
9 |
10 | After you have registered your app for App Check, your app normally won't run
11 | in an emulator or from a continuous integration (CI) environment, since those
12 | environments don't qualify as valid devices. If you want to run your app in such
13 | an environment during development and testing, you can create a debug build of
14 | your app that uses the App Check debug provider instead of a real attestation
15 | provider.
16 |
17 | Warning: The debug provider allows access to your Firebase resources from
18 | unverified devices. Don't use the debug provider in production builds of your
19 | app, and don't share your debug builds with untrusted parties.
20 |
21 | ## Apple platforms
22 |
23 | To use the debug provider while running your app in a simulator interactively
24 | (during development, for example), do the following:
25 |
26 | 1. Activate App Check with the debug provider right after you have initialized
27 | your Firebase app:
28 |
29 | ```dart
30 | import 'package:flutter/material.dart';
31 | import 'package:firebase_core/firebase_core.dart';
32 |
33 | // Import the firebase_app_check plugin
34 | import 'package:firebase_app_check/firebase_app_check.dart';
35 |
36 | Future main() async {
37 | WidgetsFlutterBinding.ensureInitialized();
38 | await Firebase.initializeApp();
39 | await FirebaseAppCheck.instance.activate(
40 | // Set appleProvider to `AppleProvider.debug`
41 | appleProvider: AppleProvider.debug,
42 | );
43 | runApp(App());
44 | }
45 | ```
46 |
47 | 1. Enable debug logging in your Xcode project (v11.0 or newer):
48 |
49 | 1. Open **Product > Scheme > Edit scheme**.
50 | 1. Select **Run** from the left menu, then select the **Arguments** tab.
51 | 1. In the **Arguments Passed on Launch** section, add `-FIRDebugEnabled`.
52 |
53 | 1. Open `ios/Runner.xcworkspace` with Xcode and run your app in the Simulator.
54 | Your app will print a local debug token to the debug output when Firebase
55 | tries to send a request to the backend. For example:
56 |
57 |
59 |
60 | {# Google-internal common file: #}
61 | <<../_includes/manage-debug-tokens.md>>
62 |
63 | After you register the token, Firebase backend services will accept it as valid.
64 |
65 | Because this token allows access to your Firebase resources without a
66 | valid device, it is crucial that you keep it private. Don't commit it to a
67 | public repository, and if a registered token is ever compromised, revoke it
68 | immediately in the Firebase console.
69 |
70 | ## Android
71 |
72 | To use the debug provider while running your Flutter app in an Android environment,
73 | implement the following code in your Flutter application:
74 |
75 | ```dart
76 | import 'package:flutter/material.dart';
77 | import 'package:firebase_core/firebase_core.dart';
78 |
79 | // Import the firebase_app_check plugin
80 | import 'package:firebase_app_check/firebase_app_check.dart';
81 |
82 | Future main() async {
83 | WidgetsFlutterBinding.ensureInitialized();
84 | await Firebase.initializeApp();
85 | await FirebaseAppCheck.instance.activate(
86 | webRecaptchaSiteKey: 'recaptcha-v3-site-key',
87 | // Set androidProvider to `AndroidProvider.debug`
88 | androidProvider: AndroidProvider.debug,
89 | );
90 | runApp(App());
91 | }
92 |
93 | ```
94 |
95 | Your app will print a local debug token to the debug output when Firebase tries
96 | to send a request to the backend. For example:
97 |
98 |
D DebugAppCheckProvider: Enter this debug secret into the allow list in
99 | the Firebase Console for your project: 123a4567-b89c-12d3-e456-789012345678
100 |
101 | {# Google-internal common file: #}
102 | <<../_includes/manage-debug-tokens.md>>
103 |
104 | After you register the token, Firebase backend services will accept it as valid.
105 |
106 | ## Web
107 |
108 | To use the debug provider while running your app from `localhost` (during
109 | development, for example), do the following:
110 |
111 | Warning: _Do not_ try to enable `localhost` debugging by adding `localhost` to
112 | reCAPTCHA’s allowed domains. Doing so would allow anyone to run your app from
113 | their local machines!
114 |
115 | 1. In the file `web/index.html`, enable debug mode by setting
116 | `self.FIREBASE_APPCHECK_DEBUG_TOKEN` to `true`:
117 |
118 | ```html
119 |
120 |
123 |
124 | ...
125 |
126 |
127 | ```
128 |
129 | 1. Run your web app locally and open the browser’s developer tool. In the
130 | debug console, you’ll see a debug token:
131 |
132 |
AppCheck debug token: "123a4567-b89c-12d3-e456-789012345678". You will
133 | need to safelist it in the Firebase console for it to work.
134 |
135 | This token is stored locally in your browser and will be used whenever you
136 | use your app in the same browser on the same machine. If you want to use the
137 | token in another browser or on another machine, set
138 | `self.FIREBASE_APPCHECK_DEBUG_TOKEN` to the token string instead of `true`.
139 |
140 | {# Google-internal common file: #}
141 | <<../_includes/manage-debug-tokens.md>>
142 |
143 | After you register the token, Firebase backend services will accept it as valid.
144 |
145 | Because this token allows access to your Firebase resources without a
146 | valid device, it is crucial that you keep it private. Don't commit it to a
147 | public repository, and if a registered token is ever compromised, revoke it
148 | immediately in the Firebase console.
149 |
--------------------------------------------------------------------------------
/docs/flutter/app-check/default-providers.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Get started using App Check in Flutter apps
7 |
8 | This page shows you how to enable App Check in a Flutter app, using the
9 | default providers: Play Integrity on Android, Device Check on Apple platforms, and
10 | reCAPTCHA v3 on web. When you enable App Check, you help ensure that
11 | only your app can access your project's Firebase resources. See an
12 | [Overview](/docs/app-check) of this feature.
13 |
14 |
15 | ## 1. Set up your Firebase project {:#project-setup}
16 |
17 | 1. [Install and initialize FlutterFire](/docs/flutter/setup) if you haven't
18 | already done so.
19 |
20 | 1. Register your apps to use App Check with the Play Integrity, Device Check, and reCAPTCHA providers in the
21 | [**Project Settings > App Check**](https://console.firebase.google.com/project/_/appcheck)
22 | section of the Firebase console.
23 |
24 | You usually need to register all of your project's apps, because once you
25 | enable enforcement for a Firebase product, only registered apps will be able
26 | to access the product's backend resources.
27 |
28 | 1. **Optional**: In the app registration settings, set a custom time-to-live
29 | (TTL) for App Check tokens issued by the provider. You can set the TTL
30 | to any value between 30 minutes and 7 days. When changing this value, be
31 | aware of the following tradeoffs:
32 |
33 | - Security: Shorter TTLs provide stronger security, because it reduces the
34 | window in which a leaked or intercepted token can be abused by an
35 | attacker.
36 | - Performance: Shorter TTLs mean your app will perform attestation more
37 | frequently. Because the app attestation process adds latency to network
38 | requests every time it's performed, a short TTL can impact the performance
39 | of your app.
40 | - Quota and cost: Shorter TTLs and frequent re-attestation deplete your
41 | quota faster, and for paid services, potentially cost more.
42 | See [Quotas & limits](/docs/app-check#quotas_limits).
43 |
44 | The default TTL
45 | is reasonable for most apps. Note that the App Check library refreshes
46 | tokens at approximately half the TTL duration.
47 |
48 |
49 | ## 2. Add the App Check library to your app {:#install-sdk}
50 |
51 | 1. From the root of your Flutter project, run the following command to install the plugin:
52 |
53 | ```bash
54 | flutter pub add firebase_app_check
55 | ```
56 |
57 | 1. Once complete, rebuild your Flutter application:
58 |
59 | ```bash
60 | flutter run
61 | ```
62 |
63 |
64 | ## 3. Initialize App Check {:#initialize}
65 |
66 | Add the following initialization code to your app so that it runs before you
67 | use any Firebase services such as Storage, but after calling
68 | `Firebase.initializeApp()`;
69 |
70 | ```dart
71 | import 'package:flutter/material.dart';
72 | import 'package:firebase_core/firebase_core.dart';
73 |
74 | // Import the firebase_app_check plugin
75 | import 'package:firebase_app_check/firebase_app_check.dart';
76 |
77 | Future main() async {
78 | WidgetsFlutterBinding.ensureInitialized();
79 | await Firebase.initializeApp();
80 | await FirebaseAppCheck.instance.activate(
81 | // You can also use a `ReCaptchaEnterpriseProvider` provider instance as an
82 | // argument for `webProvider`
83 | webProvider: ReCaptchaV3Provider('recaptcha-v3-site-key'),
84 | // Default provider for Android is the Play Integrity provider. You can use the "AndroidProvider" enum to choose
85 | // your preferred provider. Choose from:
86 | // 1. Debug provider
87 | // 2. Safety Net provider
88 | // 3. Play Integrity provider
89 | androidProvider: AndroidProvider.debug,
90 | // Default provider for iOS/macOS is the Device Check provider. You can use the "AppleProvider" enum to choose
91 | // your preferred provider. Choose from:
92 | // 1. Debug provider
93 | // 2. Device Check provider
94 | // 3. App Attest provider
95 | // 4. App Attest provider with fallback to Device Check provider (App Attest provider is only available on iOS 14.0+, macOS 14.0+)
96 | appleProvider: AppleProvider.appAttest,
97 | );
98 | runApp(App());
99 | }
100 | ```
101 |
102 | ## Next steps
103 |
104 | Once the App Check library is installed in your app, start distributing the
105 | updated app to your users.
106 |
107 | The updated client app will begin sending App Check tokens along with every
108 | request it makes to Firebase, but Firebase products will not require the tokens
109 | to be valid until you enable enforcement in the App Check section of the
110 | Firebase console.
111 |
112 | ### Monitor metrics and enable enforcement {:#monitor}
113 |
114 | Before you enable enforcement, however, you should make sure that doing so won't
115 | disrupt your existing legitimate users. On the other hand, if you're seeing
116 | suspicious use of your app resources, you might want to enable enforcement
117 | sooner.
118 |
119 | To help make this decision, you can look at App Check metrics for the
120 | services you use:
121 |
122 | - [Monitor App Check request metrics](/docs/app-check/monitor-metrics) for
123 | Realtime Database, Cloud Firestore, Cloud Storage, and Authentication.
124 | - [Monitor App Check request metrics for Cloud Functions](/docs/app-check/monitor-functions-metrics).
125 |
126 | ### Enable App Check enforcement {:#enforce}
127 |
128 | When you understand how App Check will affect your users and you're ready to
129 | proceed, you can enable App Check enforcement:
130 |
131 | - [Enable App Check enforcement](/docs/app-check/enable-enforcement) for
132 | Realtime Database, Cloud Firestore, Cloud Storage, and Authentication.
133 | - [Enable App Check enforcement for Cloud Functions](/docs/app-check/cloud-functions).
134 |
135 | ### Use App Check in debug environments {:#debug}
136 |
137 | If, after you have registered your app for App Check, you want to run your
138 | app in an environment that App Check would normally not classify as valid,
139 | such as an emulator during development, or from a continuous integration (CI)
140 | environment, you can create a debug build of your app that uses the
141 | App Check debug provider instead of a real attestation provider.
142 |
143 | See [Use App Check with the debug provider in Flutter apps](/docs/app-check/flutter/debug-provider).
144 |
--------------------------------------------------------------------------------
/docs/flutter/auth/account-linking.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Link Multiple Auth Providers to an Account
7 |
8 | You can allow users to sign in to your app using multiple authentication
9 | providers by linking auth provider credentials to an existing user account.
10 | Users are identifiable by the same Firebase user ID regardless of the
11 | authentication provider they used to sign in. For example, a user who signed in
12 | with a password can link a Google account and sign in with either method in the
13 | future. Or, an anonymous user can link a Facebook account and then, later, sign
14 | in with Facebook to continue using your app.
15 |
16 | ## Before you begin
17 |
18 | Add support for two or more authentication providers (possibly including
19 | anonymous authentication) to your app.
20 |
21 | ## Link auth provider credentials to a user account
22 |
23 | To link auth provider credentials to an existing user account:
24 |
25 | 1. Sign in the user using any authentication provider or method.
26 |
27 | 1. Complete the sign-in flow for the new authentication provider up to, but not
28 | including, calling one of the `signInWith`- methods. For example, get
29 | the user's Google ID token, Facebook access token, or email and password.
30 |
31 | 1. Get a `Credential` object for the new authentication provider:
32 |
33 | ```dart
34 | // Google Sign-in
35 | final credential = GoogleAuthProvider.credential(idToken: idToken);
36 |
37 | // Email and password sign-in
38 | final credential =
39 | EmailAuthProvider.credential(email: emailAddress, password: password);
40 |
41 | // Etc.
42 | ```
43 |
44 | 1. Pass the `Credential` object to the sign-in user's `linkWithCredential()`
45 | method:
46 |
47 | ```dart
48 | try {
49 | final userCredential = await FirebaseAuth.instance.currentUser
50 | ?.linkWithCredential(credential);
51 | } on FirebaseAuthException catch (e) {
52 | switch (e.code) {
53 | case "provider-already-linked":
54 | print("The provider has already been linked to the user.");
55 | break;
56 | case "invalid-credential":
57 | print("The provider's credential is not valid.");
58 | break;
59 | case "credential-already-in-use":
60 | print("The account corresponding to the credential already exists, "
61 | "or is already linked to a Firebase User.");
62 | break;
63 | // See the API reference for the full list of error codes.
64 | default:
65 | print("Unknown error.");
66 | }
67 | ```
68 |
69 | If the call to `linkWithCredential()` succeeds, the user can now sign in using
70 | any linked authentication provider and access the same Firebase data.
71 |
72 | ## Unlink an auth provider from a user account
73 |
74 | You can unlink an auth provider from an account, so that the user can no
75 | longer sign in with that provider.
76 |
77 | To unlink an auth provider from a user account, pass the provider ID to the
78 | `unlink()` method. You can get the provider IDs of the auth providers linked to
79 | a user from the `User` object's `providerData` property.
80 |
81 | ```dart
82 | try {
83 | await FirebaseAuth.instance.currentUser?.unlink(providerId);
84 | } on FirebaseAuthException catch (e) {
85 | switch (e.code) {
86 | case "no-such-provider":
87 | print("The user isn't linked to the provider or the provider "
88 | "doesn't exist.");
89 | break;
90 | default:
91 | print("Unknown error.");
92 | }
93 | }
94 | ```
95 |
--------------------------------------------------------------------------------
/docs/flutter/auth/anonymous-auth.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Authenticate with Firebase Anonymously
7 |
8 | You can use Firebase Authentication to create and use temporary anonymous accounts
9 | to authenticate with Firebase. These temporary anonymous accounts can be used to
10 | allow users who haven't yet signed up to your app to work with data protected
11 | by security rules. If an anonymous user decides to sign up to your app, you can
12 | [link their sign-in credentials](account-linking) to the anonymous account so
13 | that they can continue to work with their protected data in future sessions.
14 |
15 | ## Before you begin
16 |
17 | 1. If you haven't already, follow the steps in the [Get started](start) guide.
18 |
19 | 1. Enable Anonymous sign-in:
20 |
21 | - In the Firebase console's **Authentication** section, open the
22 | [Sign in method](https://console.firebase.google.com/project/_/authentication/providers)
23 | page.
24 | - From the **Sign in method** page, enable the **Anonymous sign-in**
25 | method and click **Save**.
26 |
27 | ## Authenticate with Firebase anonymously
28 |
29 | When a signed-out user uses an app feature that requires authentication with
30 | Firebase, sign in the user anonymously by calling `signInAnonymously()`:
31 |
32 | ```dart
33 | try {
34 | final userCredential =
35 | await FirebaseAuth.instance.signInAnonymously();
36 | print("Signed in with temporary account.");
37 | } on FirebaseAuthException catch (e) {
38 | switch (e.code) {
39 | case "operation-not-allowed":
40 | print("Anonymous auth hasn't been enabled for this project.");
41 | break;
42 | default:
43 | print("Unknown error.");
44 | }
45 | }
46 | ```
47 |
48 | Note: To protect your project from abuse, Firebase limits the number of new
49 | email/password and anonymous sign-ups that your application can have from the
50 | same IP address in a short period of time. You can request and schedule
51 | temporary changes to this quota from the
52 | [Firebase console](https://console.firebase.google.com/project/_/authentication/providers).
53 |
54 | ## Convert an anonymous account to a permanent account
55 |
56 | When an anonymous user signs up to your app, you might want to allow them to
57 | continue their work with their new account—for example, you might want to
58 | make the items the user added to their shopping cart before they signed up
59 | available in their new account's shopping cart. To do so, complete the following
60 | steps:
61 |
62 | 1. When the user signs up, complete the sign-in flow for the user's
63 | authentication provider up to, but not including, calling one of the
64 | `signInWith`- methods. For example, get the user's Google ID token,
65 | Facebook access token, or email address and password.
66 |
67 | 1. Get a `Credential` object for the new authentication provider:
68 |
69 | ```dart
70 | // Google Sign-in
71 | final credential = GoogleAuthProvider.credential(idToken: idToken);
72 |
73 | // Email and password sign-in
74 | final credential =
75 | EmailAuthProvider.credential(email: emailAddress, password: password);
76 |
77 | // Etc.
78 | ```
79 |
80 | 1. Pass the `Credential` object to the sign-in user's `linkWithCredential()`
81 | method:
82 |
83 | ```dart
84 | try {
85 | final userCredential = await FirebaseAuth.instance.currentUser
86 | ?.linkWithCredential(credential);
87 | } on FirebaseAuthException catch (e) {
88 | switch (e.code) {
89 | case "provider-already-linked":
90 | print("The provider has already been linked to the user.");
91 | break;
92 | case "invalid-credential":
93 | print("The provider's credential is not valid.");
94 | break;
95 | case "credential-already-in-use":
96 | print("The account corresponding to the credential already exists, "
97 | "or is already linked to a Firebase User.");
98 | break;
99 | // See the API reference for the full list of error codes.
100 | default:
101 | print("Unknown error.");
102 | }
103 | ```
104 |
105 | If the call to `linkWithCredential()` succeeds, the user's new account can
106 | access the anonymous account's Firebase data.
107 |
108 | Note: This technique can also be used to [link any two accounts](account-linking).
109 |
110 |
111 | ## Next steps
112 |
113 | After a user creates a new account, this account is stored as part of your
114 | Firebase project, and can be used to identify a user across every app in your
115 | project, regardless of what sign-in method the user used.
116 |
117 | In your apps, you can get the user's basic profile information from the
118 | `User` object. See [Manage Users](manage-users).
119 |
120 | In your Firebase Realtime Database and Cloud Storage Security Rules, you can
121 | get the signed-in user's unique user ID from the `auth` variable, and use it to
122 | control what data a user can access.
123 |
124 | You can allow users to sign in to your app using multiple authentication
125 | providers by [linking auth provider credentials](account-linking)) to an
126 | existing user account.
127 |
128 | To sign out a user, call `signOut()`:
129 |
130 | ```dart
131 | await FirebaseAuth.instance.signOut();
132 | ```
133 |
--------------------------------------------------------------------------------
/docs/flutter/auth/custom-auth.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Authenticate with Firebase Using a Custom Authentication System
7 |
8 | You can integrate Firebase Authentication with a custom authentication system by
9 | modifying your authentication server to produce custom signed tokens when a user
10 | successfully signs in. Your app receives this token and uses it to authenticate
11 | with Firebase.
12 |
13 | ## Before you begin
14 |
15 | 1. If you haven't already, follow the steps in the [Get started](start) guide.
16 | 1. [Install and configure the Firebase Admin SDK](/docs/admin/setup).
17 | Be sure to [initialize the SDK](/docs/admin/setup#initialize-sdk)
18 | with the correct credentials for your Firebase project.
19 |
20 | ## Authenticate with Firebase
21 |
22 | 1. When users sign in to your app, send their sign-in credentials (for
23 | example, their username and password) to your authentication server. Your
24 | server checks the credentials and, if they are valid,
25 | [creates a custom Firebase token](/docs/auth/admin/create-custom-tokens)
26 | and sends the token back to your app.
27 |
28 | 1. After you receive the custom token from your authentication server, pass it
29 | to `signInWithCustomToken()` to sign in the user:
30 |
31 | ```dart
32 | try {
33 | final userCredential =
34 | await FirebaseAuth.instance.signInWithCustomToken(token);
35 | print("Sign-in successful.");
36 | } on FirebaseAuthException catch (e) {
37 | switch (e.code) {
38 | case "invalid-custom-token":
39 | print("The supplied token is not a Firebase custom auth token.");
40 | break;
41 | case "custom-token-mismatch":
42 | print("The supplied token is for a different Firebase project.");
43 | break;
44 | default:
45 | print("Unknown error.");
46 | }
47 | }
48 | ```
49 |
50 | ## Next steps
51 |
52 | After a user creates a new account, this account is stored as part of your
53 | Firebase project, and can be used to identify a user across every app in your
54 | project, regardless of what sign-in method the user used.
55 |
56 | In your apps, you can get the user's basic profile information from the
57 | `User` object. See [Manage Users](manage-users).
58 |
59 | In your Firebase Realtime Database and Cloud Storage Security Rules, you can
60 | get the signed-in user's unique user ID from the `auth` variable, and use it to
61 | control what data a user can access.
62 |
63 | You can allow users to sign in to your app using multiple authentication
64 | providers by [linking auth provider credentials](account-linking)) to an
65 | existing user account.
66 |
67 | To sign out a user, call `signOut()`:
68 |
69 | ```dart
70 | await FirebaseAuth.instance.signOut();
71 | ```
72 |
--------------------------------------------------------------------------------
/docs/flutter/auth/errors.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Error Handling
7 |
8 | The Firebase Authentication SDKs provide a simple way for catching the various errors which may occur which using
9 | authentication methods. The SDKs for Flutter expose these errors via the `FirebaseAuthException`
10 | class.
11 |
12 | At a minimum, a `code` and `message` are provided, however in some cases additional properties such as an email address
13 | and credential are also provided. For example, if the user is attempting to sign in with an email and password,
14 | any errors thrown can be explicitly caught:
15 |
16 | ```dart
17 | try {
18 | await FirebaseAuth.instance.signInWithEmailAndPassword(
19 | email: "barry.allen@example.com",
20 | password: "SuperSecretPassword!"
21 | );
22 | } on FirebaseAuthException catch (e) {
23 | print('Failed with error code: ${e.code}');
24 | print(e.message);
25 | }
26 | ```
27 |
28 | Each method provides various error codes and messages depending on the type of authentication invocation type. The
29 | [Reference API](https://pub.dev/documentation/firebase_auth/latest/) provides up-to-date details on the errors for each method.
30 |
31 | Other errors such as `too-many-requests` or `operation-not-allowed` may be thrown if you reach the Firebase Authentication quota,
32 | or have not enabled a specific auth provider.
33 |
34 | ## Handling `account-exists-with-different-credential` Errors
35 |
36 | If you enabled the One account per email address setting in the [Firebase console](https://console.firebase.google.com/project/_/authentication/providers),
37 | when a user tries to sign in a to a provider (such as Google) with an email that already exists for another Firebase user's provider
38 | (such as Facebook), the error `auth/account-exists-with-different-credential` is thrown along with an `AuthCredential` class (Google ID token).
39 | To complete the sign-in flow to the intended provider, the user has to first sign in to the existing provider (e.g. Facebook) and then link to the former
40 | `AuthCredential` (Google ID token).
41 |
42 | ```dart
43 | FirebaseAuth auth = FirebaseAuth.instance;
44 |
45 | // Create a credential from a Google Sign-in Request
46 | var googleAuthCredential = GoogleAuthProvider.credential(accessToken: 'xxxx');
47 |
48 | try {
49 | // Attempt to sign in the user in with Google
50 | await auth.signInWithCredential(googleAuthCredential);
51 | } on FirebaseAuthException catch (e) {
52 | if (e.code == 'account-exists-with-different-credential') {
53 | // The account already exists with a different credential
54 | String email = e.email;
55 | AuthCredential pendingCredential = e.credential;
56 |
57 | // Fetch a list of what sign-in methods exist for the conflicting user
58 | List userSignInMethods = await auth.fetchSignInMethodsForEmail(email);
59 |
60 | // If the user has several sign-in methods,
61 | // the first method in the list will be the "recommended" method to use.
62 | if (userSignInMethods.first == 'password') {
63 | // Prompt the user to enter their password
64 | String password = '...';
65 |
66 | // Sign the user in to their account with the password
67 | UserCredential userCredential = await auth.signInWithEmailAndPassword(
68 | email: email,
69 | password: password,
70 | );
71 |
72 | // Link the pending credential with the existing account
73 | await userCredential.user.linkWithCredential(pendingCredential);
74 |
75 | // Success! Go back to your application flow
76 | return goToApplication();
77 | }
78 |
79 | // Since other providers are now external, you must now sign the user in with another
80 | // auth provider, such as Facebook.
81 | if (userSignInMethods.first == 'facebook.com') {
82 | // Create a new Facebook credential
83 | String accessToken = await triggerFacebookAuthentication();
84 | var facebookAuthCredential = FacebookAuthProvider.credential(accessToken);
85 |
86 | // Sign the user in with the credential
87 | UserCredential userCredential = await auth.signInWithCredential(facebookAuthCredential);
88 |
89 | // Link the pending credential with the existing account
90 | await userCredential.user.linkWithCredential(pendingCredential);
91 |
92 | // Success! Go back to your application flow
93 | return goToApplication();
94 | }
95 |
96 | // Handle other OAuth providers...
97 | }
98 | }
99 | ```
100 |
--------------------------------------------------------------------------------
/docs/flutter/auth/password-auth.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Authenticate with Firebase using Password-Based Accounts on Flutter
7 |
8 | You can use Firebase Authentication to let your users authenticate with
9 | Firebase using email addresses and passwords.
10 |
11 | ## Before you begin
12 |
13 | 1. If you haven't already, follow the steps in the [Get started](start) guide.
14 |
15 | 1. Enable Email/Password sign-in:
16 |
17 | - In the Firebase console's **Authentication** section, open the
18 | [Sign in method](https://console.firebase.google.com/project/_/authentication/providers)
19 | page.
20 | - From the **Sign in method** page, enable the **Email/password sign-in**
21 | method and click **Save**.
22 |
23 | ## Create a password-based account
24 |
25 | To create a new user account with a password, call the `createUserWithEmailAndPassword()`
26 | method:
27 |
28 | ```dart
29 | try {
30 | final credential = await FirebaseAuth.instance.createUserWithEmailAndPassword(
31 | email: emailAddress,
32 | password: password,
33 | );
34 | } on FirebaseAuthException catch (e) {
35 | if (e.code == 'weak-password') {
36 | print('The password provided is too weak.');
37 | } else if (e.code == 'email-already-in-use') {
38 | print('The account already exists for that email.');
39 | }
40 | } catch (e) {
41 | print(e);
42 | }
43 | ```
44 |
45 | Typically, you would do this from your app's sign-up screen. When a new user
46 | signs up using your app's sign-up form, complete any new account validation
47 | steps that your app requires, such as verifying that the new account's password
48 | was correctly typed and meets your complexity requirements.
49 |
50 | If the new account was created successfully, the user is also signed in. If you
51 | are listening to changes in [authentication state](start#auth-state), a new
52 | event will be sent to your listeners.
53 |
54 | As a follow-up to creating a new account, you can
55 | [Verify the user's email address](manage-users#verify-email).
56 |
57 | Note: To protect your project from abuse, Firebase limits the number of new
58 | email/password and anonymous sign-ups that your application can have from the
59 | same IP address in a short period of time. You can request and schedule
60 | temporary changes to this quota from the
61 | [Firebase console](https://console.firebase.google.com/project/_/authentication/providers).
62 |
63 | ## Sign in a user with an email address and password
64 |
65 | The steps for signing in a user with a password are similar to the steps for
66 | creating a new account. From your your app's sign-in screen, call
67 | `signInWithEmailAndPassword()`:
68 |
69 | ```dart
70 | try {
71 | final credential = await FirebaseAuth.instance.signInWithEmailAndPassword(
72 | email: emailAddress,
73 | password: password
74 | );
75 | } on FirebaseAuthException catch (e) {
76 | if (e.code == 'user-not-found') {
77 | print('No user found for that email.');
78 | } else if (e.code == 'wrong-password') {
79 | print('Wrong password provided for that user.');
80 | }
81 | }
82 | ```
83 |
84 | Caution: When a user uninstalls your app on iOS or macOS, the user's authentication
85 | state can persist between app re-installs, as the Firebase iOS SDK persists
86 | authentication state to the system keychain.
87 | See issue [#4661](https://github.com/firebase/flutterfire/issues/4661)
88 | for more information.
89 |
90 |
91 | ## Next steps
92 |
93 | After a user creates a new account, this account is stored as part of your
94 | Firebase project, and can be used to identify a user across every app in your
95 | project, regardless of what sign-in method the user used.
96 |
97 | In your apps, you can get the user's basic profile information from the
98 | `User` object. See [Manage Users](manage-users).
99 |
100 | In your Firebase Realtime Database and Cloud Storage Security Rules, you can
101 | get the signed-in user's unique user ID from the `auth` variable, and use it to
102 | control what data a user can access.
103 |
104 | You can allow users to sign in to your app using multiple authentication
105 | providers by [linking auth provider credentials](account-linking)) to an
106 | existing user account.
107 |
108 | To sign out a user, call `signOut()`:
109 |
110 | ```dart
111 | await FirebaseAuth.instance.signOut();
112 | ```
113 |
--------------------------------------------------------------------------------
/docs/flutter/cloud-messaging/first-message.md:
--------------------------------------------------------------------------------
1 | Project: /docs/cloud-messaging/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 | {% include "_shared/apis/console/_local_variables.html" %}
6 | {% include "_local_variables.html" %}
7 | {% include "docs/cloud-messaging/_local_variables.html" %}
8 | {% include "docs/android/_local_variables.html" %}
9 |
10 |
11 |
12 | # Send a test message to a backgrounded app
13 |
14 | To get started with FCM, build out the simplest use case: sending a
15 | test notification message from the
16 |
17 | Notifications composer to a development device
18 | when the app is in the background on the device.
19 | This page lists all the steps to achieve this, from setup to verification
20 | — it may cover steps you already completed if you
21 | have [set up a Flutter app](/docs/cloud-messaging/flutter/client)
22 | for FCM.
23 |
24 | Important: This guide focuses on the background case. If you want to receive
25 | messages when your app is in the foreground as well, see also
26 | [Receive Messages in a Flutter App](/docs/cloud-messaging/flutter/receive).
27 |
28 |
29 | ## Install the FCM plugin
30 |
31 | 1. [Install and initialize the Firebase SDKs for Flutter](/docs/flutter/setup)
32 | if you haven't already done so.
33 |
34 | 1. From the root of your Flutter project, run the following command to install
35 | the plugin:
36 |
37 | ```bash
38 | flutter pub add firebase_messaging
39 | ```
40 |
41 | 1. Once complete, rebuild your Flutter application:
42 |
43 | ```bash
44 | flutter run
45 | ```
46 |
47 |
48 | ## Access the registration token
49 |
50 | To send a message to a specific device, you need to know that device's
51 | registration token. Because you'll need to enter the token in a field in the
52 | Notifications console to complete this tutorial, make sure to copy the token
53 | or securely store it after you retrieve it.
54 |
55 | To retrieve the current registration token for an app instance, call
56 | `getToken()`. If notification permission has not been granted, this method will
57 | ask the user for notification permissions. Otherwise, it returns a token or
58 | rejects the future due to an error.
59 |
60 | ```dart
61 | final fcmToken = await FirebaseMessaging.instance.getToken();
62 | ```
63 |
64 |
65 | ## Send a test notification message
66 |
67 | {# Google-internal include #}
68 | <<../_send-to-device.md>>
69 |
70 | For insight into message delivery to your app, see the
71 | FCM reporting dashboard,
72 | which records the number of messages sent and opened on Apple and Android
73 | devices, along with data for "impressions" (notifications seen by users) for
74 | Android apps.
75 |
76 | ## Handling interaction
77 |
78 | When users tap a notification, the default behavior on both Android & iOS is to open the application. If the application is terminated,
79 | it will be started, and if it is in the background, it will be brought to the foreground.
80 |
81 | Depending on the content of a notification, you may want to handle the user's interaction when the application
82 | opens. For example, if a new chat message is sent using a notification and the user selects it, you may want to
83 | open the specific conversation when the application opens.
84 |
85 | The `firebase-messaging` package provides two ways to handle this interaction:
86 |
87 | 1. `getInitialMessage()`: If the application is opened from a terminated state, this method returns a `Future` containing a `RemoteMessage`. Once consumed, the `RemoteMessage` will be removed.
88 | 2. `onMessageOpenedApp`: A `Stream` which posts a `RemoteMessage` when the application is opened from a
89 | background state.
90 |
91 | To ensure a smooth experience for your users, you should handle both scenarios. The code example
92 | below outlines how this can be achieved:
93 |
94 | ```dart
95 | class Application extends StatefulWidget {
96 | @override
97 | State createState() => _Application();
98 | }
99 |
100 | class _Application extends State {
101 | // In this example, suppose that all messages contain a data field with the key 'type'.
102 | Future setupInteractedMessage() async {
103 | // Get any messages which caused the application to open from
104 | // a terminated state.
105 | RemoteMessage? initialMessage =
106 | await FirebaseMessaging.instance.getInitialMessage();
107 |
108 | // If the message also contains a data property with a "type" of "chat",
109 | // navigate to a chat screen
110 | if (initialMessage != null) {
111 | _handleMessage(initialMessage);
112 | }
113 |
114 | // Also handle any interaction when the app is in the background via a
115 | // Stream listener
116 | FirebaseMessaging.onMessageOpenedApp.listen(_handleMessage);
117 | }
118 |
119 | void _handleMessage(RemoteMessage message) {
120 | if (message.data['type'] == 'chat') {
121 | Navigator.pushNamed(context, '/chat',
122 | arguments: ChatArguments(message),
123 | );
124 | }
125 | }
126 |
127 | @override
128 | void initState() {
129 | super.initState();
130 |
131 | // Run code required to handle interacted messages in an async function
132 | // as initState() must not be async
133 | setupInteractedMessage();
134 | }
135 |
136 | @override
137 | Widget build(BuildContext context) {
138 | return Text("...");
139 | }
140 | }
141 | ```
142 |
143 | How you handle interaction depends on your application setup. The example above
144 | shows a basic example of using a `StatefulWidget`.
145 |
146 | ## Next steps
147 |
148 | ### Send messages to foregrounded apps
149 |
150 | Once you have successfully sent notification messages while your app is in
151 | the background, see
152 | [Receive Messages in a Flutter App](/docs/cloud-messaging/flutter/receive)
153 | to get started sending to foregrounded apps.
154 |
155 | ### Go beyond notification messages
156 |
157 | To add other, more advanced behavior to your app, you'll need a
158 | [server implementation](/docs/cloud-messaging/server).
159 |
160 | Then, in your app client:
161 |
162 | - [Receive messages](/docs/cloud-messaging/flutter/receive)
163 | - [Subscribe to message topics](/docs/cloud-messaging/flutter/topic-messaging)
164 |
165 |
--------------------------------------------------------------------------------
/docs/flutter/cloud-messaging/topic-messaging.md:
--------------------------------------------------------------------------------
1 | Project: /docs/cloud-messaging/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 | {% include "_shared/apis/console/_local_variables.html" %}
6 | {% include "_local_variables.html" %}
7 | {% include "docs/cloud-messaging/_local_variables.html" %}
8 | {% include "docs/android/_local_variables.html" %}
9 |
10 |
11 |
12 | # Topic messaging on Flutter
13 |
14 | Based on the publish/subscribe model, FCM topic messaging allows you to send a message
15 | to multiple devices that have opted in to a particular topic. You compose topic messages as
16 | needed, and FCM handles routing and delivering the message reliably to the right
17 | devices.
18 |
19 | For example, users of a local tide
20 | forecasting app could opt in to a "tidal currents alerts" topic and receive
21 | notifications of optimal saltwater fishing conditions in specified areas. Users of a sports app
22 | could subscribe to automatic updates in live game scores for their favorite
23 | teams.
24 |
25 | Some things to keep in mind about topics:
26 |
27 | - Topic messaging is best suited for content such as weather, or other publicly
28 | available information.
29 |
30 | - Topic messages are **optimized for throughput rather than latency**. For fast,
31 | secure delivery to single devices or small groups of devices,
32 | [target messages to registration tokens](/docs/cloud-messaging/send-message#send_messages_to_specific_devices),
33 | not topics.
34 |
35 | - If you need to send messages to multiple devices _per user_, consider
36 | [device group messaging](/docs/cloud-messaging/send-message#send_messages_to_device_groups)
37 | for those use cases.
38 |
39 | - Topic messaging supports unlimited subscriptions for each topic. However, FCM
40 | enforces limits in these areas:
41 |
42 | - One app instance can be subscribed to no more than 2000 topics.
43 | - If you are using [batch import](https://developers.google.com/instance-id/reference/server#manage_relationship_maps_for_multiple_app_instances)
44 | to subscribe app instances, each request is limited to 1000 app instances.
45 | - The frequency of new subscriptions is rate-limited per project. If you send
46 | too many subscription requests in a short period of time, FCM servers will
47 | respond with a `429 RESOURCE_EXHAUSTED` ("quota exceeded") response. Retry
48 | with exponential backoff.
49 |
50 |
51 | ## Subscribe the client app to a topic
52 |
53 | Client apps can subscribe to any existing topic, or they can create a new
54 | topic. When a client app subscribes to a new topic name (one that does
55 | not already exist for your Firebase project), a new topic of that name is
56 | created in FCM and any client can subsequently subscribe to it.
57 |
58 | To subscribe to a topic, call `subscribeToTopic()` with the topic name. This method
59 | returns a `Future`, which resolves when the subscription succeeded:
60 |
61 | ```dart
62 | await FirebaseMessaging.instance.subscribeToTopic("topic");
63 | ```
64 |
65 | To unsubscribe, call `unsubscribeFromTopic()` with the topic name.
66 |
67 | `subscribeToTopic()` and `unsubscribeFromTopic()` are not supported for web
68 | clients. To learn how to manage subscriptions for web users, see
69 | [Send messages to topics on Web/JavaScript](https://firebase.google.com/docs/cloud-messaging/js/topic-messaging).
70 |
71 | ## Next steps
72 |
73 | * Learn how to [send topic messages](/docs/cloud-messaging/send-message#send-messages-to-topics).
74 | * Learn how to [Manage topic subscriptions on the server](/docs/cloud-messaging/manage-topics).
--------------------------------------------------------------------------------
/docs/flutter/crashlytics/_force-test-crash.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/crashlytics/test-implementation?platform=flutter #}
3 |
4 | 1. Add code to your app that you can use to force a test exception to be
5 | thrown.
6 |
7 | If you’ve added an error handler that calls
8 | `FirebaseCrashlytics.instance.recordError(error, stack, fatal: true)` to the
9 | top-level `Zone`, you can use the following code to add a button to your app
10 | that, when pressed, throws a test exception:
11 |
12 | ```dart
13 | TextButton(
14 | onPressed: () => throw Exception(),
15 | child: const Text("Throw Test Exception"),
16 | ),
17 | ```
18 |
19 | 1. Build and run your app.
20 |
21 | 1. Force the test exception to be thrown in order to send your app's first
22 | report:
23 |
24 | 1. Open your app from your test device or emulator.
25 |
26 | 1. In your app, press the test exception button that you added using the
27 | code above.
28 |
29 | 1. Go to the
30 | [{{crashlytics}} dashboard](https://console.firebase.google.com/project/_/crashlytics){: .external}
31 | of the {{name_appmanager}} to see your test crash.
32 |
--------------------------------------------------------------------------------
/docs/flutter/crashlytics/_start-using-analytics.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/crashlytics/start-using-analytics?platform=flutter #}
3 |
4 | 1. Make sure that {{firebase_analytics}} is enabled in your Firebase project:
5 | Go to settings > _Project settings_ > _Integrations_ tab,
6 | then follow the on-screen instructions for {{firebase_analytics}}.
7 |
8 | 1. From the root of your Flutter project, run the following command to install
9 | the {{analytics}} Flutter plugin:
10 |
11 |
flutter pub add firebase_analytics
13 |
14 |
15 | 1. Make sure that your Flutter app's Firebase configuration is up-to-date by
16 | running the following command from the root directory of your Flutter
17 | project:
18 |
19 |
flutterfire configure
21 |
22 |
23 | 1. Once complete, rebuild your Flutter application:
24 |
25 |
flutter run
27 |
28 |
29 | Your Flutter project is now set up to use {{firebase_analytics}}.
30 |
--------------------------------------------------------------------------------
/docs/flutter/database/_usecase_security_preamble.md:
--------------------------------------------------------------------------------
1 | Note: By default, read and write access to your database is restricted so only
2 | authenticated users can read or write data. To get started without setting up
3 | Firebase Authentication, you can [configure your rules for public access](/docs/rules/basics#default_rules_locked_mode).
4 | This does make your database open to anyone, even people not using your app, so
5 | be sure to restrict your database again when you set up authentication.
6 |
--------------------------------------------------------------------------------
/docs/flutter/database/start.md:
--------------------------------------------------------------------------------
1 | Project: /docs/database/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Get Started with Realtime Database
8 |
9 | ## Prerequisites
10 |
11 | 1. [Install `firebase_core`](/docs/flutter/setup) and add the initialization code
12 | to your app if you haven't already.
13 | 1. Add your app to your Firebase project in the Firebase console.
14 |
15 | ## Create a Database
16 |
17 | {# TODO(markarndt): Decide whether to include common files instead. #}
18 |
19 | 1. Navigate to the **Realtime Database** section of the Firebase console.
20 | You'll be prompted to select an existing Firebase project.
21 | Follow the database creation workflow.
22 |
23 | 1. Select a starting mode for your security rules:
24 |
25 | **Test mode**
26 |
27 | Good for getting started with the mobile and web client libraries,
28 | but allows anyone to read and overwrite your data. After testing, **make
29 | sure to review the [Understand Firebase Realtime Database Rules](/docs/database/security/)
30 | section.**
31 |
32 | Note: If you create a database in Test mode and make no changes to the
33 | default world-readable and world-writeable security rules within a trial
34 | period, you will be alerted by email, then your database rules will
35 | deny all requests. Note the expiration date during the Firebase console
36 | setup flow.
37 |
38 |
39 | To get started, select testmode.
40 |
41 | **Locked mode**
42 |
43 | Denies all reads and writes from mobile and web clients.
44 | Your authenticated application servers can still access your database.
45 |
46 | 1. Choose a region for the database. Depending on your choice of region,
47 | the database namespace will be of the form `.firebaseio.com` or
48 | `..firebasedatabase.app`. For more information, see
49 | [select locations for your project](/docs/projects/locations.md##rtdb-locations).
50 |
51 | 1. Click **Done**.
52 |
53 | When you enable Realtime Database, it also enables the API in the
54 | [Cloud API Manager](https://console.cloud.google.com/projectselector/apis/api/firebasedatabase.googleapis.com/overview).
55 |
56 | ## Add Firebase Realtime Database to your app
57 |
58 | 1. From the root of your Flutter project, run the following command to install the plugin:
59 |
60 | ```bash
61 | flutter pub add firebase_database
62 | ```
63 | 1. Once complete, rebuild your Flutter application:
64 |
65 | ```bash
66 | flutter run
67 | ```
68 |
69 | ## Configure database rules
70 |
71 | The Realtime Database provides a declarative rules language that allows you to
72 | define how your data should be structured, how it should be indexed, and when
73 | your data can be read from and written to.
74 |
75 | <<_usecase_security_preamble.md>>
76 |
77 | ## Initialize the Firebase Realtime Database package
78 |
79 | To start using the Realtime Database package within your project, import it at
80 | the top of your project files:
81 |
82 | ```dart
83 | import 'package:firebase_database/firebase_database.dart';
84 | ```
85 |
86 | To use the default Database instance, call the `instance`
87 | getter on `FirebaseDatabase`:
88 |
89 | ```dart
90 | FirebaseDatabase database = FirebaseDatabase.instance;
91 | ```
92 |
93 | If you'd like to use it with a secondary Firebase App, use the static `instanceFor` method:
94 |
95 | ```dart
96 | FirebaseApp secondaryApp = Firebase.app('SecondaryApp');
97 | FirebaseDatabase database = FirebaseDatabase.instanceFor(app: secondaryApp);
98 | ```
99 |
100 | If you'd like to use a different RTDB instance on the same project, you can pass in a `databaseUrl` using
101 | the static `instanceFor` method:
102 |
103 | ```dart
104 | final firebaseApp = Firebase.app();
105 | final rtdb = FirebaseDatabase.instanceFor(app: firebaseApp, databaseURL: 'https://your-realtime-database-url.firebaseio.com/');
106 | ```
107 |
108 | ## Next Steps
109 |
110 | * Learn how to [structure data](structure-data) for Realtime Database.
111 |
112 | * [Scale your data across multiple database instances.](/docs/database/usage/sharding)
113 |
114 | * [Read and write data.](read-and-write)
115 |
116 | * [View your database in the
117 | Firebase console.](//console.firebase.google.com/project/_/database/data)
118 |
--------------------------------------------------------------------------------
/docs/flutter/database/structure-data.md:
--------------------------------------------------------------------------------
1 | Project: /docs/database/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Structure Your Database
8 |
9 | This guide covers some of the key concepts in data architecture and best
10 | practices for structuring the JSON data in your Firebase Realtime Database.
11 |
12 | Building a properly structured database requires quite a bit of forethought.
13 | Most importantly, you need to plan for how data is going to be saved and
14 | later retrieved to make that process as easy as possible.
15 |
16 | ## How data is structured: it's a JSON tree
17 |
18 | All Firebase Realtime Database data is stored as JSON objects. You can think of
19 | the database as a cloud-hosted JSON tree. Unlike a SQL database, there are no
20 | tables or records. When you add data to the JSON tree, it becomes a node in the
21 | existing JSON structure with an associated key. You can provide your own keys,
22 | such as user IDs or semantic names, or they can be provided for you using
23 | `push()`.
24 |
25 | If you create your own keys, they must be UTF-8 encoded, can be a maximum
26 | of 768 bytes, and cannot contain `.`, `$`, `#`, `[`, `]`, `/`, or ASCII control
27 | characters 0-31 or 127. You cannot use ASCII control characters in the values
28 | themselves, either.
29 | {: .note }
30 |
31 | For example, consider a chat application that allows users to store a basic
32 | profile and contact list. A typical user profile is located at a path, such as
33 | `/users/$uid`. The user `alovelace` might have a database entry that
34 | looks something like this:
35 |
36 | ```
37 | {
38 | "users": {
39 | "alovelace": {
40 | "name": "Ada Lovelace",
41 | "contacts": { "ghopper": true },
42 | },
43 | "ghopper": { ... },
44 | "eclarke": { ... }
45 | }
46 | }
47 | ```
48 |
49 | Although the database uses a JSON tree, data stored in the database can be
50 | represented as certain native types that correspond to available JSON types
51 | to help you write more maintainable code.
52 |
53 | ## Best practices for data structure
54 |
55 | ### Avoid nesting data
56 |
57 | Because the Firebase Realtime Database allows nesting data up to 32 levels deep,
58 | you might be tempted to think that this should be the default structure.
59 | However, when you fetch data at a location in your database, you also retrieve
60 | all of its child nodes. In addition, when you grant someone read or write access
61 | at a node in your database, you also grant them access to all data under that
62 | node. Therefore, in practice, it's best to keep your data structure as flat
63 | as possible.
64 |
65 | For an example of why nested data is bad, consider the following
66 | multiply-nested structure:
67 |
68 | ```
69 | {
70 | // This is a poorly nested data architecture, because iterating the children
71 | // of the "chats" node to get a list of conversation titles requires
72 | // potentially downloading hundreds of megabytes of messages
73 | "chats": {
74 | "one": {
75 | "title": "Historical Tech Pioneers",
76 | "messages": {
77 | "m1": { "sender": "ghopper", "message": "Relay malfunction found. Cause: moth." },
78 | "m2": { ... },
79 | // a very long list of messages
80 | }
81 | },
82 | "two": { ... }
83 | }
84 | }
85 | ```
86 |
87 | With this nested design, iterating through the data becomes problematic. For
88 | example, listing the titles of chat conversations requires the entire `chats`
89 | tree, including all members and messages, to be downloaded to the client.
90 |
91 |
92 | ### Flatten data structures
93 |
94 | If the data is instead split into separate paths, also called denormalization,
95 | it can be efficiently downloaded in separate calls, as it is needed. Consider
96 | this flattened structure:
97 |
98 | ```
99 | {
100 | // Chats contains only meta info about each conversation
101 | // stored under the chats's unique ID
102 | "chats": {
103 | "one": {
104 | "title": "Historical Tech Pioneers",
105 | "lastMessage": "ghopper: Relay malfunction found. Cause: moth.",
106 | "timestamp": 1459361875666
107 | },
108 | "two": { ... },
109 | "three": { ... }
110 | },
111 |
112 | // Conversation members are easily accessible
113 | // and stored by chat conversation ID
114 | "members": {
115 | // we'll talk about indices like this below
116 | "one": {
117 | "ghopper": true,
118 | "alovelace": true,
119 | "eclarke": true
120 | },
121 | "two": { ... },
122 | "three": { ... }
123 | },
124 |
125 | // Messages are separate from data we may want to iterate quickly
126 | // but still easily paginated and queried, and organized by chat
127 | // conversation ID
128 | "messages": {
129 | "one": {
130 | "m1": {
131 | "name": "eclarke",
132 | "message": "The relay seems to be malfunctioning.",
133 | "timestamp": 1459361875337
134 | },
135 | "m2": { ... },
136 | "m3": { ... }
137 | },
138 | "two": { ... },
139 | "three": { ... }
140 | }
141 | }
142 | ```
143 |
144 | It's now possible to iterate through the list of rooms by downloading only a
145 | few bytes per conversation, quickly fetching metadata for listing or displaying
146 | rooms in a UI. Messages can be fetched separately and displayed as they arrive,
147 | allowing the UI to stay responsive and fast.
148 |
149 |
150 | ### Create data that scales {:#fanout}
151 |
152 |
153 | When building apps, it's often better to download a subset of a list.
154 | This is particularly common if the list contains thousands of records.
155 | When this relationship is static and one-directional, you can simply nest the
156 | child objects under the parent.
157 |
158 | Sometimes, this relationship is more dynamic, or it may be necessary to
159 | denormalize this data. Many times you can denormalize the data by using a query
160 | to retrieve a subset of the data, as discussed in
161 | [Sorting and filtering data](lists-of-data#sorting_and_filtering_data).
162 |
163 | But even this may be insufficient. Consider, for example, a two-way relationship
164 | between users and groups. Users can belong to a group, and groups comprise a
165 | list of users. When it comes time to decide which groups a user belongs to,
166 | things get complicated.
167 |
168 | What's needed is an elegant way to list the groups a user belongs to and
169 | fetch only data for those groups. An *index* of groups can help a
170 | great deal here:
171 |
172 | ```
173 | // An index to track Ada's memberships
174 | {
175 | "users": {
176 | "alovelace": {
177 | "name": "Ada Lovelace",
178 | // Index Ada's groups in her profile
179 | "groups": {
180 | // the value here doesn't matter, just that the key exists
181 | "techpioneers": true,
182 | "womentechmakers": true
183 | }
184 | },
185 | ...
186 | },
187 | "groups": {
188 | "techpioneers": {
189 | "name": "Historical Tech Pioneers",
190 | "members": {
191 | "alovelace": true,
192 | "ghopper": true,
193 | "eclarke": true
194 | }
195 | },
196 | ...
197 | }
198 | }
199 | ```
200 |
201 | You might notice that this duplicates some data by storing the relationship
202 | under both Ada's record and under the group. Now `alovelace` is indexed under a
203 | group, and `techpioneers` is listed in Ada's profile. So to delete Ada
204 | from the group, it has to be updated in two places.
205 |
206 | This is a necessary redundancy for two-way relationships. It allows you to
207 | quickly and efficiently fetch Ada's memberships, even when the list of users or
208 | groups scales into the millions or when Realtime Database security rules
209 | prevent access to some of the records.
210 |
211 | This approach, inverting the data by listing the IDs as keys and setting the
212 | value to true, makes checking for a key as simple as reading
213 | `/users/$uid/groups/$group_id` and checking if it is `null`. The index is faster
214 | and a good deal more efficient than querying or scanning the data.
215 |
216 | ## Next Steps
217 |
218 | * [Read and Write Data to Realtime Database](read-and-write)
219 |
--------------------------------------------------------------------------------
/docs/flutter/in-app-messaging/_customize-messages.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/in-app-messaging/customize-messaging?platform=flutter #}
3 |
4 | Firebase In-App Messaging provides a useful set of preconfigured behaviors and
5 | message types with a default look and feel, but in some cases you may want to
6 | extend behaviors and message content. In-App Messaging allows you to add actions
7 | to messages and customize message look and feel.
8 |
9 | ## Add an action to your message
10 |
11 | With actions you can use your in-app messages to direct users to a
12 | website or a specific screen in your app.
13 |
14 | ### Implement a deep link handler
15 |
16 | Firebase In-App Messaging uses link handlers to process actions. The SDK is
17 | able to use a number of handlers, so if your app already has one, Firebase
18 | In-App Messaging can use that without any further setup. If you don't yet have
19 | a handler, you can use [Firebase Dynamic Links](/docs/dynamic-links).
20 |
21 | ### Add the action to your message using the Firebase console
22 |
23 | Once your app has a link handler, you're ready to compose a campaign with
24 | an action. Open the Firebase console to
25 | [In-App Messaging](https://console.firebase.google.com/project/_/inappmessaging),
26 | and start a new campaign or edit an existing campaign. In that campaign, provide
27 | a **Card**, **Button text** and **Button action**, an **Image action**, or a **Banner
28 | action**, where the action is a relevant deep link.
29 |
30 | The action's format depends on which message layout you choose. Modals get
31 | action buttons with customizable button text content, text color, and background
32 | color. Images and top banners, on the other hand, become interactive and invoke
33 | the specified action when tapped.
34 |
--------------------------------------------------------------------------------
/docs/flutter/in-app-messaging/_get-started.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/in-app-messaging/get-started?platform=flutter #}
3 |
4 | ## Before you begin
5 |
6 | [Install and initialize the Firebase SDKs for Flutter](/docs/flutter/setup) if you
7 | haven't already done so.
8 |
9 | ## Add the Firebase In-App Messaging SDK to your project
10 |
11 | 1. From the root directory of your Flutter project, run the following
12 | command to install the Firebase In-App Messaging plugin:
13 |
14 | ```bash
15 | flutter pub add firebase_in_app_messaging
16 | ```
17 |
18 | 1. Rebuild your project:
19 |
20 | ```bash
21 | flutter run
22 | ```
23 |
24 | 1. Import the Firebase In-App Messaging plugin:
25 |
26 | ```dart
27 | import 'package:firebase_in_app_messaging/firebase_in_app_messaging.dart';
28 | ```
29 |
30 | ## Send a test message
31 |
32 | ### Get your app's installation ID
33 |
34 | To conserve power, Firebase In-App Messaging only retrieves messages from the
35 | server once per day. That can make testing difficult, so the
36 | Firebase console allows you to specify a test device that displays messages
37 | on demand.
38 |
39 | That testing device is determined by a FID.
40 | Find your testing app's FID by checking the console
41 | output when you run your app.
42 |
43 | On Android, the message looks like the following:
44 |
45 | ```
46 | I/FIAM.Headless: Starting InAppMessaging runtime with Installation ID YOUR_INSTALLATION_ID
47 | ```
48 |
49 | On iOS, run the app with the runtime command argument `-FIRDebugEnabled`:
50 |
51 | 1. With your Xcode project open, select **Product > Scheme > Edit scheme...** from
52 | the top menu bar.
53 | 1. Open the **Arguments** tab of the dialog that pops up.
54 | 1. Click **+ Add items** under **Arguments Passed On Launch**.
55 | 1. Enter "-FIRDebugEnabled" in the newly-created field.
56 | 1. Click **Close**, then run your app.
57 |
58 | Once your app starts running, look for the following line in the Xcode console's logs:
59 |
60 | ```
61 | [Firebase/InAppMessaging][I-IAM180017] Starting InAppMessaging runtime with Firebase Installation ID YOUR_INSTALLATION_ID
62 | ```
63 |
64 |
65 | ### Send a message to your testing device
66 |
67 | Once you've launched your app on the testing device and you have its
68 | Firebase installation ID (FID), you can try out your Firebase In-App Messaging
69 | setup by sending a test message:
70 |
71 | 1. In the {{name_appmanager}}, open [Messaging](https://console.firebase.google.com/project/_/messaging/).
72 | 1. If this is your first campaign, click **Create your first campaign**.
73 | 1. Select **Firebase In-App messages** and click **Create**.
74 | 1. Otherwise, on the **Campaigns** tab, click **New campaign**.
75 | 1. Select **In-App Messaging**.
76 | 1. Enter a **Title** for your first message.
77 | 1. Click **Test on your Device**
78 | 1. Enter your app's Firebase installation ID in the
79 | **Add an installation ID** field.
80 | 1. Click **Test** to send the message.
81 |
82 | Firebase In-App Messaging sends your test message as soon as you click **Test**. To see the
83 | message, you need to close, then reopen the app on your testing device.
84 |
85 | To confirm whether your device is a test device, look for one of the following
86 | log messages.
87 |
88 | **Android**
89 |
90 | ```
91 | I/FIAM.Headless: Setting this device as a test device
92 | ```
93 |
94 | **iOS**
95 |
96 | ```
97 | [Firebase/InAppMessaging][I-IAM180017] Seeing test message in fetch response. Turn the current instance into a testing instance.
98 | ```
99 |
--------------------------------------------------------------------------------
/docs/flutter/in-app-messaging/_modify-message-behavior.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/in-app-messaging/modify-message-behavior?platform=flutter #}
3 |
4 | With little to no coding effort, Firebase In-App Messaging allows you to create,
5 | configure and target rich user interactions, leveraging
6 | the capabilities of Google Analytics out of the box
7 | to tie messaging events to actual user characteristics, activities, and choices.
8 | With some additional Firebase In-App Messaging SDK integration, you can tailor
9 | the behavior of in-app messages even further, responding when users interact
10 | with messages, triggering message events outside the Analytics
11 | framework, and allowing users to control sharing of their personal data related
12 | to messaging interactions.
13 |
14 | ## Respond when users interact with in-app messages
15 |
16 | With actions you can use your in-app messages to direct users to a
17 | website or a specific screen in your app.
18 |
19 | Your code can respond to basic interactions (clicks and dismissals), to
20 | impressions (verified views of your messages), and to display errors logged and
21 | confirmed by the SDK. For example, when your message is composed as a Card
22 | modal, you might want to track and follow-up on which of two URLs the user
23 | clicked on the Card.
24 |
25 | To do so, you will have to use the platform-native APIs.
26 | See the documentation for [iOS](/docs/in-app-messaging/modify-message-behavior?platform=ios#respond_when_users_interact_with_in-app_messages)
27 | and [Android](/docs/in-app-messaging/modify-message-behavior?platform=android#respond_when_users_interact_with_in-app_messages).
28 |
29 | ## Trigger in-app messages programmatically
30 |
31 | Firebase In-App Messaging by default allows you to trigger in-app messages with
32 | Google Analytics for Firebase events, with no additional integration. You can
33 | also manually trigger events programmatically with the Firebase In-App Messaging SDK's
34 | programmatic triggers.
35 |
36 | In the In-App Messaging campaign composer, create a new campaign or select an
37 | existing campaign, and in the Scheduling step of the composer workflow, note the
38 | event ID of a newly-created or existing messaging event. Once noted, instrument
39 | your app to trigger the event by its ID.
40 |
41 | ```dart
42 | FirebaseInAppMessaging.instance.triggerEvent("eventName");
43 | ```
44 |
45 | ## Use campaign custom metadata
46 |
47 | In your campaigns, you can specify custom data in a series of key/value pairs.
48 | When users interact with messages, this data is available for you to, for example,
49 | display a promo code.
50 |
51 | To do so, you will have to use the platform-native APIs.
52 | See the documentation for [iOS](/docs/in-app-messaging/modify-message-behavior?platform=ios#use_campaign_custom_metadata)
53 | and [Android](/docs/in-app-messaging/modify-message-behavior?platform=android#use_campaign_custom_metadata).
54 |
55 |
56 | ## Temporarily disable in-app messages
57 |
58 | By default, Firebase In-App Messaging renders messages whenever a triggering
59 | condition is satisfied, regardless of an app's current state. If you'd like to
60 | suppress message displays for any reason, for example to avoid interrupting a
61 | sequence of payment processing screens, you can do that with the SDK's
62 | `setMessagesSuppressed()` method:
63 |
64 | ```dart
65 | FirebaseInAppMessaging.instance.setMessagesSuppressed(true);
66 | ```
67 |
68 | Passing `true` to the method prevents Firebase In-App Messaging from displaying
69 | messages, while `false` reenables message display. The SDK turns off message
70 | suppression on app restart. Suppressed messages are ignored by the SDK. Their
71 | trigger conditions must be met again while suppression is off before Firebase
72 | In-App Messaging can display them.
73 |
74 | ## Enable opt-out message delivery
75 |
76 | By default, Firebase In-App Messaging automatically delivers messages to all app users you target
77 | in messaging campaigns. To deliver those messages, the Firebase In-App Messaging SDK uses
78 | installation IDs to identify each user's app. This means
79 | that In-App Messaging has to send client data, linked to the
80 | installation ID, to Firebase servers. If you'd like to give users
81 | more control over the data they send, disable automatic data collection and give
82 | them a chance to approve data sharing.
83 |
84 | To do that, you have to disable automatic initialization for Firebase In-App Messaging, and
85 | initialize the service manually for opt-in users:
86 |
87 | 1. Turn off automatic initialization.
88 |
89 | **Apple platforms**: Add a new key to your `Info.plist` file:
90 |
91 | - Key: `FirebaseInAppMessagingAutomaticDataCollectionEnabled`
92 | - Value: `NO`
93 |
94 | **Android**: Add a `meta-data` tag to your `AndroidManifest.xml` file:
95 |
96 | ```xml
97 |
100 | ```
101 |
102 | 1. Initialize Firebase In-App Messaging for selected users manually:
103 |
104 | ```dart
105 | FirebaseInAppMessaging.instance.setAutomaticDataCollectionEnabled(true);
106 | ```
107 |
108 | Once you set a data collection preference manually, the value persists
109 | through app restarts, overriding the value in your `Info.plist` or
110 | `AndroidManifest.xml`. If you'd like to disable initialization again, for
111 | example if a user opts out of collection later, pass `false` to the
112 | `setAutomaticDataCollectionEnabled()` method.
113 |
--------------------------------------------------------------------------------
/docs/flutter/ml/use-custom-models.md:
--------------------------------------------------------------------------------
1 | Project: /docs/_project.yaml
2 | Book: /docs/_book.yaml
3 |
4 |
5 |
6 | # Use a custom TensorFlow Lite model with Flutter
7 |
8 | If your app uses custom
9 | [TensorFlow Lite](https://www.tensorflow.org/lite/){:.external} models, you can
10 | use Firebase ML to deploy your models. By deploying models with Firebase, you
11 | can reduce the initial download size of your app and update your app's ML models
12 | without releasing a new version of your app. And, with Remote Config and A/B
13 | Testing, you can dynamically serve different models to different sets of users.
14 |
15 | ## TensorFlow Lite models
16 |
17 | TensorFlow Lite models are ML models that are optimized to run on mobile
18 | devices. To get a TensorFlow Lite model:
19 |
20 | - Use a pre-built model, such as one of the [official TensorFlow Lite models](https://www.tensorflow.org/lite/models){:.external}
21 | - [Convert a TensorFlow model, Keras model, or concrete function to TensorFlow Lite.](https://www.tensorflow.org/lite/convert){:.external}
22 |
23 | Note that in the absence of a maintained TensorFlow Lite library for Dart, you
24 | will need to integrate with the native TensorFlow Lite library for your
25 | platforms. This integration is not documented here.
26 |
27 | ## Before you begin
28 |
29 | 1. [Install and initialize the Firebase SDKs for Flutter](/docs/flutter/setup)
30 | if you haven't already done so.
31 |
32 | 1. From the root directory of your Flutter project, run the following
33 | command to install the ML model downloader plugin:
34 |
35 | ```bash
36 | flutter pub add firebase_ml_model_downloader
37 | ```
38 |
39 | 1. Rebuild your project:
40 |
41 | ```bash
42 | flutter run
43 | ```
44 |
45 | ## 1. Deploy your model {:#deploy}
46 |
47 | Deploy your custom TensorFlow models using either the Firebase console or
48 | the Firebase Admin Python and Node.js SDKs. See
49 | [Deploy and manage custom models](/docs/ml/manage-hosted-models).
50 |
51 | After you add a custom model to your Firebase project, you can reference the
52 | model in your apps using the name you specified. At any time, you can deploy a
53 | new TensorFlow Lite model and download the new model onto users' devices by
54 | calling `getModel()` (see below).
55 |
56 | ## 2. Download the model to the device and initialize a TensorFlow Lite interpreter
57 |
58 | To use your TensorFlow Lite model in your app, first use the model downloader
59 | to download the latest version of the model to the device. Then, instantiate a
60 | TensorFlow Lite interpreter with the model.
61 |
62 | To start the model download, call the model downloader's `getModel()` method,
63 | specifying the name you assigned the model when you uploaded it, whether you
64 | want to always download the latest model, and the conditions under which you
65 | want to allow downloading.
66 |
67 | You can choose from three download behaviors:
68 |
69 | | Download type | Description
70 | |----------------------------------|--------------------------------------------
71 | | `localModel` | Get the local model from the device.
72 | : : If there is no local model available, this
73 | : : behaves like `latestModel`. Use this
74 | : : download type if you are not interested in
75 | : : checking for model updates. For example,
76 | : : you're using Remote Config to retrieve
77 | : : model names and you always upload models
78 | : : under new names (recommended).
79 | | `localModelUpdateInBackground` | Get the local model from the device and
80 | : : start updating the model in the background.
81 | : : If there is no local model available, this
82 | : : behaves like `latestModel`.
83 | | `latestModel` | Get the latest model. If the local model is
84 | : : the latest version, returns the local
85 | : : model. Otherwise, download the latest
86 | : : model. This behavior will block until the
87 | : : latest version is downloaded (not
88 | : : recommended). Use this behavior only in
89 | : : cases where you explicitly need the latest
90 | : : version.
91 |
92 | You should disable model-related functionality—for example, grey-out or
93 | hide part of your UI—until you confirm the model has been downloaded.
94 |
95 | ```dart
96 | FirebaseModelDownloader.instance
97 | .getModel(
98 | "yourModelName",
99 | FirebaseModelDownloadType.localModel,
100 | FirebaseModelDownloadConditions(
101 | iosAllowsCellularAccess: true,
102 | iosAllowsBackgroundDownloading: false,
103 | androidChargingRequired: false,
104 | androidWifiRequired: false,
105 | androidDeviceIdleRequired: false,
106 | )
107 | )
108 | .then((customModel) {
109 | // Download complete. Depending on your app, you could enable the ML
110 | // feature, or switch from the local model to the remote model, etc.
111 |
112 | // The CustomModel object contains the local path of the model file,
113 | // which you can use to instantiate a TensorFlow Lite interpreter.
114 | final localModelPath = customModel.file;
115 |
116 | // ...
117 | });
118 | ```
119 |
120 | Many apps start the download task in their initialization code, but you can do
121 | so at any point before you need to use the model.
122 |
123 |
124 | ## 3. Perform inference on input data
125 |
126 | Now that you have your model file on the device you can use it with the
127 | TensorFlow Lite interpreter to perform inference. In the absence of a maintained
128 | TensorFlow Lite library for Dart, you will need to integrate with the
129 | [native TensorFlow Lite libraries](https://www.tensorflow.org/lite){:.external}
130 | for iOS and Android.
131 |
132 |
133 | ## Appendix: Model security {:#model_security}
134 |
135 | Regardless of how you make your TensorFlow Lite models available to
136 | Firebase ML, Firebase ML stores them in the standard serialized protobuf format in
137 | local storage.
138 |
139 | In theory, this means that anybody can copy your model. However,
140 | in practice, most models are so application-specific and obfuscated by
141 | optimizations that the risk is similar to that of competitors disassembling and
142 | reusing your code. Nevertheless, you should be aware of this risk before you use
143 | a custom model in your app.
144 |
--------------------------------------------------------------------------------
/docs/flutter/perf-mon/_custom-network-traces.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/perf-mon/custom-network-traces?platform=flutter #}
3 |
4 | Performance Monitoring collects _traces_ to help you monitor the performance of your app. A
5 | trace is a report of performance data captured between two points in time in
6 | your app.
7 |
8 | The
9 | [network request traces automatically collected by Performance Monitoring](/docs/perf-mon/network-traces)
10 | include most network requests for your app. However, some requests might not be
11 | reported or you might use a different library to make network requests. In these
12 | cases, you can use the Performance Monitoring API to manually instrument
13 | **_custom network request traces_**. Custom network request traces are only
14 | supported for Apple and Android apps.
15 |
16 | The default metrics for a custom network request trace are the same as those for
17 | the network request traces automatically collected by Performance Monitoring, specifically
18 | response time, response and request payload size, and success rate. Custom
19 | network request traces do not support adding custom metrics.
20 |
21 | In your code, you define the beginning and the end of a custom network request
22 | trace using the APIs provided by the Performance Monitoring SDK.
23 |
24 | Custom network request traces appear in the Firebase console alongside the
25 | network requests that Performance Monitoring captures automatically
26 | (in the _Network requests_ subtab of the traces table).
27 |
28 |
29 | ## Add custom network request traces {:#add-custom-network-traces}
30 |
31 | Use the Performance Monitoring HttpMetric API
32 | to add custom network request traces to monitor specific network requests.
33 |
34 | To manually instrument custom network requests in Performance Monitoring, add code similar
35 | to the following:
36 |
37 | ```dart
38 | final metric = FirebasePerformance.instance
39 | .newHttpMetric("https://www.google.com", HttpMethod.Get);
40 |
41 | await metric.start();
42 | final response = await http.get(Uri.parse("https://www.google.com/"));
43 | await metric.stop();
44 | ```
45 |
46 | Custom network request traces also support adding custom attributes
47 | but not custom metrics.
48 |
49 |
50 | ## Next steps
51 |
52 | * [Set up alerts](/docs/perf-mon/alerts) for network requests that are degrading
53 | the performance of your app. For example, you can configure an email alert for
54 | your team if the _response time_ for a specific URL pattern exceeds a
55 | threshold that you set.
56 |
--------------------------------------------------------------------------------
/docs/flutter/perf-mon/_disable-sdk.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/perf-mon/disable-sdk?platform=flutter #}
3 |
4 | During app development and testing, you might find it useful to disable
5 | Performance Monitoring.
6 |
7 | For example, by
8 | [disabling Performance Monitoring during your app build process](#disable-during-build),
9 | you can:
10 |
11 | * Disable certain functionalities of Performance Monitoring in your debug
12 | builds, but re-enable the functionalities for your release build.
13 |
14 | * Disable Performance Monitoring when building your app, but allow your app to
15 | re-enable it at runtime.
16 |
17 | * Disable Performance Monitoring when building your app, and do not allow your
18 | app to re-enable it at runtime.
19 |
20 | You can also build your app with Performance Monitoring _enabled_, but
21 | [use Firebase Remote Config](#disable-with-remote-config) to give you
22 | flexibility to disable (and re-enable) Performance Monitoring in your production
23 | app. With this option, you can even configure your app to let users opt-in or
24 | opt-out of using Performance Monitoring.
25 |
26 | ## Disable Performance Monitoring during your app build process {: #disable-during-build}
27 |
28 | One situation where disabling Performance Monitoring during your app build
29 | process could be useful is to avoid reporting performance data from a
30 | pre-release version of your app during app development and testing.
31 |
32 | To do so, see the platform-specific [iOS+](?platform=ios) and
33 | [Android](?platform=android) docs.
34 |
35 |
36 | ## Disable your app at runtime using Remote Config {: #disable-with-remote-config}
37 |
38 | [Firebase Remote Config](/docs/remote-config/get-started?platform=flutter) lets
39 | you make changes to the behavior and appearance of your app, so it provides an
40 | ideal way to let you disable Performance Monitoring in deployed instances of
41 | your app.
42 |
43 | For example, suppose you want to use a parameter called `perf_disable` to
44 | remotely control Performance Monitoring. Add the following to your startup code
45 | to enable or disable Performance Monitoring:
46 |
47 | ```dart
48 | // Activate previously-fetched values, falling back on the defaults if
49 | // nothing is available yet.
50 | await FirebaseRemoteConfig.instance
51 | .setDefaults(YOUR_REMOTE_CONFIG_DEFAULTS);
52 | await FirebaseRemoteConfig.instance.activate();
53 |
54 | // Enable or disable Performance Monitoring based on the value of
55 | // "perf_disable".
56 | final perfMonDisabled =
57 | FirebaseRemoteConfig.instance.getBool("perf_disable");
58 | FirebasePerformance.instance
59 | .setPerformanceCollectionEnabled(!perfMonDisabled);
60 |
61 | // Fetch values for next time. (Don't await the result!)
62 | FirebaseRemoteConfig.instance.fetch();
63 | ```
64 |
65 | Note: This snippet requires an app restart to activate configuration changes.
66 | See [Loading strategies](/docs/remote-config/loading) for alternatives.
67 |
68 |
69 |
--------------------------------------------------------------------------------
/docs/flutter/perf-mon/get-started.md:
--------------------------------------------------------------------------------
1 | Project: /docs/perf-mon/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 | {% include "_shared/apis/console/_local_variables.html" %}
6 | {% include "_local_variables.html" %}
7 | {% include "docs/perf-mon/_local_variables.html" %}
8 | {% include "_shared/firebase/_snippet_include_comment.html" %}
9 |
10 |
11 |
12 | # Get started with Performance Monitoring for Flutter
13 |
14 | This quickstart describes how to set up Firebase Performance Monitoring to help
15 | you to gain insight into the performance characteristics of your Flutter apps.
16 |
17 |
18 | ## Before you begin
19 |
20 | If you haven't already,
21 | [configure and initialize Firebase](/docs/flutter/setup) in your Flutter
22 | project.
23 |
24 | ## **Step 1**: Add Performance Monitoring to your app {:#add-perfmon}
25 |
26 | 1. From the root directory of your Flutter project, run the following
27 | command to install the Performance Monitoring Flutter plugin:
28 |
29 | ```sh {: .devsite-terminal .devsite-click-to-copy data-terminal-prefix="your-flutter-proj$ " }
30 | flutter pub add firebase_performance
31 | ```
32 |
33 | 1. From the root directory of your Flutter project, run the following command:
34 |
35 | ```sh {: .devsite-terminal .devsite-click-to-copy data-terminal-prefix="your-flutter-proj$ " }
36 | flutterfire configure
37 | ```
38 |
39 | Running this command ensures that your Flutter app's Firebase configuration
40 | is up-to-date and, for Android, adds the required Performance Monitoring
41 | Gradle plugin to your app.
42 |
43 | 1. Once complete, rebuild your Flutter project:
44 |
45 | ```sh {: .devsite-terminal .devsite-click-to-copy data-terminal-prefix="your-flutter-proj$ " }
46 | flutter run
47 | ```
48 |
49 | After you've added the Performance Monitoring SDK, Firebase automatically starts collecting
50 | data related to your app's lifecycle (like
51 | [app start time](/docs/perf-mon/app-start-foreground-background-traces)), and
52 | data for [HTTP/S network requests](/docs/perf-mon/network-traces).
53 |
54 | On Flutter, automatic screen rendering performance monitoring is not possible
55 | for individual Flutter screens. A single view controller encapsulates your
56 | entire Flutter application natively so the underlying native Firebase SDK is
57 | not aware of screen transitions.
58 |
59 | Note: When you add Performance Monitoring to your app, the Remote Config SDK is
60 | included as a dependency. If you already use Remote Config, you won't see
61 | any difference. However, if you're new to Remote Config, explore the
62 | [Remote Config documentation](/docs/remote-config) to learn more
63 | about the various features you'll be able to access in your app.
64 |
65 |
66 | ## **Step 2**: Generate performance events for initial data display {:#data-in-console}
67 |
68 | Firebase starts processing the events when you successfully add the SDK to your
69 | app. If you're still developing locally, interact with your app to generate
70 | events for initial data collection and processing.
71 |
72 | Note: The Performance Monitoring SDK batches events locally then sends them to Firebase
73 | periodically (every 30 seconds) or when the app comes back to foreground. So,
74 | there's a delay between an app interaction and when Firebase receives the event
75 | information from your app.
76 |
77 | 1. Continue to develop your app using a simulator or test device.
78 |
79 | 1. Generate events by switching your app between background and foreground
80 | several times, interacting with your app by navigating across screens,
81 | and/or triggering network requests.
82 |
83 | 1. Go to the [_Performance_ dashboard](//console.firebase.google.com/project/_/performance)
84 | of the Firebase console. You should see your initial data display within
85 | a few minutes.
86 |
87 | If you don't see a display of your initial data, review the [troubleshooting
88 | tips](/docs/perf-mon/troubleshooting?platform=ios#sdk-detected-no-data).
89 |
90 |
91 | ## **Step 3**: _(Optional)_ View log messages for performance events {:#view-log-messages}
92 |
93 | 1. Check your log messages for any error messages.
94 |
95 | Performance Monitoring tags its log messages with the following tags so that
96 | you can filter your log messages:
97 |
98 | * iOS+: `Firebase/Performance`
99 | * Android: `FirebasePerformance`
100 |
101 | 1. Check for the following types of logs which indicate that Performance Monitoring is
102 | logging performance events:
103 |
104 | * Logging trace metric: TRACE_NAME, FIREBASE_PERFORMANCE_CONSOLE_URL
105 | * Logging network request trace: URL
106 |
107 | 1. Click on the URL to view your data in the Firebase console. It may take a few
108 | moments for the data to update in the dashboard.
109 |
110 | ## **Step 4**: _(Optional)_ Add custom monitoring for specific code {:#add-custom-trace}
111 |
112 | To monitor performance data associated with specific code in your app, you can
113 | instrument [**custom code traces**](/docs/perf-mon/custom-code-traces?platform=flutter).
114 |
115 | With a custom code trace, you can measure how long it takes your app to complete
116 | a specific task or set of tasks, such as loading a set of images or querying
117 | your database. The default metric for a custom code trace is its duration, but
118 | you can also add custom metrics, such as cache hits and memory warnings.
119 |
120 | In your code, you define the beginning and the end of a custom code trace (and
121 | add any desired custom metrics) using the API provided by the Performance Monitoring SDK.
122 |
123 | Visit [Add monitoring for specific code](/docs/perf-mon/custom-code-traces?platform=flutter)
124 | to learn more about these features and how to add them to your app.
125 |
126 | ## **Step 5**: Deploy your app then review results {:#deploy-then-review-results}
127 |
128 | After you've validated Performance Monitoring using the an emulator and one or more
129 | test devices, you can deploy the updated version of your app to your users.
130 |
131 | You can monitor performance data in the
132 | [_Performance_ dashboard](//console.firebase.google.com/project/_/performance)
133 | of the Firebase console.
134 |
135 |
136 | ## Next steps
137 |
138 | * Learn more about data automatically collected by Performance Monitoring:
139 |
140 | * Data related to your app's lifecycle, like
141 | [app start time](/docs/perf-mon/app-start-foreground-background-traces)
142 | * Data for [HTTP/S network requests](/docs/perf-mon/network-traces) issued
143 | by your app
144 |
145 | * [View, track, and filter](/docs/perf-mon/console) your
146 | performance data in the Firebase console.
147 |
148 | * Add monitoring for specific tasks or workflows in your app by
149 | [instrumenting custom code traces](/docs/perf-mon/custom-code-traces?platform=flutter).
150 |
151 | * [Use attributes to filter performance data](/docs/perf-mon/attributes).
152 |
--------------------------------------------------------------------------------
/docs/flutter/reference/_toc.yaml:
--------------------------------------------------------------------------------
1 | toc:
2 | - title: cloud_firestore
3 | path: https://pub.dev/documentation/cloud_firestore/latest/
4 | status: external
5 | - title: cloud_firestore_web
6 | path: https://pub.dev/documentation/cloud_firestore_web/latest/
7 | status: external
8 | - title: cloud_functions
9 | path: https://pub.dev/documentation/cloud_functions/latest/
10 | status: external
11 | - title: cloud_functions_web
12 | path: https://pub.dev/documentation/cloud_functions_web/latest/
13 | status: external
14 | - title: firebase_analytics
15 | path: https://pub.dev/documentation/firebase_analytics/latest/
16 | status: external
17 | - title: firebase_analytics_web
18 | path: https://pub.dev/documentation/firebase_analytics_web/latest/
19 | status: external
20 | - title: firebase_app_check
21 | path: https://pub.dev/documentation/firebase_app_check/latest/
22 | status: external
23 | - title: firebase_app_installations
24 | path: https://pub.dev/documentation/firebase_app_installations/latest/
25 | status: external
26 | - title: firebase_auth
27 | path: https://pub.dev/documentation/firebase_auth/latest/
28 | status: external
29 | - title: firebase_auth_web
30 | path: https://pub.dev/documentation/firebase_auth_web/latest/
31 | status: external
32 | - title: firebase_core
33 | path: https://pub.dev/documentation/firebase_core/latest/
34 | status: external
35 | - title: firebase_core_web
36 | path: https://pub.dev/documentation/firebase_core_web/latest/
37 | status: external
38 | - title: firebase_crashlytics
39 | path: https://pub.dev/documentation/firebase_crashlytics/latest/
40 | status: external
41 | - title: firebase_database
42 | path: https://pub.dev/documentation/firebase_database/latest/
43 | status: external
44 | - title: firebase_dynamic_links
45 | path: https://pub.dev/documentation/firebase_dynamic_links/latest/
46 | status: external
47 | - title: firebase_in_app_messaging
48 | path: https://pub.dev/documentation/firebase_in_app_messaging/latest/
49 | status: external
50 | - title: firebase_messaging
51 | path: https://pub.dev/documentation/firebase_messaging/latest/
52 | status: external
53 | - title: firebase_messaging_web
54 | path: https://pub.dev/documentation/firebase_messaging_web/latest/
55 | status: external
56 | - title: firebase_ml_model_downloader
57 | path: https://pub.dev/documentation/firebase_ml_model_downloader/latest/
58 | status: external
59 | - title: firebase_performance
60 | path: https://pub.dev/documentation/firebase_performance/latest/
61 | status: external
62 | # - title: firebase_performance_platform_interface
63 | # path: https://pub.dev/documentation/firebase_performance_platform_interface/latest/
64 | # status: external
65 | - title: firebase_performance_web
66 | path: https://pub.dev/documentation/firebase_performance_web/latest/
67 | status: external
68 | - title: firebase_remote_config
69 | path: https://pub.dev/documentation/firebase_remote_config/latest/
70 | status: external
71 | - title: firebase_storage
72 | path: https://pub.dev/documentation/firebase_storage/latest/
73 | status: external
74 | - title: firebase_storage_web
75 | path: https://pub.dev/documentation/firebase_storage_web/latest/
76 | status: external
77 | - title: flutterfire_ui
78 | path: https://pub.dev/documentation/flutterfire_ui/latest/
79 | status: external
80 |
--------------------------------------------------------------------------------
/docs/flutter/setup/_setup_prereq_android.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/flutter/setup #}
3 |
4 | * Install your preferred [editor or IDE](//docs.flutter.dev/get-started/editor/).
5 |
6 | * Set up a device or emulator for running your app.
7 | [Emulators](https://developer.android.com/studio/run/managing-avds){: .external}
8 | must use an emulator image with Google Play.
9 |
10 | * Make sure that your app meets the following requirements:
11 |
12 | * Targets API level {{android_min_api_level}} ({{android_min_api_codename}})
13 | or higher
14 | * Uses Android {{android_min_version}} or higher
15 |
16 | * [Install Flutter](//docs.flutter.dev/get-started/install/) for your specific
17 | operating system, including the following:
18 |
19 | * Flutter SDK
20 | * Supporting libraries
21 | * Platform-specific software and SDKs
22 |
23 | * [Sign into Firebase]({{name_appmanagerURL}}){: .external} using your Google
24 | account.
25 |
26 | If you don't already have a Flutter app, you can complete the [Get
27 | Started: Test Drive](//docs.flutter.dev/get-started/test-drive#androidstudio) to
28 | create a new Flutter app using your preferred editor or IDE.
29 |
--------------------------------------------------------------------------------
/docs/flutter/setup/_setup_prereq_ios.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/flutter/setup #}
3 |
4 | * Install your preferred [editor or IDE](//docs.flutter.dev/get-started/editor/).
5 |
6 | * Set up a physical Apple device or use a simulator to run your app.
7 |
8 | {# Google-internal file; not on GitHub. #}
9 | <<../../../_internal/includes/docs/guides/_setup-ios_prereq_want-to-use-fcm.md>>
10 |
11 | * Make sure that your Flutter app targets the following platform versions or
12 | later:
13 | * iOS {{min_ios_os_version}}
14 | * macOS {{min_mac_os_version}}
15 |
16 | * [Install Flutter](//docs.flutter.dev/get-started/install/) for your specific
17 | operating system, including the following:
18 |
19 | * Flutter SDK
20 | * Supporting libraries
21 | * Platform-specific software and SDKs
22 |
23 | * [Sign into Firebase]({{name_appmanagerURL}}){: .external} using your Google
24 | account.
25 |
26 | If you don't already have a Flutter app, you can complete the [Get
27 | Started: Test Drive](//docs.flutter.dev/get-started/test-drive/#androidstudio) to
28 | create a new Flutter app using your preferred editor or IDE.
29 |
30 | Note: If you're targeting macOS or macOS Catalyst, you must add the [Keychain Sharing capability](https://firebase.google.com/docs/ios/troubleshooting-faq#macos-keychain-sharing) to your target. In Xcode, navigate to your target's *Signing & Capabilities* tab, and then click **+ Capabilities** to add a new capability.
31 |
--------------------------------------------------------------------------------
/docs/flutter/setup/_setup_prereq_web.md:
--------------------------------------------------------------------------------
1 | {# This content gets published to the following location: #}
2 | {# https://firebase.google.com/docs/flutter/setup #}
3 |
4 | * Install your preferred [editor or IDE](//docs.flutter.dev/get-started/editor/).
5 |
6 | * [Install Flutter](//docs.flutter.dev/get-started/install/) for your specific
7 | operating system, including the following:
8 |
9 | * Flutter SDK
10 | * Supporting libraries
11 | * Platform-specific software and SDKs
12 |
13 | * [Sign into Firebase]({{name_appmanagerURL}}){: .external} using your Google
14 | account.
15 |
16 | If you don't already have a Flutter app, you can complete the [Get
17 | Started: Test Drive](//docs.flutter.dev/get-started/test-drive?tab=vscode) to
18 | create a new Flutter app using your preferred editor or IDE.
19 |
--------------------------------------------------------------------------------
/docs/flutter/storage/create-reference.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Create a Cloud Storage reference on Flutter
8 |
9 | Your files are stored in a
10 | [Cloud Storage](//cloud.google.com/storage) bucket. The
11 | files in this bucket are presented in a hierarchical structure, just like the
12 | file system on your local hard disk, or the data in the Firebase Realtime Database.
13 | By creating a reference to a file, your app gains access to it. These references
14 | can then be used to upload or download data, get or update metadata or delete
15 | the file. A reference can either point to a specific file or to a higher level
16 | node in the hierarchy.
17 |
18 | If you've used the [Firebase Realtime Database](/docs/database), these paths should
19 | seem very familiar to you. However, your file data is stored in
20 | Cloud Storage, **not** in the Realtime Database.
21 |
22 |
23 | ## Create a Reference
24 |
25 | Create a reference to upload, download, or delete a file,
26 | or to get or update its metadata. A reference
27 | can be thought of as a pointer to a file in the cloud. References are
28 | lightweight, so you can create as many as you need. They are also reusable for
29 | multiple operations.
30 |
31 | Create a reference using the `FirebaseStorage` singleton instance and
32 | calling its `ref()` method.
33 |
34 | ```dart
35 | final storageRef = FirebaseStorage.instance.ref();
36 | ```
37 |
38 | Next, you can create a reference to a location lower in the tree,
39 | say `"images/space.jpg"` by using the `child()` method on an existing reference.
40 |
41 | ```dart
42 | // Create a child reference
43 | // imagesRef now points to "images"
44 | final imagesRef = storageRef.child("images");
45 |
46 | // Child references can also take paths
47 | // spaceRef now points to "images/space.jpg
48 | // imagesRef still points to "images"
49 | final spaceRef = storageRef.child("images/space.jpg");
50 | ```
51 |
52 | ## Navigate with References
53 |
54 | You can also use the `parent` and `root` properties to navigate up in our
55 | file hierarchy. `parent` navigates up one level,
56 | while `root` navigates all the way to the top.
57 |
58 | ```dart
59 | // parent allows us to move our reference to a parent node
60 | // imagesRef2 now points to 'images'
61 | final imagesRef2 = spaceRef.parent;
62 |
63 | // root allows us to move all the way back to the top of our bucket
64 | // rootRef now points to the root
65 | final rootRef = spaceRef.root;
66 | ```
67 |
68 | `child()`, `parent`, and `root` can be chained together multiple
69 | times, as each is a reference. But accessing `root.parent` results in `null`.
70 |
71 | ```dart
72 | // References can be chained together multiple times
73 | // earthRef points to 'images/earth.jpg'
74 | final earthRef = spaceRef.parent?.child("earth.jpg");
75 |
76 | // nullRef is null, since the parent of root is null
77 | final nullRef = spaceRef.root.parent;
78 | ```
79 |
80 |
81 | ## Reference Properties
82 |
83 | You can inspect references to better understand the files they point to
84 | using the `fullPath`, `name`, and `bucket` properties. These properties
85 | get the file's full path, name and bucket.
86 |
87 | ```dart
88 | // Reference's path is: "images/space.jpg"
89 | // This is analogous to a file path on disk
90 | spaceRef.fullPath;
91 |
92 | // Reference's name is the last segment of the full path: "space.jpg"
93 | // This is analogous to the file name
94 | spaceRef.name;
95 |
96 | // Reference's bucket is the name of the storage bucket that the files are stored in
97 | spaceRef.bucket;
98 | ```
99 |
100 | ## Limitations on References
101 |
102 | Reference paths and names can contain any sequence of valid Unicode characters,
103 | but certain restrictions are imposed including:
104 |
105 | 1. Total length of reference.fullPath must be between 1 and 1024 bytes when UTF-8 encoded.
106 | 1. No Carriage Return or Line Feed characters.
107 | 1. Avoid using `#`, `[`, `]`, `*`, or `?`, as these do not work well with
108 | other tools such as the [Firebase Realtime Database](/docs/database/overview)
109 | or [gsutil](https://cloud.google.com/storage/docs/gsutil).
110 |
111 | ## Full Example
112 |
113 | ```dart
114 | // Points to the root reference
115 | final storageRef = FirebaseStorage.instance.ref();
116 |
117 | // Points to "images"
118 | Reference? imagesRef = storageRef.child("images");
119 |
120 | // Points to "images/space.jpg"
121 | // Note that you can use variables to create child values
122 | final fileName = "space.jpg";
123 | final spaceRef = imagesRef.child(fileName);
124 |
125 | // File path is "images/space.jpg"
126 | final path = spaceRef.fullPath;
127 |
128 | // File name is "space.jpg"
129 | final name = spaceRef.name;
130 |
131 | // Points to "images"
132 | imagesRef = spaceRef.parent;
133 | ```
134 |
135 | Next, let's learn how to [upload files](upload-files) to Cloud Storage.
136 |
--------------------------------------------------------------------------------
/docs/flutter/storage/delete-files.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Delete files with Cloud Storage on Flutter
8 |
9 | After uploading files to Cloud Storage, you can also delete them.
10 |
11 | Note: By default, a Cloud Storage bucket requires Firebase Authentication to
12 | perform any action on the bucket's data or files. You can
13 | [change your Firebase Security Rules for Cloud Storage](/docs/storage/security/rules-conditions#public)
14 | to allow unauthenticated access. Since Firebase and your project's default
15 | App Engine app share this bucket, configuring public access may make newly
16 | uploaded App Engine files publicly accessible, as well. Be sure to restrict
17 | access to your Cloud Storage bucket again when you set up Authentication.
18 |
19 |
20 | ## Delete a File
21 |
22 | To delete a file, first [create a reference](create-reference)
23 | to that file. Then call the `delete()` method on that reference.
24 |
25 | ```dart
26 | // Create a reference to the file to delete
27 | final desertRef = storageRef.child("images/desert.jpg");
28 |
29 | // Delete the file
30 | await desertRef.delete();
31 | ```
32 |
33 | Warning: Deleting a file is a permanent action! If you care about restoring
34 | deleted files, make sure to back up your files, or
35 | [enable Object Versioning](https://cloud.google.com/storage/docs/using-object-versioning#set)
36 | on your Cloud Storage bucket.
37 |
38 |
39 | ## Handle Errors
40 |
41 | There are a number of reasons why errors may occur on file deletes,
42 | including the file not existing, or the user not having permission
43 | to delete the desired file. More information on errors can be found in the
44 | [Handle Errors](handle-errors) section of the docs.
45 |
--------------------------------------------------------------------------------
/docs/flutter/storage/download-files.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Download files with Cloud Storage on Flutter
8 |
9 | Cloud Storage for Firebase allows you to quickly and easily download
10 | files from a [Cloud Storage](//cloud.google.com/storage)
11 | bucket provided and managed by Firebase.
12 |
13 | Note: By default, a Cloud Storage bucket requires Firebase Authentication to
14 | perform any action on the bucket's data or files. You can
15 | [change your Firebase Security Rules for Cloud Storage](/docs/storage/security/rules-conditions#public)
16 | to allow unauthenticated access. Since Firebase and your project's default
17 | App Engine app share this bucket, configuring public access may make newly
18 | uploaded App Engine files publicly accessible, as well. Be sure to restrict
19 | access to your Cloud Storage bucket again when you set up Authentication.
20 |
21 |
22 |
23 | ## Create a Reference
24 |
25 | To download a file, first [create a Cloud Storage reference](create-reference)
26 | to the file you want to download.
27 |
28 | You can create a reference by appending child paths to the root of your
29 | Cloud Storage bucket, or you can create a reference from an existing
30 | `gs://` or `https://` URL referencing an object in Cloud Storage.
31 |
32 | ```dart
33 | // Create a storage reference from our app
34 | final storageRef = FirebaseStorage.instance.ref();
35 |
36 | // Create a reference with an initial file path and name
37 | final pathReference = storageRef.child("images/stars.jpg");
38 |
39 | // Create a reference to a file from a Google Cloud Storage URI
40 | final gsReference =
41 | FirebaseStorage.instance.refFromURL("gs://YOUR_BUCKET/images/stars.jpg");
42 |
43 | // Create a reference from an HTTPS URL
44 | // Note that in the URL, characters are URL escaped!
45 | final httpsReference = FirebaseStorage.instance.refFromURL(
46 | "https://firebasestorage.googleapis.com/b/YOUR_BUCKET/o/images%20stars.jpg");
47 | ```
48 |
49 |
50 | ## Download Files
51 |
52 | Once you have a reference, you can download files from Cloud Storage
53 | by calling the `getData()` or `getStream()`. If you prefer to download the file
54 | with another library, you can get a download URL with `getDownloadUrl()`.
55 |
56 | ### Download in memory
57 |
58 | Download the file to a `UInt8List` with the `getData()` method. This is the
59 | easiest way to download a file, but it must load the entire contents of
60 | your file into memory. If you request a file larger than your app's available
61 | memory, your app will crash. To protect against memory issues, `getData()`
62 | takes a maximum amount of bytes to download. Set the maximum size to something
63 | you know your app can handle, or use another download method.
64 |
65 | ```dart
66 | final islandRef = storageRef.child("images/island.jpg");
67 |
68 | try {
69 | const oneMegabyte = 1024 * 1024;
70 | final Uint8List? data = await islandRef.getData(oneMegabyte);
71 | // Data for "images/island.jpg" is returned, use this as needed.
72 | } on FirebaseException catch (e) {
73 | // Handle any errors.
74 | }
75 | ```
76 |
77 | ### Download to a local file
78 |
79 | The `writeToFile()` method downloads a file directly to a local device. Use this if
80 | your users want to have access to the file while offline or to share the file in a
81 | different app. `writeToFile()` returns a `DownloadTask` which you can use to manage
82 | your download and monitor the status of the download.
83 |
84 | ```dart
85 | final islandRef = storageRef.child("images/island.jpg");
86 |
87 | final appDocDir = await getApplicationDocumentsDirectory();
88 | final filePath = "${appDocDir.absolute}/images/island.jpg";
89 | final file = File(filePath);
90 |
91 | final downloadTask = islandRef.writeToFile(file);
92 | downloadTask.snapshotEvents.listen((taskSnapshot) {
93 | switch (taskSnapshot.state) {
94 | case TaskState.running:
95 | // TODO: Handle this case.
96 | break;
97 | case TaskState.paused:
98 | // TODO: Handle this case.
99 | break;
100 | case TaskState.success:
101 | // TODO: Handle this case.
102 | break;
103 | case TaskState.canceled:
104 | // TODO: Handle this case.
105 | break;
106 | case TaskState.error:
107 | // TODO: Handle this case.
108 | break;
109 | }
110 | });
111 | ```
112 |
113 | ## Download Data via URL
114 |
115 | If you already have download infrastructure based around URLs, or just want
116 | a URL to share, you can get the download URL for a file by calling the
117 | `getDownloadURL()` method on a Cloud Storage reference.
118 |
119 | ```dart
120 | final imageUrl =
121 | await storageRef.child("users/me/profile.png").getDownloadURL();
122 | ```
123 |
124 | ## Handle Errors
125 |
126 | There are a number of reasons why errors may occur on download, including the
127 | file not existing, or the user not having permission to access the desired file.
128 | More information on errors can be found in the [Handle Errors](handle-errors)
129 | section of the docs.
130 |
131 | ## Full Example
132 |
133 | A full example of a download with error handling is shown below:
134 |
135 | ```dart
136 | final islandRef = storageRef.child("images/island.jpg");
137 |
138 | final appDocDir = await getApplicationDocumentsDirectory();
139 | final filePath = "${appDocDir.absolute}/images/island.jpg";
140 | final file = File(filePath);
141 |
142 | final downloadTask = islandRef.writeToFile(file);
143 | downloadTask.snapshotEvents.listen((taskSnapshot) {
144 | switch (taskSnapshot.state) {
145 | case TaskState.running:
146 | // TODO: Handle this case.
147 | break;
148 | case TaskState.paused:
149 | // TODO: Handle this case.
150 | break;
151 | case TaskState.success:
152 | // TODO: Handle this case.
153 | break;
154 | case TaskState.canceled:
155 | // TODO: Handle this case.
156 | break;
157 | case TaskState.error:
158 | // TODO: Handle this case.
159 | break;
160 | }
161 | });
162 | ```
163 |
164 | You can also [get and update metadata](file-metadata) for files that are stored
165 | in Cloud Storage.
166 |
--------------------------------------------------------------------------------
/docs/flutter/storage/file-metadata.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Use file metadata with Cloud Storage on Flutter
8 |
9 | After uploading a file to Cloud Storage reference, you can also get
10 | and update the file metadata, for example to view or update the content type.
11 | Files can also store custom key/value pairs with additional file metadata.
12 |
13 | Note: By default, a Cloud Storage bucket requires Firebase Authentication to
14 | perform any action on the bucket's data or files. You can
15 | [change your Firebase Security Rules for Cloud Storage](/docs/storage/security/rules-conditions#public)
16 | to allow unauthenticated access. Since Firebase and your project's default
17 | App Engine app share this bucket, configuring public access may make newly
18 | uploaded App Engine files publicly accessible, as well. Be sure to restrict
19 | access to your Cloud Storage bucket again when you set up Authentication.
20 |
21 |
22 |
23 | ## Get File Metadata
24 |
25 | File metadata contains common properties such as `name`, `size`, and
26 | `contentType` (often referred to as MIME type) in addition to some less
27 | common ones like `contentDisposition` and `timeCreated`. This metadata can be
28 | retrieved from a Cloud Storage reference using
29 | the `getMetadata()` method.
30 |
31 | ```dart
32 | // Create reference to the file whose metadata we want to retrieve
33 | final forestRef = storageRef.child("images/forest.jpg");
34 |
35 | // Get metadata properties
36 | final metadata = await forestRef.getMetadata();
37 |
38 | // Metadata now contains the metadata for 'images/forest.jpg'
39 | ```
40 |
41 |
42 | ## Update File Metadata
43 |
44 | You can update file metadata at any time after the file upload completes by
45 | using the `updateMetadata()` method. Refer to the
46 | [full list](#file-metadata-properties) for more information on what properties
47 | can be updated. Only the properties specified in the metadata are updated,
48 | all others are left unmodified.
49 |
50 | ```dart
51 | // Create reference to the file whose metadata we want to change
52 | final forestRef = storageRef.child("images/forest.jpg");
53 |
54 | // Create file metadata to update
55 | final newMetadata = SettableMetadata(
56 | cacheControl: "public,max-age=300",
57 | contentType: "image/jpeg",
58 | );
59 |
60 | // Update metadata properties
61 | final metadata = await forestRef.updateMetadata(newMetadata);
62 |
63 | // Updated metadata for 'images/forest.jpg' is returned
64 | ```
65 |
66 | You can delete writable metadata properties by passing `null`:
67 |
68 | ```dart
69 | // Delete the cacheControl property
70 | final newMetadata = SettableMetadata(cacheControl: null);
71 | final metadata = await forestRef.updateMetadata(newMetadata);
72 | ```
73 |
74 |
75 | ## Handle Errors
76 |
77 | There are a number of reasons why errors may occur on getting or updating
78 | metadata, including the file not existing, or the user not having permission
79 | to access the desired file. More information on errors can be found in the
80 | [Handle Errors](handle-errors) section of the docs.
81 |
82 | ## Custom Metadata
83 |
84 | You can specify custom metadata using the `customMetadata` parameter of the
85 | `SettableMetadata` constructor:
86 |
87 | ```dart
88 | // Create reference to the file whose metadata we want to change
89 | final forestRef = storageRef.child("images/forest.jpg");
90 |
91 | // Create file metadata to update
92 | final newCustomMetadata = SettableMetadata(
93 | customMetadata: {
94 | "location": "Yosemite, CA, USA",
95 | "activity": "Hiking",
96 | },
97 | );
98 |
99 | // Update metadata properties
100 | final metadata = await forestRef.updateMetadata(newCustomMetadata);
101 |
102 | // Updated metadata for 'images/forest.jpg' is returned
103 | ```
104 |
105 | You can store app-specific data for each file in custom metadata, but we highly
106 | recommend using a database (such as the
107 | [Firebase Realtime Database](/docs/database/overview)) to store and synchronize this type of
108 | data.
109 |
110 |
111 | ## File Metadata Properties {:#file-metadata-properties}
112 |
113 | A full list of metadata properties on a file is available below:
114 |
115 | Property | Type | Settable?
116 | ---------------------|-----------------------|----------
117 | `bucket` | `String` | No
118 | `generation` | `String` | No
119 | `metageneration` | `String` | No
120 | `metadataGeneration` | `String` | No
121 | `fullPath` | `String` | No
122 | `name` | `String` | No
123 | `size` | `int` | No
124 | `timeCreated` | `DateTime` | No
125 | `updated` | `DateTime` | No
126 | `md5Hash` | `String` | No
127 | `cacheControl` | `String` | Yes
128 | `contentDisposition` | `String` | Yes
129 | `contentEncoding` | `String` | Yes
130 | `contentLanguage` | `String` | Yes
131 | `contentType` | `String` | Yes
132 | `customMetadata` | `Map` | Yes
133 |
134 | Uploading, downloading, and updating files is important, but so is being able
135 | to remove them. Let's learn how to [delete files](delete-files)
136 | from Cloud Storage.
137 |
--------------------------------------------------------------------------------
/docs/flutter/storage/handle-errors.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Handle errors for Cloud Storage on Flutter
8 |
9 | Sometimes when you're building an app, things don't go as planned and an
10 | error occurs!
11 |
12 | When in doubt, catch the exception thrown by the function
13 | and see what the error message has to say.
14 |
15 | ```dart
16 | final storageRef = FirebaseStorage.instance.ref().child("files/uid");
17 | try {
18 | final listResult = await storageRef.listAll();
19 | } on FirebaseException catch (e) {
20 | // Caught an exception from Firebase.
21 | print("Failed with error '${e.code}': ${e.message}");
22 | }
23 | ```
24 |
25 | Note: By default, a Cloud Storage bucket requires Firebase Authentication to
26 | perform any action on the bucket's data or files. You can
27 | [change your Firebase Security Rules for Cloud Storage](/docs/storage/security/rules-conditions#public)
28 | to allow unauthenticated access. Since Firebase and your project's default
29 | App Engine app share this bucket, configuring public access may make newly
30 | uploaded App Engine files publicly accessible, as well. Be sure to restrict
31 | access to your Cloud Storage bucket again when you set up Authentication.
32 |
33 |
34 | ## Handle Error Messages
35 |
36 | There are a number of reasons why errors may occur, including the file
37 | not existing, the user not having permission to access the desired file, or the
38 | user cancelling the file upload.
39 |
40 | To properly diagnose the issue and handle the error, here is a full list of
41 | all the errors our client will raise, and how they occurred.
42 |
43 | Code | Description
44 | ---------------------------------|--------------------------------------------
45 | `storage/unknown` | An unknown error occurred.
46 | `storage/object-not-found` | No object exists at the desired reference.
47 | `storage/bucket-not-found` | No bucket is configured for Cloud Storage
48 | `storage/project-not-found` | No project is configured for Cloud Storage
49 | `storage/quota-exceeded` | Quota on your Cloud Storage bucket has been exceeded. If you're on the no-cost tier, upgrade to a paid plan. If you're on a paid plan, reach out to Firebase support.
50 | `storage/unauthenticated` | User is unauthenticated, please authenticate and try again.
51 | `storage/unauthorized` | User is not authorized to perform the desired action, check your security rules to ensure they are correct.
52 | `storage/retry-limit-exceeded` | The maximum time limit on an operation (upload, download, delete, etc.) has been excceded. Try uploading again.
53 | `storage/invalid-checksum` | File on the client does not match the checksum of the file received by the server. Try uploading again.
54 | `storage/canceled` | User canceled the operation.
55 | `storage/invalid-event-name` | Invalid event name provided. Must be one of [`running`, `progress`, `pause`]
56 | `storage/invalid-url` | Invalid URL provided to `refFromURL()`. Must be of the form: `gs://bucket/object` or `https://firebasestorage.googleapis.com/v0/b/bucket/o/object?token=`
57 | `storage/invalid-argument` | The argument passed to `put()` must be `File`, `Blob`, or `UInt8` Array. The argument passed to `putString()` must be a raw, `Base64`, or `Base64URL` string.
58 | `storage/no-default-bucket` | No bucket has been set in your config's `storageBucket` property.
59 | `storage/cannot-slice-blob` | Commonly occurs when the local file has changed (deleted, saved again, etc.). Try uploading again after verifying that the file hasn't changed.
60 | `storage/server-file-wrong-size` | File on the client does not match the size of the file received by the server. Try uploading again.
61 |
--------------------------------------------------------------------------------
/docs/flutter/storage/list-files.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # List files with Cloud Storage on Flutter
8 |
9 | Cloud Storage for Firebase allows you to list the contents of your
10 | Cloud Storage bucket. The SDKs return both the items and the prefixes of
11 | objects under the current Cloud Storage reference.
12 |
13 | Projects that use the List API require Cloud Storage for Firebase
14 | Rules version 2. If you have an existing Firebase project, follow the steps in
15 | the [Security Rules Guide](/docs/storage/security/core-syntax).
16 |
17 | Note: The List API is only allowed for Rules version 2.
18 | In Rules version 2, `allow read` is the shorthand for `allow get, list`.
19 |
20 |
21 | `list()` uses the
22 | [Google Cloud Storage List API](//cloud.google.com/storage/docs/json_api/v1/objects/list).
23 | In Cloud Storage for Firebase, we use `/` as a delimiter, which allows us to
24 | emulate file system semantics. To allow for efficient traversal of large,
25 | hierarchical Cloud Storage buckets, the List API returns prefixes and
26 | items separately. For example, if you upload one file `/images/uid/file1`,
27 |
28 | * `root.child('images').listAll()` will return `/images/uid` as a prefix.
29 | * `root.child('images/uid').listAll()` will return the file as an item.
30 |
31 | The Cloud Storage for Firebase SDK does not return object paths that contain two
32 | consecutive `/`s or end with a `/`. For example, consider a bucket that has the
33 | following objects:
34 |
35 | * `correctPrefix/happyItem`
36 | * `wrongPrefix//sadItem`
37 | * `lonelyItem/`
38 |
39 | The list operations on items in this bucket will give the following results:
40 |
41 | * The list operation at the root returns the references to `correctPrefix`,
42 | `wrongPrefix` and `lonelyItem` as `prefixes`.
43 | * The list operation at the `correctPrefix/` returns the references to
44 | `correctPrefix/happyItem` as `items`.
45 | * The list operation at the `wrongPrefix/` doesn't return any references
46 | because `wrongPrefix//sadItem` contains two consecutive `/`s.
47 | * The list operation at the `lonelyItem/` doesn't return any references
48 | because the object `lonelyItem/` ends with `/`.
49 |
50 | ## List all files
51 |
52 | You can use `listAll` to fetch all results for a directory.
53 | This is best used for small directories as all results are buffered in memory.
54 | The operation also may not return a consistent snapshot if objects are added or
55 | removed during the process.
56 |
57 | For a large list, use the paginated `list()` method as `listAll()` buffers all
58 | results in memory.
59 |
60 | The following example demonstrates `listAll`.
61 |
62 | ```dart
63 | final storageRef = FirebaseStorage.instance.ref().child("files/uid");
64 | final listResult = await storageRef.listAll();
65 | for (var prefix in listResult.prefixes) {
66 | // The prefixes under storageRef.
67 | // You can call listAll() recursively on them.
68 | }
69 | for (var item in listResult.items) {
70 | // The items under storageRef.
71 | }
72 | ```
73 |
74 | ## Paginate list results
75 |
76 | The `list()` API places a limit on the number of results it returns. `list()`
77 | provides a consistent pageview and exposes a pageToken that allows control over
78 | when to fetch additional results.
79 |
80 | The pageToken encodes the path and version of the last item returned in the
81 | previous result. In a subsequent request using the pageToken, items that come
82 | after the pageToken are shown.
83 |
84 | The following example demonstrates paginating a result:
85 |
86 | ```dart
87 | Stream listAllPaginated(Reference storageRef) async* {
88 | String? pageToken;
89 | do {
90 | final listResult = await storageRef.list(ListOptions(
91 | maxResults: 100,
92 | pageToken: pageToken,
93 | ));
94 | yield listResult;
95 | pageToken = listResult.nextPageToken;
96 | } while (pageToken != null);
97 | }
98 | ```
99 |
100 | ## Handle errors
101 |
102 | `list()` and `listAll()` fail if you haven't upgraded
103 | the Security Rules to version 2. Upgrade your Security Rules if you see this
104 | error:
105 |
106 | ```
107 | Listing objects in a bucket is disallowed for rules_version = "1".
108 | Please update storage security rules to rules_version = "2" to use list.
109 | ```
110 |
111 | Other possible errors may indicate the user does not have the right permission.
112 | More information on errors can be found in the [Handle Errors](handle-errors)
113 | page.
114 |
--------------------------------------------------------------------------------
/docs/flutter/storage/start.md:
--------------------------------------------------------------------------------
1 | Project: /docs/storage/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 |
6 |
7 | # Get started with Cloud Storage on Flutter
8 |
9 | Cloud Storage for Firebase lets you upload and share user generated content, such
10 | as images and video, which allows you to build rich media content into your
11 | apps. Your data is stored in a
12 | [Google Cloud Storage](//cloud.google.com/storage) bucket — an
13 | exabyte scale object storage solution with high availability and global
14 | redundancy. Cloud Storage for Firebase lets you securely upload these files
15 | directly from mobile devices and web browsers, handling spotty networks with
16 | ease.
17 |
18 |
19 | ## Prerequisites
20 |
21 | [Install and initialize the Firebase SDKs for Flutter](/docs/flutter/setup) if you
22 | haven't already done so.
23 |
24 |
25 | ## Create a default Cloud Storage bucket {:#create-default-bucket}
26 |
27 | 1. From the navigation pane of the [Firebase console](https://console.firebase.google.com/), select **Storage**,
28 | then click **Get started**.
29 |
30 | 1. Review the messaging about securing your Cloud Storage data using security
31 | rules. During development, consider
32 | [setting up your rules for public access](#set_up_public_access).
33 |
34 | 1. Select a [location](/docs/projects/locations#types) for your default
35 | Cloud Storage bucket.
36 |
37 | * This location setting is your project's
38 | [_default Google Cloud Platform (GCP) resource location_](/docs/firestore/locations#default-cloud-location).
39 | Note that this location will be used for GCP services in your project
40 | that require a location setting, specifically, your
41 | [Cloud Firestore](/docs/firestore) database and your
42 | [App Engine](//cloud.google.com/appengine/docs/) app
43 | (which is required if you use Cloud Scheduler).
44 |
45 | * If you aren't able to select a location, then your project already
46 | has a default GCP resource location. It was set either during project
47 | creation or when setting up another service that requires a location
48 | setting.
49 |
50 | If you're on the Blaze plan, you can
51 | [create multiple buckets](#use_multiple_storage_buckets), each with its own
52 | [location](//cloud.google.com/storage/docs/bucket-locations).
53 |
54 | Note: After you set your project's default GCP resource location, you
55 | cannot change it.
56 |
57 | 1. Click **Done**.
58 |
59 |
60 | ## Set up public access {:#set_up_public_access}
61 |
62 | Cloud Storage for Firebase provides a declarative rules language that allows you
63 | to define how your data should be structured, how it should be indexed, and when
64 | your data can be read from and written to. By default, read and write access to
65 | Cloud Storage is restricted so only authenticated users can read or write
66 | data. To get started without setting up [Firebase Authentication](/docs/auth), you can
67 | [configure your rules for public access](/docs/storage/security/rules-conditions#public).
68 |
69 | This does make Cloud Storage open to anyone, even people not using your
70 | app, so be sure to restrict your Cloud Storage again when you set up
71 | authentication.
72 |
73 |
74 | ## Add the Cloud Storage SDK to your app {:#add-sdk}
75 |
76 | 1. From the root of your Flutter project, run the following command to install
77 | the plugin:
78 |
79 | ```bash
80 | flutter pub add firebase_storage
81 | ```
82 |
83 | 1. Once complete, rebuild your Flutter application:
84 |
85 | ```bash
86 | flutter run
87 | ```
88 |
89 | 1. Import the plugin in your Dart code:
90 |
91 | ```dart
92 | import 'package:firebase_storage/firebase_storage.dart';
93 | ```
94 |
95 |
96 | ## Set up Cloud Storage {:#set-up-cloud-storage}
97 |
98 | The first step in accessing your Cloud Storage bucket is to create an
99 | instance of `FirebaseStorage`:
100 |
101 | ```dart
102 | final storage = FirebaseStorage.instance;
103 | ```
104 |
105 | You're ready to start using Cloud Storage!
106 |
107 | First, let's learn how to [create a Cloud Storage reference](create-reference).
108 |
109 | ## Advanced setup
110 |
111 | There are a few use cases that require additional setup:
112 |
113 | - Using Cloud Storage buckets in
114 | [multiple geographic regions](//cloud.google.com/storage/docs/bucket-locations)
115 | - Using Cloud Storage buckets in
116 | [different storage classes](//cloud.google.com/storage/docs/storage-classes)
117 | - Using Cloud Storage buckets with multiple authenticated users in the same app
118 |
119 | The first use case is perfect if you have users across the world, and want to
120 | store their data near them. For instance, you can create buckets in the US,
121 | Europe, and Asia to store data for users in those regions to reduce latency.
122 |
123 | The second use case is helpful if you have data with different access patterns.
124 | For instance: you can set up a multi-regional or regional bucket that stores
125 | pictures or other frequently accessed content, and a nearline or coldline bucket
126 | that stores user backups or other infrequently accessed content.
127 |
128 | In either of these use cases, you'll want to
129 | [use multiple Cloud Storage buckets](#use_multiple_storage_buckets).
130 |
131 | The third use case is useful if you're building an app, like Google Drive, which
132 | lets users have multiple logged in accounts (for instance, a personal account
133 | and a work account). You can
134 | [use a custom Firebase App](#use_a_custom_firebaseapp)
135 | instance to authenticate each additional account.
136 |
137 | ### Use multiple Cloud Storage buckets {:#use_multiple_storage_buckets}
138 |
139 | If you want to use a Cloud Storage bucket other than the default provided above,
140 | or use multiple Cloud Storage buckets in a single app, you can create an instance
141 | of `FirebaseStorage` that references your custom bucket:
142 |
143 | ```dart
144 | // Get a non-default Storage bucket
145 | final storage = FirebaseStorage.instanceFor(bucket: "gs://my-custom-bucket");
146 | ```
147 |
148 | ### Working with imported buckets
149 |
150 | When importing an existing Cloud Storage bucket into Firebase, you'll
151 | have to grant Firebase the ability to access these files using the
152 | `gsutil` tool, included in the
153 | [Google Cloud SDK](//cloud.google.com/sdk/docs/):
154 |
155 | ```bash
156 | gsutil -m acl ch -r -u service-PROJECT_NUMBER@gcp-sa-firebasestorage.iam.gserviceaccount.com gs://YOUR-CLOUD-STORAGE-BUCKET
157 | ```
158 |
159 | You can find your project number as described in the [introduction to
160 | Firebase projects](/docs/projects/learn-more#project-number).
161 |
162 | This does not affect newly created buckets, as those have the default access
163 | control set to allow Firebase. This is a temporary measure, and will be
164 | performed automatically in the future.
165 |
166 | ### Use a custom Firebase App {:#use_a_custom_firebaseapp}
167 |
168 | If you're building a more complicated app using a custom `FirebaseApp`, you can
169 | create an instance of `FirebaseStorage` initialized with that app:
170 |
171 | ```dart
172 | // Use a non-default App
173 | final storage = FirebaseStorage.instanceFor(app: customApp);
174 | ```
175 |
176 |
177 | ## Next steps
178 |
179 | * Prepare to launch your app:
180 | * Enable [App Check](/docs/app-check/overview) to help ensure that only
181 | your apps can access your storage buckets.
182 | * Set up [budget alerts](/docs/projects/billing/avoid-surprise-bills#set-up-budget-alert-emails)
183 | for your project in the Google Cloud Console.
184 | * Monitor the [_Usage and billing_ dashboard](//console.firebase.google.com/project/_/usage)
185 | in the Firebase console to get an overall picture of your project's
186 | usage across multiple Firebase services. You can also visit the
187 | [Cloud Storage _Usage_ dashboard](//console.firebase.google.com/project/_/storage/usage) for more
188 | detailed usage information.
189 | * Review the [Firebase launch checklist](/support/guides/launch-checklist).
190 |
--------------------------------------------------------------------------------
/docs/flutter/test-lab/integration-testing-with-flutter.md:
--------------------------------------------------------------------------------
1 | Project: /docs/test-lab/_project.yaml
2 | Book: /docs/_book.yaml
3 | page_type: guide
4 |
5 | {% include "_shared/apis/console/_local_variables.html" %}
6 | {% include "_local_variables.html" %}
7 | {% include "docs/test-lab/_local_variables.html" %}
8 | {% include "docs/ios/_local_variables.html" %}
9 | {% include "_shared/firebase/_snippet_include_comment.html" %}
10 |
11 |
12 |
13 |
14 | # Integration Testing with Flutter
15 |
16 | To test Flutter apps with {{firebase_testlab}}, you can write Flutter
17 | integration tests, build Android APKs or iOS test zip files, and run as
18 | regular Android instrumentation tests or iOS XCTests.
19 |
20 |
21 | # Flutter integration test types {: #test-types}
22 |
23 | Flutter supports three types of tests: unit tests, widget tests, and
24 | integration tests. A *unit test* verifies the behavior of a method or class.
25 | A *widget test* verifies the behavior of Flutter widgets without running the
26 | app itself. An *integration test*, also called end-to-end testing or GUI
27 | testing, runs the full app.
28 |
29 | To learn more about integration tests, see [Flutter integration testing](https://docs.flutter.dev/testing/integration-tests){:.external}.
30 |
31 |
32 | # Write Flutter integration tests {: #write-flutter-integration-tests}
33 |
34 | To learn how to write integration tests, see the [project setup](https://docs.flutter.dev/testing/integration-tests#project-setup){:.external}
35 | section of the Flutter integration tests documentation. Optionally, you can
36 | follow [running using Flutter command](https://docs.flutter.dev/testing/integration-tests#running-using-the-flutter-command){:.external}
37 | to run and verify the tests locally.
38 |
39 |
40 | # Test on {{testlab}} {: #test-on-test-lab}
41 |
42 | You can use {{testlab}} with both Android and iOS targets.
43 |
44 |
45 | ## Android setup {: #android-setup}
46 |
47 | Follow the instructions in the
48 | [Android Device Testing](https://github.com/flutter/flutter/tree/main/packages/integration_test#android-device-testing){:.external}
49 | section of the README.
50 |
51 |
52 | ## iOS setup {: #ios-setup}
53 |
54 | Follow the instructions in the
55 | [iOS Device Testing](https://github.com/flutter/flutter/tree/main/packages/integration_test#ios-device-testing){:.external}
56 | section of the README.
57 |
58 | ## Robo test support {: #robo-test-support}
59 |
60 | [Robo tests](/docs/test-lab/android/robo-ux-test) do not natively support
61 | Flutter. To improve crawling of your app, use [Robo scripts](/docs/test-lab/android/run-robo-scripts),
62 | which are tests that automate manual QA tasks for mobile apps, and enable
63 | continuous integration (CI) and pre-launch testing strategies.
64 | For example, to control Robo behavior in a more precise and robust way, you can
65 | use clicks with [visionText](/docs/test-lab/android/robo-scripts-reference#click).
66 |
67 |
68 | # Analyze test results {: #analyze-test-results}
69 |
70 | You can run Flutter integration tests as an Android instrumentation test or an
71 | iOS XCTest. To analyze the result of an integration test, see the
72 | documentation for [Android](https://firebase.google.com/docs/test-lab/android/analyzing-results){:.external}
73 | and [iOS](https://firebase.google.com/docs/test-lab/ios/analyzing-results){:.external},
74 | depending on your platform.
75 |
76 |
77 | ## Limitations {: #limitations}
78 |
79 | Test timing information for individual test cases is not available, which means
80 | that features like test case duration and videos for individual test cases
81 | don't work as expected.
82 |
83 | ## Troubleshooting {: #troubleshooting}
84 |
85 | If you encounter issues, check the [public issue tracker for integration tests](https://github.com/flutter/flutter/issues?q=is%3Aopen+is%3Aissue+label%3Aintegration_test){:.external}.
86 |
87 | If you encounter a new issue caused by the integration test framework,
88 | file a new issue in the public issue tracker following the guidance in
89 | [Creating useful bug reports](https://docs.flutter.dev/resources/bug-reports){:.external}.
90 |
--------------------------------------------------------------------------------