How do the rest of the modules access "Firebase" class, after we initialize using ```Firebase.initializeApp();``` in the entry point? - firebase

So my app is working, but I want to understand what does the initialization actually do?
and why do we have access to a "Firebase" class only after we initialize?
in other words:
How do the rest of the modules access "Firebase" class, after we initialize using Firebase.initializeApp(); in the entry point?
for reference, this is one approach of how we initialize:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp()
);
}
My question is, how is the returned value of the initialized app stored? so that I can access it from any module?

In your case (no application name provided), it initializes a new FirebaseAppPlatform for the default Firebase App and returns it as a Future<FirebaseAppPlatform>. This method should be called before any usage of FlutterFire plugins.
Thanks to that FirebaseApp instance, all the Firebase module can get access to the initialized Firebase Application. Example for Firestore: FirebaseFirestore.instance
Thanks to that initialization using await, you'll also get a synchronous getter for the currentUser.

Related

Can't create unit test with FireStore for flutterfire, throws during init, even with simplest possible test

// ignore_for_file: avoid_print
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
group('core tests - coffee', () {
test('fetch coffees', () async {
await Firebase.initializeApp();
final FirebaseFirestore firestore = FirebaseFirestore.instance;
print('initialized');
expect(firestore, isNotNull);
});
});
}
This is in a test. Oddly, it works in the live app, but not in a simple test case.
Errors during Firebase.initializeApp() with:
Null check operator used on a null value
MethodChannel.binaryMessenger
package:flutter/…/services/platform_channel.dart:121
I don't want a testWidgets. I don't want a mocked FireStore. I want to hit the real database.
I'm on a mac, running a simulator, using VSC, although the simulator shouldn't even be involved.
Firebase plugins wraps around native platform (firebase) SDKs and i think they are not available on when running tests.
I would suggest to use either the emulator suite or fake_cloud_firestore package, or do manual testing by humans (connected with a different firebase instance)

How to test a Flutter application using Firebase?

I am using Flutter and Firebase as my database. I want to do some unit test of my application, but when I start this test :
testWidgets('MyWidget has a title and message', (WidgetTester tester) async {
// Create the widget by telling the tester to build it.
await tester.pumpWidget(LoginPage());
expect(true, true);
});
I have the Exception :
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp()
But Firebase.initializeApp() is called in my main.dart here :
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
And I don't know how to initialize the Firebase app in my test.
Posting this as a community wiki as it's based on #GuilhermeGabanelli's comment.
If you check this flutterfire documentation on how to perform unit tests with Firebase Services you will see that:
The Firebase libraries need to run on an actual device or emulator. So if you want to run unit tests, you'll have to use Fakes instead. A Fake is a library that implements the API of a given Firebase library and simulates its behavior.
...
When initializing your app, instead of passing the actual instance of a Firebase library (e.g. FirebaseFirestore.instance if using Firestore), you pass an instance of a fake (e.g. FakeFirebaseFirestore()). Then the rest of your application will run as if it were talking to Firebase.
Followed by an example with sample code. I believe this is the cause of the issue you are facing and if you change your code to use Fakes this should be fixed.

is it ok to call firebase.initializeApp() in the main [duplicate]

This question already has answers here:
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase
(27 answers)
Closed 2 years ago.
flutterfire recently introduced some changes and one of those is the need to call initializeApp() before using any plugin.
is it ok to call it in the main ? something like this :
void main() async {
await Firebase.initializeApp();
return runApp(App());
}
or maybe like this without async await
void main() {
Firebase.initializeApp();
return runApp(App());
}
i think the first example is more correct but its blocking the execution of the main and i have no idea how much time before the future complete?
The only requirement from Firebase is that you call Firebase.initializeApp() before any other Firebase APIs are called. If that condition isn't met, it will raise an exception explicitly telling you so.
In my code I call it in my main, which is the earliest place I can think if, and it works without problems:
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
...
The initialization of Firebase at this level is pretty much instantaneous, as it's just waiting for the call to the native code to complete, and the native code itself does nothing more then look up the configuration values.
But if that is taking too long for you, you can call it without await. It just means that you may have to deal with that Future<FirebaseApp> later in your code where you access Firebase, typically by wrapping that in a FutureBuilder.

Using Offline Persistence in Firestore in a Flutter App

I'm developing a app that uses Firebase's Firestore to send data to the web. One of the functions of the app is being able to save data in the device while being offline and send it to Firestore when internet connection is restored.
I activated offline persistence but it dosen't work.
DEBUG CONSOLE:
W/OkHttpClientTransport(28536): Failed closing connection
W/OkHttpClientTransport(28536): javax.net.ssl.SSLException: Write error: ssl=0x7f7acfc408: I/O error during system call, Broken pipe
W/OkHttpClientTransport(28536): at com.google.android.gms.org.conscrypt.NativeCrypto.SSL_write(Native Method)
W/OkHttpClientTransport(28536): at com.google.android.gms.org.conscrypt.NativeSsl.write(:com.google.android.gms#14798020#14.7.98 (040406-222931072):4)
How can I activate offline persistence and sync with Firestore when internet is restored?
MY CODE:
Future<Null> sendFirebaseData(var selectedModel) async {
Firestore.instance.enablePersistence(true);
var certID = await getIDCertificado();
var dateTime = new DateTime.now();
var nowHour = new DateFormat('kk:mm:ss').format(dateTime);
Map<String, dynamic> dataHeader = {
'ID': certID,
};
Map<String, dynamic> finalDataMap = {}..addAll(dataGeneral)
..addAll(dataInstrumento)..addAll(dataPadrao)
..addAll(dataAdicional)..addAll(dataHeader);
await Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);}
when you use offline persistence in Firestore, don't use Transactions or await for response.
so, change this :
await Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);
to this:
Firestore.instance.collection('certificados').document((certID.toString()))
.setData(finalDataMap);
When you restore your internet connection your data will be sync automatically, even if you are in background.
Doesn't work when your app is closed.
Context Of Promises & Callbacks when Offline
Why the above code change to remove "await" works.
Reference: Firebase Video - How Do I Enable Offline Support 11:13
Your callback won't be called and your promise won't complete until the document write has been successful on the server. This is why if your UI waits until the write completes to do something, it appears to freeze in "offline mode" even if the write was actually made to the local cache.
It is OK to not use async / await, .then() or callbacks. Firestore will always "act" as if the data change was applied immediately, so you don't need to wait to be working with fresh data.
You only need to use callbacks and promises when you need to be sure that a server write has happened, and you want to block other things from happening until you get that confirmation.
I think the currrent answer is outdated. According to the firebase documentation, offline persistentence is enabled by default for Android and iOS. For the web, it is not.
In flutter, the firestore implementation is based on the underlying OS. So you're safe on mobile apps, but not with flutter for web.
It is enabled by default but still only when you are not using await or transactions, further you can use timeout to stop listening to network connection by firestore after a specific time.
ref.setData(newNote.toMap()).timeout(Duration(seconds: 2),onTimeout:() {
//cancel this call here
print("do something now");
});

Xamarin.Forms - Android Activity with async OnCreate method

I'm running into the questions if it's a problem to mark FormsAppCompatActivity.OnCreate(Bundle bundle) as async? I have to fetch user-specific data from an AWS DynamoDB, and I need to retrieve the user from the Akavache cache before in order to query with the userId. Of course, I could also save the userId to the local settings or serialize the whole user object to be able to retrieve it synchronously.
I also don't expect performance issues during startup because the cache uses SQLite definitely exists. The only problem is that either I await Akavache's GetObject<T>(string key) and therefore, mark everything down to OnCreate as async, or I subscribe to the returned Observable and the following methods will try to query the user data without a valid userId, because the Observable hasn't returned yet.
Since you're using XF for development, the code LoadApplication(new App()); in OnCreate of MainActivity will hook the lifecycle event to App's lifecycle event in PCL.
You didn't post any code, I guess that you place your code for data fetch after LoadApplication(new App());, then as you said it didn't return yet, otherwise the behavior should be different.
I suggest you to call your task in the OnStart() of App in PCL and together use DependencyService to call into your async task for fetching data from PCL.

Resources