why firebase auth doesn't work on my new samsung phone? - android

i am beginner in flutter .
i have a probleme firebase auth with email work on all phones and emulators but on my new samsung phone it doesn't .
here is the error message
/FirebaseAuth( 2571): [FirebaseAuth:] Preparing to create service connection to fallback implementation
W/System ( 2571): Ignoring header X-Firebase-Locale because its value was null.
2
I/System.out( 2571): (HTTPLog)-Static: isSBSettingEnabled false
D/InputMethodManager( 2571): HSIFW - flag : 0
here is my auth screen where the user sign up or login.
import 'package:flutter/material.dart';
import 'package:m51/common/constants.dart';
import 'package:m51/common/loading.dart';
import 'package:m51/services/authentication.dart';
class AuthenticateScreen extends StatefulWidget {
#override
_AuthenticateScreenState createState() => _AuthenticateScreenState();
}
class _AuthenticateScreenState extends State<AuthenticateScreen> {
final AuthenticationService _auth = AuthenticationService();
final _formKey = GlobalKey<FormState>();
String error = '';
bool loading = false;
final emailController = TextEditingController();
final nameController = TextEditingController();
final passwordController = TextEditingController();
bool showSignIn = true;
#override
void dispose() {
nameController.dispose();
emailController.dispose();
passwordController.dispose();
super.dispose();
}
void toggleView() {
setState(() {
_formKey.currentState?.reset();
error = '';
emailController.text = '';
nameController.text = '';
passwordController.text = '';
showSignIn = !showSignIn;
});
}
#override
Widget build(BuildContext context) {
return loading
? Loading()
: Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.blueGrey,
elevation: 0.0,
title: Text(showSignIn ? 'Sign in to Water Social' : 'Register to Water Social'),
actions: <Widget>[
TextButton.icon(
icon: Icon(
Icons.person,
color: Colors.white,
),
label: Text(showSignIn ? "Register" : 'Sign In',
style: TextStyle(color: Colors.white)),
onPressed: () => toggleView(),
),
],
),
body: Container(
padding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 30.0),
child: Form(
key: _formKey,
child: Column(
children: [
!showSignIn
? TextFormField(
controller: nameController,
decoration: textInputDecoration.copyWith(hintText: 'name'),
validator: (value) =>
value == null || value.isEmpty ? "Enter a name" : null,
)
: Container(),
!showSignIn ? SizedBox(height: 10.0) : Container(),
TextFormField(
controller: emailController,
decoration: textInputDecoration.copyWith(hintText: 'email'),
validator: (value) =>
value == null || value.isEmpty ? "Enter an email" : null,
),
SizedBox(height: 10.0),
TextFormField(
controller: passwordController,
decoration: textInputDecoration.copyWith(hintText: 'password'),
obscureText: true,
validator: (value) => value != null && value.length < 6
? "Enter a password with at least 6 characters"
: null,
),
SizedBox(height: 10.0),
ElevatedButton(
child: Text(
showSignIn ? "Sign In" : "Register",
style: TextStyle(color: Colors.white),
),
onPressed: () async {
if (_formKey.currentState?.validate() == true) {
setState(() => loading = true);
var password = passwordController.value.text;
var email = emailController.value.text;
var name = nameController.value.text;
dynamic result = showSignIn
? await _auth.signInWithEmailAndPassword(email, password)
: await _auth.registerWithEmailAndPassword(name, email, password);
if (result == null) {
print ('Please supply a valid email');
}
}
}
),
SizedBox(height: 10.0),
Text(
error,
style: TextStyle(color: Colors.red, fontSize: 15.0),
)
],
),
),
),
);
}
}
i also have that message
I/flutter ( 4866): [firebase_auth/invalid-email] The email address is
badly formatted.
the service code
import 'package:firebase_auth/firebase_auth.dart';
import 'package:urjob/models/user.dart';
import 'package:urjob/services/database.dart';
class AuthenticationService {
final FirebaseAuth _auth = FirebaseAuth.instance;
AppUser? _userFromFirebaseUser(User? user) {
return user != null ? AppUser(user.uid) : null;
}
Stream<AppUser?> get user {
return _auth.authStateChanges().map(_userFromFirebaseUser);
}
Future signInWithEmailAndPassword(String email, String password) async {
try {
UserCredential result =
await _auth.signInWithEmailAndPassword(email: email, password: password);
User? user = result.user;
return _userFromFirebaseUser(user);
} catch (exception) {
print(exception.toString());
return null;
}
}
Future registerWithEmailAndPassword(String name, String email, String password, String profilepic) async {
try {
UserCredential result =
await _auth.createUserWithEmailAndPassword(email: email, password: password);
User? user = result.user;
if (user == null) {
throw Exception("No user found");
} else {
await DatabaseService(user.uid).saveUser(name,profilepic,email);
return _userFromFirebaseUser(user);
}
} catch (exception) {
print(exception.toString());
return null;
}
}
Future signOut() async {
try {
return await _auth.signOut();
} catch (exception) {
print(exception.toString());
return null;
}
}
Future sendreset(String email) async {
try {
return await _auth.sendPasswordResetEmail(email: email);
} catch (exception) {
print(exception.toString());
return null;
}
}
}
Thank you for your help

i found the solution
we need in ma case to add .trim() functions to erase white spaces
https://github.com/FirebaseExtended/flutterfire/issues/1760

Trim text gotten from textfields.
emailController.text.trim(),
passwordController.text.trim()

Related

Flutter: TCP socket connection fails on real device

I'm posting this even though I already solved the issue, because I spent more than an hour trying to figure out what was causing it, and might help someone else.
I have a simple application that connects to a server through a TCP socket. It works fine inside the debugger with the device emulator, but when I deploy it on a real device it fails to connect immediately.
Further investigations led me to finding out that the socket was actually throwing the following exception:
SocketException: Connection failed (OS Error: Operation not permitted, errno = 1), address = 192.168.1.46, port = 40001
Code sample
Connect button opens a socket on _host:_port
Send Radar Distance button sends a message formatted like {"distance": _distance, "angle": _angle} on the socket.
Status and Message fields show info about the socket status and eventually useful infos.
main.dart
import 'package:flutter/material.dart';
import 'views/view_test.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: const ViewTest(),
);
}
}
views/view_test.dart
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
const List<String> materialTypes = <String>['PLASTIC', 'GLASS'];
class ViewTest extends StatefulWidget {
const ViewTest({Key? key}) : super(key: key);
#override
State<ViewTest> createState() => _ViewTestState();
}
class _ViewTestState extends State<ViewTest> {
String _distance = "";
String _angle = "";
String _status = "";
String _message = "";
Socket? _socket;
final String _host = "192.168.1.46";
final int _port = 4001;
Future<void> _sendMessage(String message) async {
print("Sent message $message");
_socket!.write(message);
await Future.delayed(const Duration(seconds: 1));
}
void _connect(String ip, int port) async {
Socket? sock;
try {
sock =
await Socket.connect(ip, port, timeout: const Duration(seconds: 3));
_socket = sock;
setState(() {
_status = "Connected to $ip:$port.";
_message = "";
});
// listen for responses from the server
_socket!.listen(
// handle data from the server
(Uint8List data) {
final serverResponse = String.fromCharCodes(data);
setState(() {
_message = serverResponse;
});
print(serverResponse);
},
// handle errors
onError: (error) {
setState(() {
_status = "Disconnected.";
_message = "Error: $error";
});
print("Error: $error");
_socket!.destroy();
_socket = null;
},
// handle server ending connection
onDone: () {
setState(() {
_status = "Disconnected.";
_message = 'Server left.';
});
print('Server left.');
_socket!.destroy();
_socket = null;
},
);
} catch (e) {
setState(() {
_status = "Connection failed.";
_message = e.toString();
});
print("Error: ${e.toString()}");
}
}
void _disconnect() {
if (_socket != null) _socket!.destroy();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Center(child: Text("Radar Test")),
),
body: Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 50.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ElevatedButton(
onPressed: () {
setState(() {
_status = "";
_message = "";
});
_disconnect();
_connect(_host, _port);
},
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
_socket == null ? 'Connect' : 'Reconnect',
style: const TextStyle(fontSize: 22.0),
),
),
),
const SizedBox(height: 50.0),
TextField(
onChanged: (text) {
_distance = text;
},
keyboardType:
const TextInputType.numberWithOptions(decimal: false),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r'[0-9]+'), // this regex allows only decimal numbers
)
],
decoration: const InputDecoration(
hintText: '100',
border: UnderlineInputBorder(),
labelText: 'Distance',
),
),
TextField(
onChanged: (text) {
_angle = text;
},
keyboardType:
const TextInputType.numberWithOptions(decimal: false),
inputFormatters: <TextInputFormatter>[
FilteringTextInputFormatter.allow(
RegExp(r'[0-9]+'), // this regex allows only decimal numbers
)
],
decoration: const InputDecoration(
hintText: '90',
border: UnderlineInputBorder(),
labelText: 'Angle',
),
),
const SizedBox(height: 50.0),
Text("Status: $_status"),
Text("Message: $_message"),
],
),
),
),
floatingActionButton: ElevatedButton(
onPressed: _socket == null
? null
: () {
// test
_sendMessage(
'{"distance": ${_distance.isEmpty ? 100 : int.parse(_distance)}, "angle": ${_angle.isEmpty ? 90 : int.parse(_angle)}}');
},
child: const Padding(
padding: EdgeInsets.all(8.0),
child: Text(
'Send Radar Distance',
style: TextStyle(fontSize: 22.0),
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
);
}
}
Turns out I had to give the application Internet permissions, as stated in Flutter docs about Networking. So I added the following line to AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
NB: AndroidManifest.xml manifest is located in the following location:
android > app > src > main > AndroidManifest.xml

how to save data and show it even after closing the app in flutter

class SimpleDialog extends StatelessWidget {
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _textEditingController =
TextEditingController();
String? baseurl;
#override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Base URL'),
content: Form(
key: _formKey,
child: TextFormField(
keyboardType: TextInputType.multiline,
maxLines: null,
controller: _textEditingController,
decoration: InputDecoration(
hintText: "Please Enter Base Url",
border:
OutlineInputBorder(borderRadius: BorderRadius.circular(15)),
),
validator: (value) {
// return value!.isNotEmpty ? null : "Enter Base Url";
return Uri.parse(value.toString()).host == ''
? "Enter Base Url"
: null;
},
)),
actions: <Widget>[
Center(
child: InkWell(
onTap: () {
if (_formKey.currentState!.validate()) {
baseurl = _textEditingController.text.toString().trim();
checkBaseUrl(baseurl, context);
print('baseurl=====base------$baseurl');
}
},
child: Container(
width: 100,
height: 40,
padding: EdgeInsets.all(12.0),
decoration: BoxDecoration(
color: Colors.blue,
borderRadius: BorderRadius.circular(20.0),
),
child: Text(
"Connect",
textAlign: TextAlign.center,
style: TextStyle(color: Colors.white),
),
),
),
)
],
);
}
Future<void> checkBaseUrl(String baseurl, context) async {
Response response;
try {
response = await http.get(Uri.parse(baseurl));
print(await response);
if (response.statusCode == 200) {
var snackBar = SnackBar(content: Text('Connected Successfully'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
var name = await baseurl;
await Prefs().seturlBase(name);
print(await '---pred---prefp---$name');
baseurl = await Prefs().geturlBase().toString();
Navigator.of(context).pop();
} else {
var snackBar = SnackBar(content: Text('Connection failed'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
Navigator.of(context).pop();
}
} catch (e) {
var snackBar = SnackBar(content: Text('Connection failed'));
ScaffoldMessenger.of(context).showSnackBar(snackBar);
Navigator.of(context).pop();
}
Class Prefs:
Future<void> seturlBase(String urlBase) async {
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setString(this.urlBase, urlBase);
}
Future<String> geturlBase() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
String urlBase;
urlBase = await prefs.getString(this.urlBase) ?? '';
return urlBase;
}
Check out the image, I need to save the URL as an input. After closing the app the URL should save and when users again open their app URL should be there for easy going.
How to achieve it, I used shared preferences.
.....................................................Thank you...........................
firt create a const for your base url
const String keyBaseUrl = 'baseUrl'
you can save it like this.
final SharedPreferences sharedPrefs = await SharedPreferences.getInstance();
sharedPrefs.setString(keyBaseUrl, baseurl);
and you can get it like this.
SharedPreferences prefs = await SharedPreferences.getInstance();
String? baseurl = prefs.getString(keyBaseUrl);

Flutter Error, Exception caught by gesture, The following _CastError was thrown while handling a gesture: Null check operator used on a null value

Whenever I tried to do login and tap on the login button then I am having this type of problem with the null check operator used on null values.
This is the error message that I got:
════════ Exception caught by gesture ═══════════════════════════════════════════
The following _CastError was thrown while handling a gesture:
Null check operator used on a null value
When the exception was thrown, this was the stack
#0 _AuthFormState._trySubmit package://FlutterChat/widgets/auth_form.dart:46
#1 _InkResponseState._handleTap
#2 GestureRecognizer.invokeCallback
#3 TapGestureRecognizer.handleTapUp
#4 BaseTapGestureRecognizer._checkUp
Handler: "onTap"
Recognizer: TapGestureRecognizer#c9833
debugOwner: GestureDetector
state: possible
won arena
finalPosition: Offset(165.5, 228.0)
finalLocalPosition: Offset(19.0, 13.5)
button: 1
sent tap down
This is my auth_form.dart file:
import 'package:flutter/material.dart';
import 'dart:io';
import './user_image_picker.dart';
class AuthForm extends StatefulWidget {
AuthForm(this.submitFn, this.isLoading);
final bool isLoading;
final Future<void> Function(String email, String password, String username,
File image, bool isLogin, BuildContext ctx) submitFn;
#override
_AuthFormState createState() => _AuthFormState();
}
class _AuthFormState extends State<AuthForm> {
final _formKey = GlobalKey<FormState>();
var _isLogin = true;
dynamic _userEmail = '';
dynamic _userName = '';
dynamic _userPassword;
File? _userImageFile;
void _pickedImage(File? image) {
_userImageFile = image;
}
//Form validation and save
_trySubmit() {
final isValid = _formKey.currentState?.validate();
FocusScope.of(context).unfocus();
if (_userImageFile == null && !_isLogin) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text('Please Select an Image'),
backgroundColor: Theme.of(context).errorColor,
));
return;
}
if (isValid!) {
_formKey.currentState?.save();
widget.submitFn(
_userEmail?.trim(),
_userPassword?.trim(),
_userName?.trim(),
_userImageFile!,
_isLogin,
context,
);
}
}
//Form Widget
#override
Widget build(BuildContext context) {
return new Builder(
builder: (context) {
return Center(
child: Card(
margin: EdgeInsets.all(20),
child: SingleChildScrollView(
child: Padding(
padding: EdgeInsets.all(16),
child: Form(
key: _formKey,
child: Column(
children: [
if (!_isLogin) UserImagePicker(_pickedImage),
TextFormField(
key: ValueKey('email'),
autocorrect: false,
textCapitalization: TextCapitalization.none,
enableSuggestions: false,
validator: (value) {
if (value?.isEmpty == null || !value!.contains('#')) {
return 'Please Enter valid Email Address.';
}
return null;
},
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
labelText: 'Email Address',
),
onSaved: (value) {
_userEmail = value;
},
),
if (!_isLogin)
TextFormField(
key: ValueKey('username'),
autocorrect: true,
textCapitalization: TextCapitalization.words,
enableSuggestions: false,
validator: (value) {
if (value!.isEmpty) {
return 'Please Enter Username.';
}
return null;
},
decoration: InputDecoration(
labelText: 'Username',
),
onSaved: (value) {
_userName = value;
}),
TextFormField(
key: ValueKey('password'),
validator: (value) {
if (value?.isEmpty == null || value!.length < 7) {
return 'Password must be atleast 7 characters long';
}
return null;
},
obscureText: true,
decoration: InputDecoration(
labelText: 'Password',
),
onSaved: (value) {
_userPassword = value;
}),
SizedBox(
height: 12,
),
if (widget.isLoading) CircularProgressIndicator(),
if (!widget.isLoading)
ElevatedButton(
child: Text(_isLogin ? 'Login' : 'Signup'),
onPressed: _trySubmit,
),
if (!widget.isLoading)
TextButton(
child: Text(_isLogin
? 'Create a new account'
: 'I already have an account'),
style: TextButton.styleFrom(primary: Colors.pink),
onPressed: () {
setState(() {
_isLogin = !_isLogin;
});
},
),
],
),
),
),
),
),
);
},
);
}
}
This is my auth_screen.dart file:
import 'package:FlutterChat/screens/conversion_screen.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import '../widgets/auth_form.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'dart:io';
import 'package:firebase_storage/firebase_storage.dart';
//import 'package:firebase_core/firebase_core.dart';
class AuthScreen extends StatefulWidget {
#override
_AuthScreenState createState() => _AuthScreenState();
}
class _AuthScreenState extends State<AuthScreen> {
//FirebaseAuth _auth = FirebaseAuth.instance;
var _isLoading = false;
//Submit AuthCredential Function
Future<void> submitAuthForm(String? email, String? password, String? username,
File? image, bool isLogin, BuildContext ctx) async {
UserCredential userCredential;
try {
setState(() {
_isLoading = true;
});
if (isLogin) {
userCredential = await FirebaseAuth.instance
.signInWithEmailAndPassword(email: email!, password: password!);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversionScreen()));
} else {
userCredential = await FirebaseAuth.instance
.createUserWithEmailAndPassword(email: email!, password: password!);
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => ConversionScreen()));
final ref = FirebaseStorage.instance
.ref()
.child('user_image')
.child(userCredential.user!.uid + '.jpg');
await ref.putFile(image!).whenComplete(() => print('Image Upload'));
final url = await ref.getDownloadURL();
await FirebaseFirestore.instance
.collection('users')
.doc(userCredential.user?.uid)
.set({
'username': username,
'email': email,
'imageUrl': url,
});
}
} on PlatformException catch (error) {
dynamic message = 'An error occured, please check your credentials!';
if (error.message != null) {
message = error.message;
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(message),
backgroundColor: Theme.of(ctx).errorColor,
),
);
setState(() {
_isLoading = false;
});
} catch (error) {
print(error);
setState(() {
_isLoading = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Theme.of(context).primaryColor,
body: AuthForm(submitAuthForm, _isLoading),
);
}
}
If someone knows then please help me.
The error is occurring due to this line,
_userImageFile!,
What I suspect is that your if clause,
if (_userImageFile == null && !_isLogin) {
is not protecting it from not being null, since the if clause would be false if _isLogin is true despite _userImageFile being null.
One way to fix this would be to do remove the bang operator since you can also have a case of calling the submitFn when your _isLogin is true and in that case, you definitely won't have a non null _userImageFile.
_userImageFile, // while calling widget.submitFn
Then make sure you change your `submitFn' function type to
final Future<void> Function(String email, String password, String username,
// add the ? for File image
File? image, bool isLogin, BuildContext ctx) submitFn;
Since your, submitAuthForm already says File? image, nothing to change there.
in auth_form.dart,use this process..check the image enter image description here

Error in FirebaseUser for authentication using flutter [duplicate]

This question already has answers here:
Undefined class 'FirebaseUser'
(6 answers)
Closed 1 year ago.
I'm beginner to this flutter. Currently i am trying to do email authentication for sign-up. I already tried few solution from website/github/youtube, but it turns to the same error which is on FirebaseUser. Here i attach my code segment.
class _RegisterEmailSectionState extends State<_RegisterEmailSection> {
void _register() async {
final FirebaseUser user = (await
_auth.createUserWithEmailAndPassword(
email: _emailController.text,
password: _passwordController.text,
)
).user;
if (user != null) {
setState(() {
_success = true;
_userEmail = user.email;
});
} else {
setState(() {
_success = true;
});
}
}
void dispose() {
_emailController.dispose();
_passwordController.dispose();
super.dispose();
}
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
final TextEditingController _emailController = TextEditingController();
final TextEditingController _passwordController = TextEditingController();
bool _success;
String _userEmail;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
TextFormField(
controller: _emailController,
decoration: const InputDecoration(labelText: 'Email'),
validator: (String value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
TextFormField(
controller: _passwordController,
decoration: const InputDecoration(labelText:
'Password'),
validator: (String value) {
if (value.isEmpty) {
return 'Please enter some text';
}
return null;
},
),
Container(
padding: const EdgeInsets.symmetric(vertical: 16.0),
alignment: Alignment.center,
child: RaisedButton(
onPressed: () async {
if (_formKey.currentState.validate()) {
_register();
}
},
child: const Text('Submit'),
),
),
Container(
alignment: Alignment.center,
child: Text(_success == null
? ''
: (_success
? 'Successfully registered ' + _userEmail
: 'Registration failed')),
)
],
),
),
);
}
}
Is there something that I miss out? I don't know why FirebaseUser error in my code. I assume that it is error due to different version of firebase. I found someone from the flutter community and they said try to changed it to be Authresult but the same error come out.
Can anyone help me on this issue? Thank you in advance!
Change
final FirebaseUser user = ...
to
final User user = ...
Here is the class you trying to get here. It has the type of User.

Flutter with Firebase Google sign in: Failed assertion network_image_io.dart

I'm trying to do Firebase authentication and Google sign in using Flutter but I'm getting this error message:
'package:flutter/src/painting/_network_image_io.dart': Failed assertion: line 23 pos 14: 'url != null': is not true.
I can't understand what is wrong, can you help me?
login.dart code snippet
-> calls signInWithGoogle() method from sign_in.dart and return FirstScreen
Widget _signInButton() {
return OutlineButton(
splashColor: Colors.grey,
onPressed: () {
signInWithGoogle().whenComplete(() {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return FirstScreen();
},
),
);
});
},
sign_in.dart code snippet:
-> Here I authenticate the user and try to get logged user name, email and image
final FirebaseAuth _auth = FirebaseAuth.instance;
final GoogleSignIn googleSignIn = GoogleSignIn();
String name;
String email;
String imageUrl;
Future<String> signInWithGoogle() async {
final GoogleSignInAccount googleSignInAccount = await googleSignIn.signIn();
final GoogleSignInAuthentication googleSignInAuthentication =
await googleSignInAccount.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleSignInAuthentication.accessToken,
idToken: googleSignInAuthentication.idToken,
);
final AuthResult authResult = await _auth.signInWithCredential(credential);
final FirebaseUser user = authResult.user;
// Checking if email and name is null
assert(user.email != null);
assert(user.displayName != null);
assert(user.photoUrl != null);
name = user.displayName;
email = user.email;
imageUrl = user.photoUrl;
// Only taking the first part of the name, i.e., First Name
if (name.contains(" ")) {
name = name.substring(0, name.indexOf(" "));
}
assert(!user.isAnonymous);
assert(await user.getIdToken() != null);
final FirebaseUser currentUser = await _auth.currentUser();
assert(user.uid == currentUser.uid);
log('data: $user');
return 'signInWithGoogle succeeded: $user';
}
void signOutGoogle() async {
await googleSignIn.signOut();
print("User Sign Out");
}
FirstScreen code snippet:
-> Here I try to show user data (name, email and image) based on what I got on previously code
children: <Widget>[
CircleAvatar(
backgroundImage: NetworkImage(
imageUrl,
),
radius: 60,
backgroundColor: Colors.transparent,
),
SizedBox(height: 40),
Text(
'NAME',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
name,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 20),
Text(
'EMAIL',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.bold,
color: Colors.black54),
),
Text(
email,
style: TextStyle(
fontSize: 25,
color: Colors.deepPurple,
fontWeight: FontWeight.bold),
),
SizedBox(height: 40)
EDIT: aditional info -> console log shows "Unhandled Exception: PlatformException(sign_in_failed, com.google.android.gms.common.api.ApiException: 10: , null)"
After wasting a day to find my way around the Google SignIn package with various fixes and troubleshooting, I realised there is web package Google has made for web sign in which uses the OAuthClient verification and configuration as per their changing policy with Google Sign in.
Sadly it isn't straight forward and quick as it was before. But following the steps mentioned in the pub.dev.
https://pub.dev/packages/google_sign_in_web
Attaching my main.dart working POC snippets here.
import 'dart:async';
import 'dart:convert' show json;
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:http/http.dart' as http;
GoogleSignIn _googleSignIn = GoogleSignIn(
// Optional clientId
// clientId: '479882132969-9i9aqik3jfjd7qhci1nqf0bm2g71rm1u.apps.googleusercontent.com',
scopes: <String>[
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
void main() {
runApp(
const MaterialApp(
title: 'Google Sign In',
home: SignInDemo(),
),
);
}
class SignInDemo extends StatefulWidget {
const SignInDemo({Key? key}) : super(key: key);
#override
State createState() => SignInDemoState();
}
class SignInDemoState extends State<SignInDemo> {
GoogleSignInAccount? _currentUser;
String _contactText = '';
#override
void initState() {
super.initState();
_googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? account) {
setState(() {
_currentUser = account;
});
if (_currentUser != null) {
_handleGetContact(_currentUser!);
}
});
_googleSignIn.signInSilently();
}
Future<void> _handleGetContact(GoogleSignInAccount user) async {
setState(() {
_contactText = 'Loading contact info...';
});
final http.Response response = await http.get(
Uri.parse('https://people.googleapis.com/v1/people/me/connections'
'?requestMask.includeField=person.names'),
headers: await user.authHeaders,
);
if (response.statusCode != 200) {
setState(() {
_contactText = 'People API gave a ${response.statusCode} '
'response. Check logs for details.';
});
print('People API ${response.statusCode} response: ${response.body}');
return;
}
final Map<String, dynamic> data =
json.decode(response.body) as Map<String, dynamic>;
final String? namedContact = _pickFirstNamedContact(data);
setState(() {
if (namedContact != null) {
_contactText = 'I see you know $namedContact!';
} else {
_contactText = 'No contacts to display.';
}
});
}
String? _pickFirstNamedContact(Map<String, dynamic> data) {
final List<dynamic>? connections = data['connections'] as List<dynamic>?;
final Map<String, dynamic>? contact = connections?.firstWhere(
(dynamic contact) => (contact as Map<Object?, dynamic>)['names'] != null,
orElse: () => null,
) as Map<String, dynamic>?;
if (contact != null) {
final List<dynamic> names = contact['names'] as List<dynamic>;
final Map<String, dynamic>? name = names.firstWhere(
(dynamic name) =>
(name as Map<Object?, dynamic>)['displayName'] != null,
orElse: () => null,
) as Map<String, dynamic>?;
if (name != null) {
return name['displayName'] as String?;
}
}
return null;
}
Future<void> _handleSignIn() async {
try {
await _googleSignIn.signIn();
} catch (error) {
print(error);
}
}
Future<void> _handleSignOut() => _googleSignIn.disconnect();
Widget _buildBody() {
final GoogleSignInAccount? user = _currentUser;
if (user != null) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
ListTile(
leading: GoogleUserCircleAvatar(
identity: user,
),
title: Text(user.displayName ?? ''),
subtitle: Text(user.email),
),
const Text('Signed in successfully.'),
Text(_contactText),
ElevatedButton(
onPressed: _handleSignOut,
child: const Text('SIGN OUT'),
),
ElevatedButton(
child: const Text('REFRESH'),
onPressed: () => _handleGetContact(user),
),
],
);
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
const Text('You are not currently signed in.'),
ElevatedButton(
onPressed: _handleSignIn,
child: const Text('SIGN IN'),
),
],
);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Sign In'),
),
body: ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: _buildBody(),
));
}
}
I found that the error I was getting was due to the lack of some OAuth Credentials settings. I found the solution here

Categories

Resources