How to log Firebase Analytics events in Flutter - firebase

I want to log Firebase event in Flutter, but I cannot log any event.
I want to count what times events are done, so when tapping the button, I log the event.
class Onboarding extends StatefulWidget {
Onboarding({Key key, this.analytics, this.observer})
: super(key: key);
final FirebaseAnalytics analytics;
final FirebaseAnalyticsObserver observer;
#override
_OnboardingState createState() => _OnboardingState(analytics, observer);
}
class _OnboardingState extends State<Onboarding> {
_OnboardingState(this.analytics, this.observer);
final FirebaseAnalyticsObserver observer;
final FirebaseAnalytics analytics;
...
Future<void> _sendAnalyticsEvent(FirebaseAnalytics analytics,
FirebaseAnalyticsObserver observer) async {
await analytics.logEvent(
name: 'onboarding'
);
}
Materialbotton(
child: onPressed: () async {
_sendAnalyticsEvent(analytics, observer);
...
}
)
However, if I see Firebase console, I see nothing

Per my understanding, it takes 24 hours in general to see the events logged in firebase console. But to see if the events are indeed being logged, you can use debugView, located under Analytics sidebar in firebase console.
Before you could use debugView, you'll need to configure the setting by enabling respective emulator or simulator on which you're running the app, as explained here
Once you enable it, you should be able to see the events being logged as you perform action in the app.
Hope this helps.

Related

Oauth2 Client & Open ID Connect in Flutter - Authorization Code Grant Type

So most of the tutorials that go over Authorization just use Firebase's Auth, and most of the backend work is taken care of.
I need to create an OAuth Client in Dart/Flutter for Intuit's Quickbooks Online.
My basic understanding is when a user launches my Flutter Web Application, I pop up a screen to initiate the Authorization Code Grant - OAuth.
They sign into Intuit Quickbooks using this pop-up screen, then grant my application permission.
At this point my application should receive an Authorization Code.
I am guessing that I need to store this Authorization Code in my Google Cloud Firestore?
I need to send this Authorization Code back to Intuit & receive 2 things: An Access Token & a Refresh Token.
I think I should also store these in the Cloud Firestore?
But I don't see where cloud functions fit into this picture. Do I use the cloud functions to write/read to the Cloud Firestore?
How do I handle user sessions? I need to address State management as well.
I am starting to understand why many people just use built-in, out-of-the-box functionality of Firebase Auth, because developing a custom OAuth Client in Dart/Flutter is a huge undertaking.
I'm starting to feel confused & lost. I need some suggestions, or organizing because I'm losing sight of what needs to revised, designed or developed.
Main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:html' as html;
import 'dart:convert';w
import 'package:cloud_firestore/cloud_firestore.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(App());
}
class App extends StatefulWidget {
// Create the initialization Future outside of `build`:
#override
_AppState createState() => _AppState();
}
class _AppState extends State<App> {
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
#override
Widget build(BuildContext context) {
return FutureBuilder(
/// Initialize FlutterFire:
future: _initialization,
builder: (context, snapshot) {
if (snapshot.hasError) {
return Text(snapshot.error.toString());
}
/// Once complete, show your application
if (snapshot.connectionState == ConnectionState.done) {
return MyApp();
}
/// Otherwise, show something whilst waiting for initialization to complete
return CircularProgressIndicator();
},
);
}
}
/// Client id provided by Intuit, our production app ClientID
const String clientId = "ABS0R9arxiHjNcAb0rP7OMs8aS1FRiMIINxOkhQimUPewGmQ2H";
const String clientSecret = "";
class MyApp extends StatelessWidget {
/// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Title',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primaryColor: cPrimaryColor,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
late String _token;
late html.WindowBase _popupWin;
Future<String> _validateToken() async {
final response = await http.get(
Uri.parse('https://appcenter.intuit.com/connect/oauth2'),
headers: {'Authorization': 'OAuth $_token'},
);
return (jsonDecode(response.body) as Map<String, dynamic>)['login']
.toString();
}
void _login(String data) {
/// Parse data to extract the token.
final receivedUri = Uri.parse(data);
/// Close the popup window
if (_popupWin != null) {
_popupWin.close();
_popupWin == null; // changed = to ==
}
setState(() => _token = receivedUri.fragment
.split('&')
.firstWhere((e) => e.startsWith('access_token='))
.substring('access_token='.length));
}
#override
void initState() {
super.initState();
/// Listen to message send with `postMessage`.
html.window.onMessage.listen((event) {
/// The event contains the token which means the user is connected.
if (event.data.toString().contains('access_token=')) {
_login(event.data);
}
});
/// You are not connected so open the Intuit authentication page.
WidgetsBinding.instance!.addPostFrameCallback((_) {
final currentUri = Uri.base;
final redirectUri = Uri(
host: currentUri.host,
scheme: currentUri.scheme,
port: currentUri.port,
path: '/static.html',
);
final authUrl = //TODO add state=security_token
'https://appcenter.intuit.com/connect/oauth2?client_id=ABS0R9arxiHjNcAb0rP7OMs8aS1FRiMIINxOkhQimUPewGmQ2H&response_type=code&scope=com.intuit.quickbooks.accounting&redirect_uri=https://google.com/&state=security_token%3D138r5719ru3e1%26url%3Dhttps://qb-payment-app.web.app/';
_popupWin = html.window.open(
authUrl, "Intuit QuickBooks Online Auth", "width=800, height=900, scrollbars=yes");
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('My App Bar'),
)
);
}
}
You asked a lot of questions here. I will address one of the statements:
I am starting to understand why many people just use built-in, out-of-the-box functionality of Firebase Auth, because developing a custom OAuth Client in Dart/Flutter is a huge undertaking.
Actually it's pretty easy to implement custom OAuth client, please see this question where I've implemented my own google sign in service: Flutter web google_sign_in: How to retrieve refreshToken
You can customise this service to work with Quickbooks instead of Google SignIn.

Flutter app error message: No Firebase App

I recently went back to a Flutter project I've not touched for a couple of months and updated a few bits and pieces. Now, when I run the app in my emulator, I get the message:
[core/no-app] No Firebase App '[DEFAULT]' has been created
I added this line of code to initialize it in the app: await Firebase.initializeApp();... but it now doesn't appear to connect to my Firebase, just an empty one that I presume it has created on the fly.
This was my original code, which according to this site is the correct way to initialize the app: https://firebase.flutter.dev/docs/overview/
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
final Future<FirebaseApp> _initialization = Firebase.initializeApp();
#override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark(),
home: FutureBuilder(
future: _initialization,
builder: (context, snapshot) {...
Any idea what I'm doing wrong? The original app on my phone works fine with Firebase, so I presume it's something to do with updating Flutter, Firebase to the latest versions.
Thanks
You should initalize your app in the main function before you run your app, not in the MyApp widget.
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(); // add this line
runApp(MyApp());
}
Ah, it wasn't anything to do with the incorrect Firebase app. I did initialize it in the main function, but in debugging I found that it was hitting an error in reading an object from the database. It was just incorrectly defined. I fixed that and it works now.
Thanks

How to find out if the user is logged in from Firebase Manual Authentication Or Google Authentication Flutter

My question is how to find out if a user who is currently signed in has been authenticated using firebase manual sign in or google sign in?
When I tap into the user property of class FirebaseUser , when I try to access the providerID, it returns "Firebase" even though I am currently signed in through the Google Sign In provider through Firebase. So, is there any way to find out what provider the user has used for registration of the app?
Thanks a lot for your help. Below is the code that I have already written.
Future<FirebaseUser> getFirebaseUser() async {
FirebaseUser user = await _auth.currentUser();
print(user.email);
return user;
}
#override
void initState() {
// TODO: implement initState
super.initState();
startTimer();
}
void startTimer() {
timer = Timer.periodic(Duration(seconds: 2), (timer) {
if (getFirebaseUser() != null) {
// I Need to push to the menu screen while providing the parameters so that it can recognise if the user is from Firebase Manual Auth or google sign in provider.
//print(_user.providerId);
// Navigator.push(context, MaterialPageRoute(
// builder: (context)
// {
// SideBarLayoutStateful(app: MenuScreen(), isFromGoogleSignIn: ,resultUser: _user, profilePicture: _user.photoUrl,);
// }
//));
}
Navigator.pushNamed(context, 'welcome');
timer.cancel();
});
}
I Need to push to the menu screen while providing the parameters so that it can recognise if the user is from Firebase Manual Auth or google sign in provider, which effects the content displayed on the menu screen.
Thanks for your help and I appreciate it!
Is this supposed to happen:
Future<FirebaseUser> getFirebaseUser() async {
FirebaseUser user = await _auth.currentUser();
print(user.email);
print(user.providerId);
return user;
}

Is there a way to determine if a user is signed in via custom firebase account or google account in flutter?

I'm building a flutter app and I have options on my login page to create an account (which gets saved in firebase) or just sign in with Google (which also creates an account on firebase). On other pages, I have a logout button which only logs out of custom firebase account because it's calling this function:
Future<void> signOut() async {
return _firebaseAuth.signOut();
}
I also have this function for google sign out:
Future<void> signOutGoogle() async{
return googleSignIn.signOut();
}
variables declared at top:
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
FirebaseUser user;
Is there a way to determine if the user is signed in via Google or custom firebase? That way I'd be able to determine which function to call when the user clicks Logout.
Thanks in advance
You can access FirebaseUser property called providerData which type is List<UserInfo>. UserInfo has a providerId which is fe. google.com, facebook.com, password (email) or phone.
You can find those values looking up the code.
print(user.providerData[0].providerId) // -> fe. google.com

Wait screen until document added to Firestore subcollection?

I am make random chat app with Flutter and Firestore.
When first user want to chat, I want show wait screen (CircularProgressIndicator). When second user join chat, I want show main chat screen.
But how can I make client app listen continuous for user2 to join? Base on my Firestore schema it must listen for user2 to join /roomUsers subcollection (user2 is add as document name UID). This subcollection already have data for first user so cannot just listen if subcollection hasdata.
#jurrdb has post this code on stackoverflow:
class MyScreen extends StatefulWidget {
#override
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
Widget _screen;
#override
void initState() {
_screen = CircularProgressIndicator();
_doSomeFirebaseChecking();
}
void _doSomeFirebaseChecking() async {
// Add your code that performs checks at Firebase here.
// Then use setState to update the widget to a screen of choice.
setState(() {
});
}
}
I am try use this model but no know how to make client app check Firestore subcollection continuous.
I have try get documents from /roomUsers subcollection and check if documentSnapshot.length > 1 but this only run once so not update when user2 join chatroom.
How can solve this? I am try streambuilder/futurebuilder but no solve.
Thanks!
Update: Here how I write "user document" into the roomUsers subcollection:
roomUsersRef = Firestore.instance.collection(‘chats').document(docID).collection(‘roomUsers').document(uid);
await roomUsersRef.setData({
‘user2UID': uid,
});

Resources