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:
void main() {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
const bool USE_EMULATOR = true;
if (USE_EMULATOR) {
// [Firestore | localhost:8080]
FirebaseFirestore.instance.settings = const Settings(
host: 'localhost:8080',
sslEnabled: false,
persistenceEnabled: false,
);
// [Authentication | localhost:9099]
await FirebaseAuth.instance.useEmulator('http://localhost:9099');
// [Storage | localhost:9199]
await FirebaseStorage.instance.useEmulator(
host: 'localhost',
port: 9199,
);
}
}
Make sure your host and port matches from firebase emulators:start
NOTE: in main.dart
now you can always provide 'localhost'
await FirebaseAuth.instance.useEmulator('http://localhost:9099');
because it will change automagically to '10.0.2.2' if it is running on android
for latest guide follow https://firebase.flutter.dev/docs/firestore/usage#emulator-usage
STEP 1 [setup firestore in flutter in main.dart]
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); <--- Important!
await Firestore.instance.settings(
host: '192.168.1.38:5002', <--- Make sure to put your local ip
sslEnabled: false); it will not work if you use 'localhost:5002'
Google it "how to find my local ip"
}
STEP 1 [setup firestore in flutter in main.dart] for newer version of firebase
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); <--- Important!
String host = Platform.isAndroid ? '10.0.2.2:5002' : 'localhost:5002';
await FirebaseFirestore.instance.settings = Settings(
host: host,
sslEnabled: false,
);
}
STEP 2 [init firebase project]
firebase init
STEP 3 [config firestore emulator eg firebase.json]
"emulators": {
"ui": {
"enabled": true,
"host": "localhost",
"port": 4000
},
"functions": {
"port": 5001
},
"firestore": {
"host": "0.0.0.0", <------ Make sure to set it "0.0.0.0"
"port": 5002
},
}
STEP 4 [run emulators and flutter app]
firebase emulators:start
flutter run
Worked both on iOS simulator and Android emulators
PS: try to restart firestore emulator or/and flutter app
when you stop firestore emulator all data in firestore will be gone. So maybe before stoping emulator if you want to continue from where you left of you can export firestore emulator data like so
firebase emulators:export../data
(../data can be any path you want )
to load exported data
firebase emulators:start --import../data
you can save different states of your firestore emulator for different cases, example
firebase emulators:start --import ../initialData
firebase emulators:start --import ../otherStateData
If you want to use dart for firebase functions you can follow this https://github.com/pulyaevskiy/firebase-functions-interop
one good thing I found for myself to detect if your function is running in emulator or production you can read more here
functions/index.js
export const prepopulateFirestoreEmulator = functions.https.onRequest(
(request, response) => {
if (process.env.FUNCTIONS_EMULATOR && process.env.FIRESTORE_EMULATOR_HOST) {
// TODO: prepopulate firestore emulator from 'yourproject/src/sample_data.json
response.send('Prepopulated firestore with sample_data.json!');
} else {
response.send(
"Do not populate production firestore with sample_data.json"
);
}
}
);
functions/index.dart
import 'package:firebase_functions_interop/firebase_functions_interop.dart';
import 'package:node_interop/node.dart';
import 'package:node_interop/util.dart';
void devPrepopulateCollections(ExpressHttpRequest request) {
var env =
new Map<String, String>.from(dartify(process.env)); // <-- important part
if (env.containsKey('FUNCTIONS_EMULATOR') &&
env.containsKey('FIRESTORE_EMULATOR_HOST')) {
// TODO: prepopulate firestore emulator from 'yourproject/src/sample_data.json
request.response
..write("Prepopulated firestore with sample_data.json!")
..close();
} else {
request.response
..write("Do not populate production firestore with sample_data.json")
..close();
}
}
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.
Work for both iOS and Android devices
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
},
}
}
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,
);
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());
}
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));
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
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;
}
Latest Update : To connect flutter app to your local firebase emulator suite, followthis official instruction for configuration.
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
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.