I'm trying to develop a Flutter app and run it from Chrome instance. This app uses firebase emulator for the development purpose but somehow when I make changes to any code and when Flutter tries to reload the app, it paused the debug session and point me to the error.
However, it doesn't show any details about the error in the debug console other than this
Restarted application in 774ms.
[GETX] Instance "LoggerService" has been created
[GETX] Instance "LoggerService" has been initialized
[GETX] Instance "AuthService" has been created
[GETX] Instance "AuthService" has been initialized
[2022-04-14T16:06:38.386Z] #firebase/firestore:
ChromeProxyService: Failed to evaluate expression 'FirebaseAuth.instance.useAuthEmulator': InternalError: No frame with index 46.
ChromeProxyService: Failed to evaluate expression 'async': InternalError: No frame with index 46.
ChromeProxyService: Failed to evaluate expression 'FirebaseFirestore.instance.useFirestoreEmulator': InternalError: No frame with index 46.
I tried several things including:
Restarting the emulator suite using 0.0.0.0 and set the app to point out to said host
Changing 10.0.2.2 to my computer's IP address (192.168.x.x)
Using localhost instead of 10.0.2.2 as pointed on the documentation
But this still happening everytime I hit ctrl + S.
I did not modify anything in the emulator script, it was a fresh install. How can I fix this?
It turns out my AuthService implementation is causing this issue, it works when I commented the event listener.
auth_service.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:get/get.dart';
import 'package:prisma_inventa/app/routes/app_pages.dart';
class AuthService extends GetxService {
static AuthService get instance => Get.find();
final _firebaseAuth = FirebaseAuth.instance;
final user = Rx<User?>(null);
bool get authenticated => user() != null;
Future<AuthService> init() async {
user.bindStream(_firebaseAuth.authStateChanges());
ever(user, _redirectIfUnauthenticated);
return this;
}
void _redirectIfUnauthenticated(User? user) {
// print('AUTH STATE CHANGED, user: ${user.toString()}');
// if (user == null) {
// Get.offAllNamed(Routes.AUTH);
// return;
// }
// Get.offAndToNamed(Routes.HOME);
}
...
}
Related
I wanted to user firestore in my unity proyect, so I did as in the documentation. Notice that I also do db = FirebaseFirestore.DefaultInstance;.
I put the firebase starting code in a trial monobehviour in of my scene, in which I wanted to make some database query trials.
Firebase.FirebaseApp app;
void Start() {
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task => {
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available) {
// Create and hold a reference to your FirebaseApp,
// where app is a Firebase.FirebaseApp property of your application class.
app= Firebase.FirebaseApp.DefaultInstance;
Debug.LogError("FirebaseApp succesfully created");
// Set a flag here to indicate whether Firebase is ready to use by your app.
} else {
UnityEngine.Debug.LogError(System.String.Format(
"Could not resolve all Firebase dependencies: {0}", dependencyStatus));
// Firebase Unity SDK is not safe to use here.
}
});
db = FirebaseFirestore.DefaultInstance;
}
Every time I stopped my app and re-played in the editor, unity freezed, and I had to kill the process and restart unity.
Since I commented out the: app= Firebase.FirebaseApp.DefaultInstance;
to: //app= Firebase.FirebaseApp.DefaultInstance; as I only wanted to use the database, everything is going fine.
Am I doing something wrong? Does it make sense that due to some mistake unity hangs after re-play (first play works).
On the other hand I dont understand why in the docs the code advices to store the FirebaseApp in a variable if the FirebaseApp class has got an static instance getter: public static FirebaseApp DefaultInstance { get; }
Thanks for any comment.
I am trying to use the Firebase package with the below line of code.
I really want to know what this line of code actually does?
The official documentation didn't help me much. Can someone explain me, please?
You have to use it, in this way:
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
https://flutter.dev/docs/resources/architectural-overview#architectural-layers
The above image is the architecture layers of Flutter, the WidgetFlutterBinding is used to interact with the Flutter engine. Firebase.initializeApp() needs to call native code to initialize Firebase, and since the plugin needs to use platform channels to call the native code, which is done asynchronously therefore you have to call ensureInitialized() to make sure that you have an instance of the WidgetsBinding.
From the docs:
Returns an instance of the WidgetsBinding, creating and initializing it if necessary. If one is created, it will be a WidgetsFlutterBinding. If one was previously initialized, then it will at least implement WidgetsBinding.
You only need to call this method if you need the binding to be initialized before calling runApp.
From the source code:
#override
Future<FirebaseAppPlatform> initializeApp(
{String name, FirebaseOptions options}) async {
if (name == defaultFirebaseAppName) {
throw noDefaultAppInitialization();
}
// Ensure that core has been initialized on the first usage of
// initializeApp
if (!isCoreInitialized) {
await _initializeCore();
}
// If no name is provided, attempt to get the default Firebase app instance.
// If no instance is available, the user has not set up Firebase correctly for
// their platform.
if (name == null) {
MethodChannelFirebaseApp defaultApp =
appInstances[defaultFirebaseAppName];
if (defaultApp == null) {
throw coreNotInitialized();
}
return appInstances[defaultFirebaseAppName];
}
assert(options != null,
"FirebaseOptions cannot be null when creating a secondary Firebase app.");
// Check whether the app has already been initialized
if (appInstances.containsKey(name)) {
throw duplicateApp(name);
}
_initializeFirebaseAppFromMap(await channel.invokeMapMethod(
'Firebase#initializeApp',
<String, dynamic>{'appName': name, 'options': options.asMap},
));
return appInstances[name];
}
The invokeMapMethod will invoke a method on the above channel with the specified arguments, which will then call the initializeApp() method in the native code,
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_core/firebase_core/android/src/main/java/io/flutter/plugins/firebase/core/FlutterFirebaseCorePlugin.java#L227
There are also different ways to initialize Firebase, which you can check here:
No Firebase App '[DEFAULT]' has been created - call Firebase.initializeApp() in Flutter and Firebase
In the other ways we do not call WidgetsFlutterBinding.ensureInitialized() since the runApp() function calls it internally:
void runApp(Widget app) {
WidgetsFlutterBinding.ensureInitialized()
..scheduleAttachRootWidget(app)
..scheduleWarmUpFrame();
}
https://github.com/flutter/flutter/blob/bbfbf1770c/packages/flutter/lib/src/widgets/binding.dart#L1012
A simple answer is that if Flutter needs to call native code before calling runApp
WidgetsFlutterBinding.ensureInitialized();
makes sure that you have an instance of the WidgetsBinding, which is required to use platform channels to call the native code.
You only need to call this method if you need the binding to be
initialized before calling runApp.
A simple answer, you need to use this line, if your main function uses async keyword because you use await statement inside it.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
SharedPreferences prefs = await SharedPreferences.getInstance(); // just an example
}
Trying to unit test a simple login feature that uses firebase authentication. Receive an ExceptionInInitializerError when trying to initialise Firebase Authentication within the test class
import com.google.firebase.auth.FirebaseAuth;
#RunWith(MockitoJUnitRunner.class)
public class LoginTest {
#Mock
private LoginView view;
#Mock
private FirebaseAuth firebaseAuth;
#Before
public void setUp() {
MockitoAnnotations.initMocks(this);
view = mock(LogIn.class);
firebaseAuth = FirebaseAuth.getInstance(); // Error
}
Error message:
java.lang.ExceptionInInitializerError
at com.google.firebase.FirebaseApp.<clinit>(SourceFile:131)
at com.google.firebase.auth.FirebaseAuth.getInstance(Unknown Source)
Caused by: java.lang.RuntimeException: Method getMainLooper in android.os.Looper not mocked.
You don't want to invoke any part of Firebase during unit testing. The Firebase SDK simply can't be successfully initialized in a unit testing environment running in a JVM. It will be far better if your test mocks a FirebaseAuth instance, and decides what to do when its methods are called. This will involve having it create other mocks of object that it would normally generate. The important thing is to keep Firebase Authentication completely out of your test's code path, so that its not going to generate any errors due to being uninitialized.
I'm quite new to the Microservice world and particularly vertX. I want my verticle to start anyway even there is no database connection available (e.g. database URL missing in configuration). I already managed to do this and my verticle is starting.
The issue now is that I want my verticle to notice when the database connection is available again and connect to it. How can I do this ?
I thought about creating another Verticle "DatabaseVerticle.java" which would send the current DB config on the event bus and my initial verticle would consume this message and check whether the config info is consistent (reply with success) or still missing some data (reply with fail and make the DatabaseVerticle check again).
This might work (and might not) but does not seem to be the optimal solution for me.
I'd be very glad if someone could suggest a better solution. Thank you !
For your use case, I'd recommend to use the vertx-config. In particular, have a look at the Listening to configuration changes section of the Vert.x Config documentation.
You could create a config retriever and set a handler for changes:
ConfigRetrieverOptions options = new ConfigRetrieverOptions()
.setScanPeriod(2000)
.addStore(myConfigStore);
ConfigRetriever retriever = ConfigRetriever.create(vertx, options);
retriever.getConfig(json -> {
// If DB config available, start the DB client
// Otherwise set a "dbStarted" variable to false
});
retriever.listen(change -> {
// If "dbStarted" is still set to false
// Check the config and start the DB client if possible
// Set "dbStarted" to true when done
});
The ideal way would be some other service telling your service about database connection. Either through event bus or HTTP, what you can do is when someone tries to access your database when connection is not made just try to make some DB call and handle the exception, return a boolean as false. Now when you get a message on event bus, consume it and save it in some config pojo. Now when someone tries to access your database, look for config and if available make a connection.
Your consumer:
public void start(){
EventBus eb = vertx.eventBus();
eb.consumer("database", message -> {
config.setConfig(message.body());
});
}
Your db client(Mongo for this eg):
public class MongoService{
private MongoClient client;
public boolean isAvailable = false;
MongoService(Vertx vertx){
if(config().getString("connection")){
client = MongoClient.createShared(vertx, config().getString("connection"));
isAvailable = true;
}
}
}
Not everything in Vertx should be solved by another verticle.
In this case, you can use .periodic()
http://vertx.io/docs/vertx-core/java/#_don_t_call_us_we_ll_call_you
I assume you have some function that checks the DB for the first time.
Let's call it checkDB()
class PeriodicVerticle extends AbstractVerticle {
private Long timerId;
#Override
public void start() {
System.out.println("Started");
// Should be called each time DB goes offline
final Long timerId = this.vertx.setPeriodic(1000, (l) -> {
final boolean result = checkDB();
// Set some variable telling verticle that DB is back online
if (result) {
cancelTimer();
}
});
setTimerId(timerId);
}
private void cancelTimer() {
System.out.println("Cancelling");
getVertx().cancelTimer(this.timerId);
}
private void setTimerId(final Long timerId) {
this.timerId = timerId;
}
}
Here I play a bit with timerId, since we cannot pass it to cancelTimer() right away. But otherwise, it's quite simple.
I'm writing a UWP version of a Windows Phone 8.1 app of mine. This app uses a read-only SQLite database and I'm trying to use Entity Framework 7 on the UWP app to access it.
I can read the database just fine in the app's initial page. However, once I tap one of the rows to navigate to that row's detail page (where I fetch some child records), I get an exception saying there are no database providers configured, even though the code to access the database is the same as in the page that's working. The weirder part is that if I step through the code using the debugger, it works.
I'm also using Template10 on my app, but it does not make a difference whether I put the DB access code in a Template10 ViewModel or straight in the code-behind for the view.
This is the OnConfiguring method for my DbContext class:
protected async override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
var assetsFolder = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("Assets");
optionsBuilder.UseSqlite($"Filename={Path.Combine(assetsFolder.Path, "joinbus.db")}");
}
This is how I access the database on the app's initial page (which always works):
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
{
using (var db = new JoinbusContext())
{
Lines = await db.Lines.ToListAsync();
}
}
This is how I access the database on the detail page (which only works when debugging):
public override async Task OnNavigatedToAsync(object parameter, NavigationMode mode, IDictionary<string, object> state)
{
var line = parameter as Line;
using (var db = new JoinbusContext())
{
var origins = await db.LineOrigins.Where(lo => lo.Line.Id == line.Id)
.Include(lo => lo.Origin).ToListAsync();
LineOrigins = origins;
}
}
The exception thrown is System.InvalidOperationException with the message "No database providers are configured. Configure a database provider by overriding OnConfiguring in your DbContext class or in the AddDbContext method when setting up services."