How to use firebase initialize with routings in Flutter - firebase

I need to initialize the Fiberbese app in a flutter routed environment
EX: I wanna use
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
and after the future has completed I need to direct to the initialRoute
initialRoute:<**Replace this with a string after future returns**>,
routes: {
MyHomePage.Id :(context) => MyHomePage(),
SoundTester.Id :(context) => SoundTester(),
GoogleMapSample.Id:(context) => GoogleMapSample()
},
Is there any way to do this? or this is impossible to do?

Initialise your app in main.dart at the main() method like this
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized(); // add this line
await Firebase.initializeApp(); // add this line
runApp(MyApp());
}

Related

Initializing FIrebase on Flutter throws error

So I have been trying to initialize my firebase with my flutter app but it keeps throwing an error every time, the code has no problem since flutter builds the app fine but just not firebase.
So this is my code to initialize firebase;
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({Key? key}) : super(key: key);
#override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
bool _initialized = false;
bool _error = false;
void initializeFlutterFire() async {
try {
// Wait for Firebase to initialize and set `_initialized` state to true
await Firebase.initializeApp();
setState(() {
_initialized = true;
});
} catch (e) {
// Set `_error` state to true if Firebase initialization fails
setState(() {
_error = true;
});
}
}
#override
void initState() {
initializeFlutterFire();
super.initState();
}
#override
Widget build(BuildContext context) {
return MaterialApp();
and this is the error I keep getting:
Error: Assertion failed:
file:///home/pete/snap/flutter/common/flutter/.pub-cache/hosted/pub.dartlang.org/firebase_core_web-1.4.0/lib/src/fire
base_core_web.dart:271:11
options != null
"FirebaseOptions cannot be null when creating the default app."
at Object.throw_ [as throw] (http://localhost:35305/dart_sdk.js:5061:11)
at Object.assertFailed (http://localhost:35305/dart_sdk.js:4986:15)
at firebase_core_web.FirebaseCoreWeb.new.initializeApp
(http://localhost:35305/packages/firebase_core_web/firebase_core_web.dart.lib.js:243:42)
at initializeApp.next (<anonymous>)
at http://localhost:35305/dart_sdk.js:38640:33
at _RootZone.runUnary (http://localhost:35305/dart_sdk.js:38511:59)
at _FutureListener.thenAwait.handleValue (http://localhost:35305/dart_sdk.js:33713:29)
at handleValueCallback (http://localhost:35305/dart_sdk.js:34265:49)
at Function._propagateToListeners (http://localhost:35305/dart_sdk.js:34303:17)
at _Future.new.[_completeWithValue] (http://localhost:35305/dart_sdk.js:34151:23)
at async._AsyncCallbackEntry.new.callback (http://localhost:35305/dart_sdk.js:34172:35)
at Object._microtaskLoop (http://localhost:35305/dart_sdk.js:38778:13)
at _startMicrotaskLoop (http://localhost:35305/dart_sdk.js:38784:13)
at http://localhost:35305/dart_sdk.js:34519:9
I fixed the issue by the following steps:
Run flutter channel stable
Run flutter upgrade
replace await Firebase.initializeApp() with await Firebase.initializeApp(
options: const FirebaseOptions(
apiKey: "AIzaSyD1C8QaEAxv9QJIm2DDF9N3_b3UZv5o",
appId: "1:270790104828:web:1da6b11a4729a7d79729",
messagingSenderId: "2707901048",
projectId: "todo-app-firebase-ce8",
),
);
replace the values with what you copied to index.html file when initializing web app on firebase console and copying the script code from there.
Restart the app.
Worked for me!
The firebase_options file is missing from your import statement and options is missing from the Firebase.initializeApp method.
Import the firebase_core plugin and firebase_options files.
//lib/main.dart
import 'package:firebase_core/firebase_core.dart';
import 'firebase_options.dart';
Add options parameter to the Firebase.initializeApp method inside the main function.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options:
DefaultFirebaseOptions.currentPlatform);
runApp(const MyApp());
}
Documentation for FlutterFire - initializing-flutterfire
I was facing this issue so I just used this command and it was fixed. please try once before doing anything else
$ flutter upgrade
UPDATED:
Dont waste time on configuring it by yourself, use this CLI https://firebase.flutter.dev/docs/overview/#using-the-flutterfire-cli
Following the steps will lead you to configure it for all the platforms. Its MAGIC!

Initializing Firebase Throws an Error - Flutter

While I was trying to set up Firebase, I learned that I need to initialize Firebase after the last updates. But when I run:
Firebase.initializeApp();
I get an error saying:
_CastError (Null check operator used on a null value)
I tried to remove it, afterwords everything worked fine.
This is the code I am running:
Future<void> main() async {
await Firebase.initializeApp();
runApp(SignIn());
}
According to documents this is how you can initialize firebase in your app:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); //Make sure you imported firebase_core
runApp(SignIn());
);
}
Happy Fluttering :)

not able to use firebase integration in flutter

I am using firebase in flutter application after updating the libraries to the latest version.
Below is the code which was previously used but now I am facing error
CODE
void main() {
FirebaseFirestore.instance.settings(timestampsInSnapshotsEnabled: true).then((_) {
print("Timestamps enabled in snapshots\n");
}, onError: (_) {
print("Error enabling timestamps in snapshots\n");
});
runApp(MyApp());
}
ERROR
error: The expression doesn't evaluate to a function, so it can't be invoked.
when I am implementing the above code I get the error, please help me to resolve this
Here's a code that should fix it.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
You need to Initialize the Firebase instance before runApp(MyApp());
void main() async{
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
//Before running App During load time initialize firebase instance.
runApp(MyApp());
}

Are there negative consequences for calling Firebase initializeApp() twice?

While Firebase.initializeApp() only needs to be called once, are there negative consequences for calling it twice?
Background: I'm troubleshooting a [core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() error and temporarily fixed it by adding await Firebase.initializeApp(); in void main() async in addition to my pre-existing final Future<FirebaseApp> _fbApp = Firebase.initializeApp();
Everything seems to work okay now. I intend to fix it, but if calling Firebase.initializeApp() twice isn't hurting anything, I can stick with my immediate priorities and move forward.
Here's the relevant block of code:
void main() async {
WidgetsFlutterBinding
.ensureInitialized(); // added per https://stackoverflow.com/questions/57689492/flutter-unhandled-exception-servicesbinding-defaultbinarymessenger-was-accesse
await Firebase
.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final Future<FirebaseApp> _fbApp = Firebase
.initializeApp(); // changed from "async { await Firebase.initializeApp();" per official "Getting started with Firebase on Flutter - Firecasts" video at https://youtu.be/EXp0gq9kGxI?t=920
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return StreamProvider<Userrr>.value(
value: AuthService().user,
// above specifies what stream we want to listen to and what data we expect to get back
child: MaterialApp(
Thanks!
UPDATE: I tried all the good advice below and nothing seemed to work. I think my code, an exact duplication from two tutorials (one for getting started with Firebase and another for Firebase auth 101) had one or more gaps because of package updates or other incompatibilities.
I went back to basics and wrote-out by hand and re-implemented every step for installing and setting-up Firebase Core from the official "FlutterFire Overview."
I re-read all the documentation, as suggested below.
I updated all packages, including firebase_auth: “^0.20.0" to firebase_auth: “^0.20.0+1" (the +1 change is to “FIX: package compatibility,” per the changelog).
And then finally, I created a backup of main.dart as old_main.dart, then copy-pasted the exact "Initializing FlutterFire" FurtureBuilder code, then carefully replaced each part of that generic code with my own. Here is each item I replaced:
// replaced "_initialization" with "_fbApp"
// replaced if (snapshot.hasError) ... "return SomethingWentWrong();" with the response from below
// replaced "return Loading();" with CircularProgressIndicator form below
// changed return MyAwesomeApp(); to return MyApp();
// changed "class App extends StatelessWidget" to "class MyApp extends StatelessWidget
// replaced "MyAwesomeApp();" from "if (snapshot.connectionState == ConnectionState.done) { return MyAwesomeApp();" with all the "StreamProvider<Userrr>.value(..." code EXCEPT changed home to "home: Wrapper(),"
It may seem elementary, but for a novice like myself, it was the only way forward. Thankfully it worked!
Here's the full working code excerpt:
void main() {
WidgetsFlutterBinding
.ensureInitialized(); // added by mgav, per https://stackoverflow.com/questions/57689492/flutter-unhandled-exception-servicesbinding-defaultbinarymessenger-was-accesse
// await Firebase.initializeApp(); // added by mgav to test, KNOWING the Firebase is already initialized as a future below in line 25. Was trying to test (temp?) fix for error: “[core/no-app] No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() The relevant error-causing widget was: MyApp file:///Users/mgav/AndroidStudioProjects/brand_new_flutter_app/lib/main.dart:21:10”
runApp(MyApp());
}
// BEGIN Firebase FutureBuilder code pasted from docs at https://firebase.flutter.dev/docs/overview/#initializing-flutterfire (replaces next section of commented-out code)
class MyApp extends StatelessWidget {
// Create the initialization Future outside of `build`:
final Future<FirebaseApp> _fbApp = Firebase.initializeApp();
#override
Widget build(BuildContext context) {
return FutureBuilder(
// Initialize FlutterFire:
future: _fbApp,
builder: (context, snapshot) {
// Check for errors
if (snapshot.hasError) {
print('You have an error! ${snapshot.error.toString()}');
return Text('Something went wrong main.dart around line 48');
}
// Once complete, show your application
if (snapshot.connectionState == ConnectionState.done) {
return StreamProvider<Userrr>.value(
value: AuthService().user,
// above specifies what stream we want to listen to and what data we expect to get back
child: MaterialApp(
title: 'Real Revs and Q&A',
theme: ThemeData(
primarySwatch: Colors.blueGrey,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
routes: {
// '/welcome': (context) => WelcomeScreen(),
'/cleanwritereview': (context) => CleanWriteReviewScreen(),
'/registrationscreen': (context) => RegistrationScreen(),
'/loginscreen': (context) => LoginScreen(),
'/viewreviewsscreen': (context) => ViewReviewsScreen(),
'/homescreen': (context) => Home(),
},
home: Wrapper(),
),
);
}
// Otherwise, show something whilst waiting for initialization to complete
return Center(
child: CircularProgressIndicator(),
);
},
);
}
}
You'll get an error message if you call initializeApp() twice for the same FirebaseApp.
In your case, you can get the app that you've already created with:
final FirebaseApp _fbApp = Firebase.app();
Also see the documentation on FlutterFire, specifically initializing and using FirebaseApp.
To initialise firebase you either do:
main(){
await Firebase.initializeApp(); // don't run the app until firebase is initialized
runApp(MyApp());
}
Or use a FutureBuilder which ensure the future is resolved before running the code inside the builder function.
#override
Widget build(BuildContext context) {
final _fbApp = Firebase.initializeApp();
return FutureBuilder(
future: _fbApp,
builder: (context, snapshot) { // waits until _fbApp is resolved to execute.
....
});
}
You get an error because you don't await _fbApp future.
In your code there is no guarantee AuthService().user is executed after initializeApp has finished. To garantee this you have to wait until initializeApp() is resolved by using await, then or a FutureBuilder.
Add a try catch to understand why the first call in initializeApp is not working.
Firebase initialises its core services only once. there is exactly one FirebaseApp instance by name. When you don't specify the name '[DEFAULT]' is used.
Try doing this:
final app = await Firebase.initializeApp();
final app2 = await Firebase.initializeApp();
print(app == app2); // is true
Please provide more details on your setup:
firebase_auth, firebase_core versions,
Execution plateform (Android, ios or web).
In the last version of fire_auth we use:
FirebaseAuth.instance.authStateChanges // stream to subscribe to the user's current authentication state.

Flutter - how to get current context?

I am using Firebase cloud messaging for notifications, and i want to show a dialog or snackbar once i receive a notification when i am inside the application, my problem is that i am initializing the firebase configuration at the top of my widget tree (Splash screen once the app is starting)
_fireBaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
dynamic data = message['data'];
................ // Adding a snackbar/alertdialog here doesn't work
},
);
obviously if i set a dialog or snackbar it won't show since i need the context of my current page, is there any way to get the current context?
I also tried putting it inside the build widget of my splash screen but still the dialog isn't showing once i am on another page.
#override
Widget build(BuildContext context) {
_fireBaseMessaging.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
dynamic data = message['data'];
if (data['id'] == '1') {
newPro = true;
} else if (data['id'] == '2') {
print("THIS WORKS!!!");
showDialog(
context: context,
builder: (context) => AlertDialog(
content: ListTile(
title: Text("TEST"),
subtitle: Text("TEST"),
),
actions: <Widget>[
FlatButton(
child: Text("OK"),
onPressed: () => Navigator.pop(context),
)
],
));
}
},
);
I had the exact same issue, but I found a brilliant thread on GitHub. Basically, you can create a navigatorKey and pass that in to MaterialApp, and then use that navigatorKey to change route.
See how in this thread: https://github.com/brianegan/flutter_redux/issues/5#issuecomment-361215074
I ended up using Overlay support:
https://pub.dev/packages/overlay_support
It is basically called at the very beginning of my tree just like wrapping providers at the main.dart, it worked like a charm, nothing else worked at all!
Also here is a tutorial that helped me a lot:
https://medium.com/flutter-community/in-app-notifications-in-flutter-9c1e92ea10b3
Because it makes me uncomfortable to have the answer embedded in a link, here is the answer (credit to xqwzts on Github).
Use a GlobalKey you can access from anywhere to navigate:
Create the key:
final GlobalKey<NavigatorState> navigatorKey = new GlobalKey<NavigatorState>();
Pass it to your App:
new MaterialApp(
title: 'MyApp',
onGenerateRoute: generateRoute,
navigatorKey: navigatorKey,
);
Push routes:
navigatorKey.currentState.pushNamed('/someRoute');
An elegant solution to this problem is to use GlobalKey. That'll let you find the current BuildContext and do things with it.
You make a file called eg. global.dart looking like this:
import 'package:flutter/material.dart';
class GlobalVariable {
static final GlobalKey<NavigatorState> navState = GlobalKey<NavigatorState>();
}
You use this in your main() and MaterialApp() like this:
import 'global.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'fcm.dart'; // My Firebase Cloud Messaging code
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'screens/welcome_screen.dart';
void main() {
print('Running main()');
WidgetsFlutterBinding.ensureInitialized();
Firebase.initializeApp();
initializeFcm('', GlobalVariable.navState); // Sending the global key when initializing Firebase Cloud Messaging
FirebaseMessaging.onBackgroundMessage(firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: WelcomeScreen(),
navigatorKey: GlobalVariable.navState, // Putting the global key in the MaterialApp
);
}
}
Then, in the file that handles Firebase Cloud Messaging, which I've named fcm.dart, you'll be able to use the GlobalKey to find the current context and use it, for example like this:
import 'package:blackbox/global.dart';
import 'online_screens/game_hub_screen.dart';
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
void initializeFcm(String token, GlobalKey myGlobalKey) async {
print('Initializing Firebase Cloud Messaging...');
await Firebase.initializeApp();
FirebaseMessaging.onMessageOpenedApp.listen((remoteMsg) {
// Using the currentContext found with GlobalKey:
Navigator.push(GlobalVariable.navState.currentContext, MaterialPageRoute(builder: (context) {
return GameHubScreen();
}));
});
}
do the initializing inside a build method of your first widget in the tree ! which normally it called an App widget and it is StateLess StateFull widget and inside the build method you have access to the BuildContext

Resources