'Flutter + firebase: Configure app to use local firebase emulator

I have configured firebase to run locally for debugging using the emulator by following this link.

Now I want to be able to run my app connected to the localhost for debugging triggers as well. Is there a way to achieve this by configuring my flutter app to use the localhost?

My emulator is running as following:

enter image description here



Solution 1:[1]

After carefully going through the docs here, I got it working by configuring the host setting on the firestore instance:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter/material.dart';
import 'package:tracker/screens/screens.dart';

void main() async {

  // This will set the app to communicate with localhost
  await Firestore.instance.settings(host: "10.0.2.2:8080", sslEnabled: false);

  runApp(AppSetupScreen());
}

Note: This will only work with emulator and not with physical device.

Solution 2:[2]

An add-on:

To make the Firebase emulators work with the physical devices

Work for both iOS and Android devices

1. Cloud functions setup:

in firebase.json

{
  // ...other configs
  "emulators": {
    "functions": {
      "port": 5001,
      "host": "0.0.0.0" // must have
    },
    "firestore": {
      "port": 8080,
      "host": "0.0.0.0" // must have
    },
  }
}

2. Your Flutter app setup:

The IP address you use for cloud functions and firestore should be the same

// The FirebaseFunctions config
// ! You need to replace the placeholder with your IP address below:
FirebaseFunctions.instance.useFunctionsEmulator(origin: 'http://<YOUR_IP_ADDRESS>:5001');

// The Firestore config
// ! You need to replace the placeholder with your IP address below:
FirebaseFirestore.instance.settings = Settings(
  host: '<YOUR_IP_ADDRESS>:8080',
  sslEnabled: false,
  persistenceEnabled: false,
);

Solution 3:[3]

for cloud_firestore: ^0.14.1+2, instead of using FirebaseFirestore.instance.settings use this -

FirebaseFunctions.instance.useFunctionsEmulator(
    origin: "http://localhost:5001",
  );

It internally handles setting up 10.0.2.2 if the device is android.

Your main block should look like the following

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  FirebaseFunctions.instance.useFunctionsEmulator(
    origin: "http://localhost:5001",
  );
  runApp(MyApp());
}

Solution 4:[4]

Looks like i've connected ios to localhost:8080, but db works very slow and I also didn't notice any logs in a file. @UsmanZaheer, can you please tell when did it write logs and was it working fast?

Steps:

  • firebase init

  • add links that have been created by ini to package.json in functions;

    "firestore": { "rules": "firestore.rules", "indexes": "firestore.indexes.json" },

  • firebase emulators:start

in main() write

await Firestore.instance.settings(
      host: 'http://localhost:8080',
      sslEnabled: false,
      persistenceEnabled: false,
      timestampsInSnapshotsEnabled: true
  ).catchError((e) => print(e));

Solution 5:[5]

Your main.dart should look like this:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firestore.instance
    .settings(
       host: 'http://localhost:8080',
       sslEnabled: false,
       persistenceEnabled: false,
     )
    .catchError((e) => print(e));
  // 
  // ...
  //
  runApp(App(...));
}

in your firebase.json file

  "emulators": {
    "firestore": {
          "host": "localhost",
          "port": 8080
    },
    ...
  }

you should also set the following in your terminal:

export FIRESTORE_EMULATOR_HOST=localhost:8080

and then run

firebase emulators:start

Solution 6:[6]

Adjustment for Flutter Web

addition to the correct answer by @Sultanmyrza

Platform requires dart:io/dart:html which are mutually exclussive so to check for the platform I use kIsWeb

FirebaseFirestore __firestore;
FirebaseFirestore get _firestore {
  if (__firestore != null) {
    return __firestore;
  }
  debugPrint('isFirebaseEmulator: $isFirebaseEmulator');
  __firestore = FirebaseFirestore.instance;
  if (isFirebaseEmulator) {
    __firestore.settings = const Settings(
      host: kIsWeb ? 'localhost:8080' : '10.0.2.2:8080',
      sslEnabled: false,
    );
  }
  return __firestore;
}

Solution 7:[7]

Latest Update: To connect flutter app to your local firebase emulator suite, follow this official instruction for configuration.

Solution 8:[8]

My init function looks like so:

init_firebase.dart

Future<void> initFirebase() async {
  await Firebase.initializeApp(
    options: DefaultFirebaseOptions.currentPlatform,
  );

  if (!kReleaseMode) {
    try {
      await Future.wait([
        FirebaseAuth.instance.useAuthEmulator('localhost', 9099),
        FirebaseStorage.instance.useStorageEmulator('localhost', 9199),
      ]);

      FirebaseFunctions.instance.useFunctionsEmulator('localhost', 5001);
      FirebaseFirestore.instance.useFirestoreEmulator('localhost', 8080);
    } catch (e) {}
  }
}

By using !kReleaseMode, we don't have to have a boolean that we switch each time. It will just use emulator by default during development

By wrapping it in try-catch block we avoid some errors from hot reload

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 UsmanZaheer
Solution 2 S1ngoooor
Solution 3 Samrat
Solution 4 Shakle
Solution 5 Mehmet Artun
Solution 6 Alex.F
Solution 7 sarru1291
Solution 8