I have added google sign in button to my login page. but when I CLICK IT its not working at all. I REFER this video for the implementation. how to resolve this. I'm struggling to find the error. appreciate your help on this. all the firebase parts are done according to the video instructions. there's no error to displaying. just button not working.
//google_sign_in.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleSignInProvider extends ChangeNotifier{
final googleSignIn =GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin()async{
final googleUser= await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth =await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
notifyListeners(); //to update UI
}
}
//main.dart
import 'dart:io';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:lala_live/provider/google_sign_in.dart';
import 'package:lala_live/screens/login.dart';
import 'package:lala_live/screens/splashscreen.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:provider/provider.dart';
const bool USE_EMULATOR = false;
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
if (USE_EMULATOR) {
_connectToFirebaseEmulator();
}
runApp(MyApp());
}
Future _connectToFirebaseEmulator() async {
final fireStorePort = "8080";
final authPort = 9099;
final localhost = Platform.isAndroid ? '10.0.2.2' : 'localhost';
FirebaseFirestore.instance.settings = Settings(
host: "$localhost:$fireStorePort",
sslEnabled: false,
persistenceEnabled: false,
);
await FirebaseAuth.instance.useAuthEmulator('http://$localhost:', authPort);
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) => ChangeNotifierProvider(
create: (context)=> GoogleSignInProvider(),
child: MaterialApp(
debugShowCheckedModeBanner: false,
theme: ThemeData(fontFamily: 'Quicksand'),
home: FutureBuilder(
future: Future.delayed(Duration(seconds: 3)),
builder: (ctx, timer) => timer.connectionState == ConnectionState.done
? Login() //Screen to navigate to once the splashScreen is done.
: SplashScreen()),
),
);
}
//login.dart
Center(
child: SocialButton(
logo: 'asset/images/googleicon.png',
height: widgetheight,
width: width / 4,
text: 'Google',
onPressed: () {
final provider = Provider.of<GoogleSignInProvider>(context,listen:false);
provider.googleLogin();
},
color: containergrey)),
],
),
Try this,
maybe u forgot to async await
onPressed: () async {
final provider =
Provider.of<GoogleSignInProvider>(context, listen: false);
await provider.googleLogin();
},
googleSignIn.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
class GoogleSignInProvider extends ChangeNotifier {
final googleSignIn = GoogleSignIn();
GoogleSignInAccount? _user;
GoogleSignInAccount get user => _user!;
Future googleLogin() async {
try {
final googleUser = await googleSignIn.signIn();
if (googleUser == null) return;
_user = googleUser;
final googleAuth = await googleUser.authentication;
final credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
await FirebaseAuth.instance.signInWithCredential(credential);
} catch (e) {}
notifyListeners();
}
Future logout() async {
await googleSignIn.disconnect();
FirebaseAuth.instance.signOut();
}
}
**SignInButton**
import 'package:flutter/material.dart';
class ButtonWidget extends StatelessWidget {
final String text;
final VoidCallback onClicked;
const ButtonWidget({
Key? key,
required this.text,
required this.onClicked,
}) : super(key: key);
#override
Widget build(BuildContext context) => ElevatedButton(
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
onPrimary: Colors.white,
padding: EdgeInsets.symmetric(horizontal: 32, vertical: 12),
),
child: Text(text),
onPressed: onClicked,
);
}
Widget buildUpgradeButton() => ButtonWidget(
text: Click to SignIn,
onClicked: () {
final provider =
Provider.of<GoogleSignInProvider>(context, listen: false);
provider.googleLogin();
});
Related
I am learning flutter and I am stuck on a problem .
I created a little app which allows me to auth via Gmail on firebase.
As soon as I get logged in the email and a generated name will be added to "collection: users"
now I would like to add some more information about the user to the "collection: profilepage".
on my main.dart I ask: is user logged in, then
return(UserNameChooser).
In UserNameChooser I have 2 textfields which will be written into "collection: profilepage".
Now my Question: How can I get the UserID from the "collection: users" and add
the ID to the "collection: profilepage".
Or how do you manage profilepage auth connection?
I tried so many ways but couldn't get it done...
My Main.dart
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:signal/services/auth.dart';
// import 'package:signal/views/home.dart';
import 'package:signal/views/usernamechooser.dart';
import 'views/signin.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
debugShowCheckedModeBanner: false,
theme: ThemeData(
primarySwatch: Colors.lightBlue,
),
home: FutureBuilder(
future: AuthMethods().getCurrentUser(),
builder: (context, AsyncSnapshot<dynamic> snapshot) {
if(snapshot.hasData){
return UserNameChooser();
}
else{
return SignIn();
}
}
),
);
}
}
My auth.dart
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
import 'package:signal/services/database.dart';
import 'package:signal/views/home.dart';
class AuthMethods{
final FirebaseAuth auth = FirebaseAuth.instance;
getCurrentUser() async {
return await auth.currentUser;
}
signInWithGoogle(BuildContext context) async {
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
final GoogleSignInAccount googleSignInAccount =
await _googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await
googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.credential(
idToken: googleSignInAuthentication.idToken,
accessToken: googleSignInAuthentication.accessToken
);
UserCredential result =
await _firebaseAuth.signInWithCredential(credential);
User userDetails = result.user;
if(result != null){
SharedPreferenceHelper().saveUserEmail(userDetails.email);
SharedPreferenceHelper().saveUserId(userDetails.uid);
SharedPreferenceHelper()
.saveUserName(userDetails.email.replaceAll("#gmail.com", ""));
SharedPreferenceHelper().saveDisplayName(userDetails.displayName);
SharedPreferenceHelper().saveUserProfileUrl(userDetails.photoURL);
Map<String, dynamic> userInfoMap = {
"email": userDetails.email,
"username": userDetails.email.replaceAll("#gmail.com", ""),
"name": userDetails.displayName,
"imgUrl": userDetails.photoURL
};
DatabaseMethods()
.addUserInfoToDB(userDetails.uid, userInfoMap)
.then((value) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => Home()));
});
}
}
Future signOut() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.clear();
await auth.signOut();
}
}
My Database.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
class DatabaseMethods{
Future addUserInfoToDB(String userId, Map<String, dynamic>userInfoMap)
async {
return FirebaseFirestore.instance
.collection("users")
.doc(userId)
.set(userInfoMap);
}
Future<Stream<QuerySnapshot>> getUserByUserName(String username) async{
return FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.snapshots();
}
Future addMessage(String chatRoomId, String messageId, Map messageInfoMap) async {
return FirebaseFirestore.instance
.collection ("chatrooms")
.doc(chatRoomId)
.collection("chats")
.doc(messageId)
.set(messageInfoMap);
}
updateLastMessageSend(String chatRoomId, Map lastMessageInfoMap){
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.update(lastMessageInfoMap);
}
createChatRoom(String chatRoomId, Map chatRoomInfoMap) async{
final snapShot = await FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.get();
if(snapShot.exists){
//chatroom already exists
return true;
}else{
//chatroom does not exists
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.set(chatRoomInfoMap);
}
}
Future<Stream<QuerySnapshot>> getChatRoomMessages(chatRoomId) async {
return FirebaseFirestore.instance
.collection("chatrooms")
.doc(chatRoomId)
.collection("chats")
.orderBy("ts", descending: true)
.snapshots();
}
Future<Stream<QuerySnapshot>> getChatRooms() async {
String myUsername = await SharedPreferenceHelper().getUserName();
return FirebaseFirestore.instance
.collection("chatrooms")
.orderBy("lastMessageSendTs", descending: true)
.where("users",arrayContains: myUsername)
.snapshots();
}
Future<QuerySnapshot> getUserInfo(String username) async {
return await FirebaseFirestore.instance
.collection("users")
.where("username", isEqualTo: username)
.get();
}
}
my usernamechooser.dart
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:signal/views/home.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:signal/helperfunctions/sharedpref_helper.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(
MaterialApp(home: UserNameChooser(),));
}
class UserNameChooser extends StatefulWidget{
#override
_UserNameChooserState createState() => _UserNameChooserState();
}
class _UserNameChooserState extends State<UserNameChooser> {
String userNameKey, getUserId;
TextEditingController chosenusername = new TextEditingController();
TextEditingController chosenage = new TextEditingController();
Future<String> getUserName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userNameKey);
}
#override
Widget build(BuildContext context){
return Scaffold(
appBar: AppBar(title: Text("usernamechooser"),
),
body: Container(
padding: EdgeInsets.all(40.0),
child: Center(child: Column(
children: [
Container(
),
TextFormField(
controller: chosenusername,
decoration: InputDecoration(
hintText: "Username"
),
),
SizedBox(
height: 10.0,
),
TextFormField(
controller: chosenage,
decoration: InputDecoration(
hintText: "alter"
),
),
SizedBox(
height: 10.0,
),
TextButton(
onPressed: (){
Map <String,dynamic> data = {"choseusername": chosenusername.text,"chosenage": chosenage.text};
FirebaseFirestore.instance.collection("userprofile").add(data);
Navigator.push(context, MaterialPageRoute(builder: (context) => Home(),));
},
child: Text("Submit"),
),
]
),
)
)
);
}
}
and last but not least my shared_preferences.dart
import 'package:shared_preferences/shared_preferences.dart';
class SharedPreferenceHelper {
static String userIdKey = "USERKEY";
static String userNameKey = "USERNAMEKEY";
static String displayNameKey = "USERDISPLAYNAMEKEY";
static String userEmailKey = "USEREMAILKEY";
static String userProfilePicKey = "USERPROFILEPICKEY";
//save data
Future<bool> saveUserName(String getUserName) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userNameKey, getUserName);
}
Future<bool> saveUserEmail(String getUseremail) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userEmailKey, getUseremail);
}
Future<bool> saveUserId(String getUserId) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userIdKey, getUserId);
}
Future<bool> saveDisplayName(String getDisplayName) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(displayNameKey, getDisplayName);
}
Future<bool> saveUserProfileUrl(String getUserProfile) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.setString(userProfilePicKey, getUserProfile);
}
// get data
Future<String> getUserName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userNameKey);
}
Future<String> getUserEmail() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userEmailKey);
}
Future<String> getUserId() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userIdKey);
}
Future<String> getDisplayName() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(displayNameKey);
}
Future<String> getUserProfileUrl() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
return prefs.getString(userProfilePicKey);
}
}
Problem Solved ...
here how i did it :
I loaded the currentUser.uid into the var useruid ..
var useruid = FirebaseAuth.instance.currentUser.uid;
and sent this uid to the user db :)
Unhandled Exception: type 'Future' is not a subtype of type 'QuerySnapshot' in flutter googlesignin using firebase.Got problem with this line: final QuerySnapshot result=FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
it is used for sign inwith google using firebase
import 'package:shared_preferences/shared_preferences.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'home.dart';
import 'package:flutter_auth_buttons/flutter_auth_buttons.dart';
import 'package:flutter_signin_button/flutter_signin_button.dart';
class Login extends StatefulWidget {
#override
_LoginState createState() => _LoginState();
}
class _LoginState extends State<Login> {
final FirebaseAuth firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = new GoogleSignIn();
SharedPreferences preferences;
bool loading = false;
bool isLogedIn = false;
#override
void initState() {
super.initState();
isSignedIn();
}
void isSignedIn() async {
setState(() {
loading = true;
});
preferences = await SharedPreferences.getInstance();
isLogedIn = await googleSignIn.isSignedIn();
if (isLogedIn) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (context) => HomePage()));
}
setState(() {
loading = false;
});
}
Future<Null> handleSignIn() async{
preferences = await SharedPreferences.getInstance();
final GoogleSignInAccount googleUser = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication = await googleUser.authentication;
AuthCredential credential = GoogleAuthProvider.credential(idToken: googleSignInAuthentication.idToken, accessToken: googleSignInAuthentication.accessToken);
//final UserCredential userCredential = await firebaseAuth.signInWithCredential(credential);
//final User user = userCredential.user;
User user = (await firebaseAuth.signInWithCredential(credential)).user;```
if(user!=null)
{
final QuerySnapshot result=FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
List<DocumentSnapshot> documents= result.docs;
if(documents.length==0)
{
//insert user to collection
FirebaseFirestore.instance.collection('users').doc(user.uid).set({
"id":user.uid,
"username":user.displayName,
"photourl":user.photoURL});
await preferences.setString("id", user.uid);
await preferences.setString("username", user.displayName);
await preferences.setString("photourl", user.photoURL);
}
else{
// await preferences.setString("id",documents[0].data['id']);
//await preferences.setString("photourl",documents[0]['photourl']);
//await preferences.setString("username",documents[0]['username']);
await preferences.setString("id", documents[0].data()['id']);
await preferences.setString("username", documents[0].data()['username']);
await preferences.setString("photourl", documents[0].data()['photoUrl']);
}
Fluttertoast.showToast(msg: "Login Was successful");
setState(() {
loading=false;
});
Navigator.push(context, MaterialPageRoute(builder: (context)=>HomePage()));
}else{
Fluttertoast.showToast(msg: "Login Failed");
setState(() {
loading=false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children:<Widget> [
Center(
child: FlatButton(
color: Colors.red,
onPressed: (){handleSignIn();},child: Text("sigin",style: TextStyle(color: Colors.white),),
)
),
Visibility(
visible: loading ?? true,
child: Center(
child: Container(
alignment: Alignment.center,
color: Colors.white.withOpacity(0.8),
child: CircularProgressIndicator(
valueColor: AlwaysStoppedAnimation<Color>(Colors.red),
),
)
)
)
],
),
);
}
}```
get() returns a Future<QuerySnapshot>, therefore you need to do the following:
final QuerySnapshot result= await FirebaseFirestore.instance.collection('users').where('id',isEqualTo: user.uid).get();
https://dart.dev/codelabs/async-await
When i try to sign in with my google account in the app i get this error in the console
And the app shut down , i used the sign in method in firebase- google
And this is the code that i used for the sign up page
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LoginButton(), // <-- Built with StreamBuilder
UserProfile()
],
)));
}
}
class UserProfile extends StatefulWidget {
#override
UserProfileState createState() => UserProfileState();
}
class UserProfileState extends State<UserProfile> {
Map<String, dynamic> _profile;
bool _loading = false;
#override
initState() {
super.initState();
// Subscriptions are created here
authService.profile.listen((state) => setState(() => _profile = state));
authService.loading.listen((state) => setState(() => _loading = state));
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(padding: EdgeInsets.all(20), child: Text(_profile.toString())),
Text(_loading.toString())
]);
}
}
class LoginButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: authService.user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return MaterialButton(
onPressed: () => authService.signOut(),
color: Colors.red,
textColor: Colors.white,
child: Text('Signout'),
);
} else {
return MaterialButton(
onPressed: () => authService.testSignInWithGoogle(),
color: Colors.white,
textColor: Colors.black,
child: Text('Login with Google'),
);
}
});
}
}
and this for authentification
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:rxdart/rxdart.dart';
class AuthService {
// Dependencies
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final Firestore _db = Firestore.instance;
// Shared State for Widgets
Observable<FirebaseUser> user; // firebase user
Observable<Map<String, dynamic>> profile; // custom user data in Firestore
PublishSubject loading = PublishSubject();
// constructor
AuthService() {
user = Observable(_auth.onAuthStateChanged);
profile = user.switchMap((FirebaseUser u) {
if (u != null) {
return _db
.collection('users')
.document(u.uid)
.snapshots()
.map((snap) => snap.data);
} else {
return Observable.just({});
}
});
}
Future<String> testSignInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
assert(user.email != null);
assert(user.displayName != null);
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
Future<String> signOut() async {
try {
await _auth.signOut();
return 'SignOut';
} catch (e) {
return e.toString();
}
}
}
// TODO refactor global to InheritedWidget
final AuthService authService = AuthService();
and this is what i have in pubspec.yml:
dependencies:
flutter:
sdk: flutter
firebase_core: ^0.4.5
firebase_analytics: ^5.0.15
cloud_firestore: ^0.13.6
firebase_auth: ^0.16.1
google_sign_in: ^4.5.1
rxdart: ^0.22.6
cupertino_icons: ^0.1.3
i am trying to implement the sign in button from firebase with google , but all the tutorials are old. I have an error at :onPressed: () => authService.googleSignIn()
Here is the code that i used for authentification:
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:rxdart/rxdart.dart';
class AuthService {
// Dependencies
final GoogleSignIn _googleSignIn = GoogleSignIn();
final FirebaseAuth _auth = FirebaseAuth.instance;
final Firestore _db = Firestore.instance;
// Shared State for Widgets
Observable<FirebaseUser> user; // firebase user
Observable<Map<String, dynamic>> profile; // custom user data in Firestore
PublishSubject loading = PublishSubject();
// constructor
AuthService() {
user = Observable(_auth.onAuthStateChanged);
profile = user.switchMap((FirebaseUser u) {
if (u != null) {
return _db
.collection('users')
.document(u.uid)
.snapshots()
.map((snap) => snap.data);
} else {
return Observable.just({});
}
});
}
Future<String> _testSignInWithGoogle() async {
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
final FirebaseUser user =
(await _auth.signInWithCredential(credential)).user;
assert(user.email != null);
assert(user.displayName != null);
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
return 'signInWithGoogle succeeded: $user';
}
Future<String> signOut() async {
try {
await _auth.signOut();
return 'SignOut';
} catch (e) {
return e.toString();
}
}
}
// TODO refactor global to InheritedWidget
final AuthService authService = AuthService();
and this is for the login page
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginScreen> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
LoginButton(), // <-- Built with StreamBuilder
UserProfile()
],
)));
}
}
class UserProfile extends StatefulWidget {
#override
UserProfileState createState() => UserProfileState();
}
class UserProfileState extends State<UserProfile> {
Map<String, dynamic> _profile;
bool _loading = false;
#override
initState() {
super.initState();
// Subscriptions are created here
authService.profile.listen((state) => setState(() => _profile = state));
authService.loading.listen((state) => setState(() => _loading = state));
}
#override
Widget build(BuildContext context) {
return Column(children: <Widget>[
Container(padding: EdgeInsets.all(20), child: Text(_profile.toString())),
Text(_loading.toString())
]);
}
}
class LoginButton extends StatelessWidget {
#override
Widget build(BuildContext context) {
return StreamBuilder(
stream: authService.user,
builder: (context, snapshot) {
if (snapshot.hasData) {
return MaterialButton(
onPressed: () => authService.signOut(),
color: Colors.red,
textColor: Colors.white,
child: Text('Signout'),
);
} else {
return MaterialButton(
onPressed: () => authService.googleSignIn(),
color: Colors.white,
textColor: Colors.black,
child: Text('Login with Google'),
);
}
});
}
}
I thing the AuthService.googleSignIn() in async method
so the cant assign to sync method
onPressed: () => authService.googleSignIn()
use like this
onPressed: () { authService.googleSignIn() }
This is the problem: notification is received by the app both with app in foreground or background (or terminated) but the snackbar for notification when the app is used doesn't work. I'm new in flutter so maybe I did some huge mistake.
I am showing my code below. If you want more information just ask and thanks for the help!
// Import Package
import 'dart:io';
import 'package:app_gap_go/pages/admin/modifySingleMeeting.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
// import 'package:flutter/rendering.dart';
// Import Other Package
import 'package:provider/provider.dart';
// Import Pagine
import './pages/wrapper.dart';
import './pages/setting/settings.dart';
import './pages/riunioni/riunioni.dart';
import './pages/auth/register.dart';
import './pages/admin/pannelloAdmin.dart';
import './pages/admin/modifyMeetings.dart';
// Import Utility
import 'utility/themeData.dart';
// Import Services
import './services/authService.dart';
// Import Models
import './models/user.dart';
void main() {
// debugPaintSizeEnabled = true;
// debugPaintBaselinesEnabled = true;
// debugPaintPointersEnabled = true;
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
final FirebaseMessaging _fcm = new FirebaseMessaging();
final Firestore _db = Firestore.instance;
final FirebaseAuth _auth = FirebaseAuth.instance;
GlobalKey<ScaffoldState> scaffoldState = new GlobalKey<ScaffoldState>();
// Request and save token
Future _saveDeviceToken() async {
String fcmToken = await _fcm.getToken();
FirebaseUser user = await _auth.currentUser();
if (fcmToken != null) {
var tokenRef = _db
.collection('utenti')
.document(user.uid)
.collection('tokens')
.document(fcmToken);
await tokenRef.setData({
'token': fcmToken,
'createdAt': FieldValue.serverTimestamp(),
'platform': Platform.operatingSystem,
});
}
}
#override
void initState() {
_fcm.configure(
onMessage: (Map<String, dynamic> message) async {
print("onMessage: $message");
final snackbar = SnackBar(
content: Text(message['notification']['title']),
action: SnackBarAction(
label: 'Go',
onPressed: () => null,
),
);
scaffoldState.currentState.showSnackBar(snackbar);
},
onResume: (Map<String, dynamic> message) async {
print("onResume: $message");
},
onLaunch: (Map<String, dynamic> message) async {
print("onLaunch: $message");
},
);
if(Platform.isIOS) {
_fcm.onIosSettingsRegistered.listen((data) {
_saveDeviceToken();
});
_fcm.requestNotificationPermissions(IosNotificationSettings());
} else {
_saveDeviceToken();
}
_fcm.subscribeToTopic('meetings');
super.initState();
}
#override
Widget build(BuildContext context) {
return StreamProvider<User>.value(
key: scaffoldState,
value: AuthService().user,
child: MaterialApp(
title: "GapGo",
theme: themeApp,
routes: {
'/': (BuildContext context) => Wrapper(),
'/register': (BuildContext context) => Register(),
'/settings': (BuildContext context) => Settings(),
'/riunioni': (BuildContext context) => Riunioni(),
'/adminPanel': (BuildContext context) => PannelloAdmin(),
'/modifyMeetings': (BuildContext context) => ModifyMeetings(),
'/modifySingleMeeting': (BuildContext context) =>
ModifySingleMeeting(),
},
),
);
}
// End State
}
I literally faced the same issue, i neither could use a dialog nor a SnackBar, the problem is actually from not having the current context of your navigator route, here is my solution.
Change this:
SnackBarAction(
label: 'Go',
onPressed: () => null,
),
Into this:
SnackBarAction(
label: 'Go',
onPressed: () => print("pressed"),
),
According to the docs:
The label and onPressed arguments must be non-null.
https://api.flutter.dev/flutter/material/SnackBarAction/SnackBarAction.html
The problem is most likely due to the fact you're calling the scaffoldState key inside the StreamProvider.value widget but your routes are outside that widget. MaterialApp widget should be inside and incapsulate the Scaffold widget.
I have similar case in here the SnackBarAction show error because of const
**const** SnackBar(
content: Text('Added item to the Cart '),
duration: Duration(seconds: 2),
action: SnackBarAction(
label: 'UNDO',
onPressed: () {},
));
},
SHOUD BE LIKE THIS
SnackBar(
content: Text('Added item to the Cart '),
duration: Duration(seconds: 2),
action: SnackBarAction(
label: 'UNDO',
onPressed: () {},
));
},