How to get state changed value after widget build? - flutter

I have simple application where I work with user location. On first app open I will ask from user to allow location and then save to var. But when I try check inside widget location allow status it is return old value instance of changed value.
Code
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:yandex_mapkit/yandex_mapkit.dart';
import 'package:permission_handler/permission_handler.dart';
class PlacesListScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
return _Map();
}
}
class _Map extends StatefulWidget {
#override
_MapState createState() => _MapState();
}
class _MapState extends State<_Map> {
YandexMapController controller;
PermissionStatus _permissionStatus = PermissionStatus.undetermined;
#override
void initState() {
super.initState();
_requestPermission();
}
Future<void> _requestPermission() async {
Map<Permission, PermissionStatus> permissions =
await [Permission.location].request();
setState(() {
_permissionStatus = permissions[Permission.location];
});
}
void _showMessage(BuildContext context, Text text) {
final ScaffoldState scaffold = Scaffold.of(context);
scaffold.showSnackBar(
SnackBar(
content: text,
action: SnackBarAction(
label: 'OK', onPressed: scaffold.hideCurrentSnackBar),
),
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('App Name'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: null,
),
],
),
body: Text('App Content'),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: Row(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
FloatingActionButton(
onPressed: () async {
if (_permissionStatus == PermissionStatus.granted) {
await Future.wait([
controller.moveToUser(),
controller.showUserLayer(
iconName: 'lib/assets/arrow.png',
arrowName: 'lib/assets/user_location1.png',
accuracyCircleFillColor: Colors.green.withOpacity(0.5),
)
]);
} else {
_showMessage(context, const Text('Permission Denied'));
}
},
child: Icon(Icons.place, color: Colors.white),
backgroundColor: Colors.green,
heroTag: 'showUserLocation',
),
],
),
);
}
}
Using FloatingActionButton I tried check Permission status in my code. But my var _permissionStatus doesn't updated when user allowed location. How to fix this problem and get changed value from state?

You can use this package: https://pub.dev/packages/location
and then you can read the permission status:
Location location = new Location();
PermissionStatus _permissionGranted;
_permissionGranted = await location.hasPermission();
if (_permissionGranted == PermissionStatus.denied) {
_permissionGranted = await location.requestPermission();
if (_permissionGranted != PermissionStatus.granted) {
return;
}
}
another way:
location.hasPermision().then(PermissionStatus status){
if (_permissionGranted == PermissionStatus.denied){
location.requestPermission().then((PermissionStatus requestStatus){
// save the value
}
);
}
});

You need to know when user grand the permission then you know it, you must use the wrap your widget with FocusScope like this:
first define this:
final _focusNode = FocusScopeNode();
then wrap it with this:
return FocusScope(
node: _focusNode,
child: WillPopScope(
onWillPop: () async {
_requestPermission();
},.....

Related

The body might cause 'null' to be returned, but the return type, 'FutureOr<List<Map<dynamic, dynamic>>>', is a potentially non-nullable type

Error is:
The body might complete normally, causing 'null' to be returned, but the return type, 'FutureOr<List<Map<dynamic, dynamic>>>', is a potentially non-nullable type.
Try adding either a return or a throw statement at the end.
I tried adding an else function, yet I don't know where to add it exactly. Not to mention, that I don't know whether this is the best way to solve this error or not.
This is my code:
import 'package:algorithm_learn/sqldb.dart';
import 'package:flutter/material.dart';
class Home extends StatefulWidget {
const Home({super.key});
#override
State<Home> createState() => _HomeState();
}
class _HomeState extends State<Home> {
SqlDb sqlDb = SqlDb();
bool isloading = true;
List coing = [];
Future<List<Map>> readData() async {
List<Map> response = await sqlDb.readData("SELECT * FROM 'Coing'"); //(ERROR IS HERE)
coing.addAll(response);
isloading = false;
if (this.mounted) {
setState(() {});
}
}
#override
void initState() {
readData();
super.initState();
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('HomePage'),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.of(context).pushNamed("addperson");
},
child: const Icon(Icons.add),
),
body: isloading == true ?
Center(child: Text("Loading..."))
: Container(
child: ListView(
children: [
MaterialButton(
onPressed: () async {
await sqlDb.mydeleteDatabase();
},
child: const Text("Delete Database"),
),
ListView.builder(
itemCount: coing.length,
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemBuilder: (context, i) {
return Card(
child: ListTile(
title: Text("${coing[i]['first_name']}"),
subtitle: Text("${coing[i]['last_name']}"),
trailing: IconButton(
onPressed: () async {
int response = await sqlDb.deleteData(
"DELETE FROM coing WHERE id = ${coing[i]['id']}");
if (response > 0) {
coing.removeWhere(
(element) => element["id"] == coing[i]['id']);
setState(() {});
}
},
icon: Icon(Icons.delete, color: Colors.red),
),
),
);
},
),
],
),
),
);
}
}
You can mark it as nullable by adding a ?
Future<List<Map>> readData() async {
List<Map>? response = await sqlDb.readData("SELECT * FROM 'Coing'");
if(response != null)
{
coing.addAll(response);
}
isloading = false;
if (this.mounted) {
setState(() {});
}
}

flutter how to fix permission handler error

I dont know how to resolve this red error part.
I copied this from internet then i got this error.
please help me to solve this.
This is my full code.
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:android_intent/android_intent.dart';
import 'package:geolocator/geolocator.dart';
class AskForPermission extends StatefulWidget {
#override
_AskForPermissionState createState() => _AskForPermissionState();
}
class _AskForPermissionState extends State<AskForPermission> {
final PermissionHandler permissionHandler = PermissionHandler();
Map<PermissionGroup, PermissionStatus>? permissions;
void initState() {
super.initState();
requestLocationPermission();
_gpsService();
}
Future<bool> _requestPermission(PermissionGroup permission) async {
final PermissionHandler _permissionHandler = PermissionHandler();
var result = await _permissionHandler.requestPermissions([permission]);
if (result[permission] == PermissionStatus.granted) {
return true;
}
return false;
}
/*Checking if your App has been Given Permission*/
Future<bool> requestLocationPermission({Function? onPermissionDenied}) async {
var granted = await _requestPermission(PermissionGroup.location);
if (granted!=true) {
requestLocationPermission();
}
debugPrint('requestContactsPermission $granted');
return granted;
}
/*Show dialog if GPS not enabled and open settings location*/
Future _checkGps() async {
if (!(await Geolocator.isLocationServiceEnabled())) {
if (Theme.of(context).platform == TargetPlatform.android) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Can't get gurrent location"),
content:const Text('Please make sure you enable GPS and try again'),
actions: <Widget>[
FlatButton(child: Text('Ok'),
onPressed: () {
final AndroidIntent intent = AndroidIntent(
action: 'android.settings.LOCATION_SOURCE_SETTINGS');
intent.launch();
Navigator.of(context, rootNavigator: true).pop();
_gpsService();
})],
);
});
}
}
}
/*Check if gps service is enabled or not*/
Future _gpsService() async {
if (!(await Geolocator.isLocationServiceEnabled())) {
_checkGps();
return null;
} else
return true;
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Ask for permisions'),
backgroundColor: Colors.red,
),
body: Center(
child: Column(
children: <Widget>[
Text("All Permission Granted"),
],
))
);
}
}
I got the same problem - the code that worked with permission_handler ^8.0.0+2 didn't work anymore after I upgraded to ^8.3.0 - the code wouldn't compile, the Permission and the other classes where not "found" anymore (I use VS Code)
I fixed it by cleaning the pub cache:
flutter pub cache clean
and afterwards just get again the dependencies:
flutter pub get
PS: for upgrading to 8.3.0, I set targetSdkVersion and compileSdkVersion to 31 into build.gradle file
Install permission handler package from here. Then in your .dart file add import and call permission asking function somewhere. E.g. function like this asks for storage permission.
import 'package:permission_handler/permission_handler.dart';
Future<void> getStoragePermission() async {
if (await Permission.manageExternalStorage.request().isGranted) {
setState(() {});
} else if (await Permission.storage.request().isPermanentlyDenied) {
await openAppSettings();
} else if (await Permission.storage.request().isDenied) {
setState(() {});
}
}
Please refer to below code
https://pub.dev/packages/permission_handler/install
permission_handler: ^5.0.1+1
import 'package:permission_handler/permission_handler.dart';
import 'package:google_fonts/google_fonts.dart';
class MyApp extends StatelessWidget {
MyApp({Key key}) : super(key: key);
// This widget is the root of your application.
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primaryColor: Color(0xfff00B074),
textTheme: const TextTheme(
bodyText1: TextStyle(
fontSize: 18.0,
fontFamily: 'Barlow-Medium',
color: Color(0xff464255)),
),
),
home: PermissionHandlerScreen(),
);
}
}
class PermissionHandlerScreen extends StatefulWidget {
#override
_PermissionHandlerScreenState createState() =>
_PermissionHandlerScreenState();
}
class _PermissionHandlerScreenState extends State<PermissionHandlerScreen> {
#override
void initState() {
super.initState();
permissionServiceCall();
}
permissionServiceCall() async {
await permissionServices().then(
(value) {
if (value != null) {
if (value[Permission.storage].isGranted &&
value[Permission.camera].isGranted &&
value[Permission.microphone].isGranted) {
/* ========= New Screen Added ============= */
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => SplashScreen()),
);
}
}
},
);
}
/*Permission services*/
Future<Map<Permission, PermissionStatus>> permissionServices() async {
// You can request multiple permissions at once.
Map<Permission, PermissionStatus> statuses = await [
Permission.storage,
Permission.camera,
Permission.microphone,
//add more permission to request here.
].request();
if (statuses[Permission.storage].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.storage].isDenied) {
permissionServiceCall();
}
}
if (statuses[Permission.microphone].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.microphone].isDenied) {
permissionServiceCall();
}
}
if (statuses[Permission.camera].isPermanentlyDenied) {
openAppSettings();
setState(() {});
} else {
if (statuses[Permission.camera].isDenied) {
permissionServiceCall();
}
}
/*{Permission.camera: PermissionStatus.granted, Permission.storage: PermissionStatus.granted}*/
return statuses;
}
#override
Widget build(BuildContext context) {
permissionServiceCall();
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Container(
child: Center(
child: InkWell(
onTap: () {
permissionServiceCall();
},
child: Text("Click here to enable Enable Permission Screen")),
),
),
),
);
}
}
class SplashScreen extends StatelessWidget {
const SplashScreen({Key key}) : super(key: key);
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
},
child: Scaffold(
body: Center(
child: Text(
"Splash Screen",
),
),
),
);
}
}
Add permission_handler dependency in your pubspec.yaml file.
Try the flutter pub get command. If already done, then refer to this link about the permission handler package.

List does not appear in the app interface

The idea is that a list appears on my app screen and is updated as I add texts to the textField, but in my tests the list appears empty even though I put test items there.
image error
flutter version 1.0.0
dependences
path_provider: ^1.1.0
code atualization
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:io';
import 'dart:async';
import 'dart:convert';
class Home extends StatefulWidget {
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
List _listaTarefas = [];
Future<File> _pegarArquivo() async {
final diretorio = await getApplicationDocumentsDirectory();
return File("${diretorio.path}/dados.json");
}
_salvarArquivo() async {
var arquivo = await _pegarArquivo();
Map<String, dynamic> tarefa = Map();
tarefa['titulo'] = "Teste";
tarefa['realizada'] = false;
_listaTarefas.add(tarefa);
String dados = json.encode(_listaTarefas);
arquivo.writeAsString(dados);
}
_lerArquivo() async {
try {
final arquivo = await _pegarArquivo();
return arquivo.readAsString();
} catch (e) {
return null;
}
}
#override
void initState() {
super.initState();
_lerArquivo().then((dados) {
setState(() {
_listaTarefas = json.decode(dados);
});
});
}
#override
Widget build(BuildContext context) {
_salvarArquivo();
print('Resultado' + _listaTarefas.toString());
return Scaffold(
appBar: AppBar(
title: Text('Lista de tarefas'),
backgroundColor: Colors.purple,
),
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
backgroundColor: Colors.purple,
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Adicionar Tarefa'),
content: TextField(
decoration: InputDecoration(
labelText: 'Digite sua tarefa',
),
onChanged: (text) {},
),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text('cancelar'),
),
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('Salvar'),
),
],
);
});
}),
body: Column(
children: <Widget>[
Expanded(
child: ListView.builder(
itemCount: _listaTarefas.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_listaTarefas[index]['titulo']),
);
}))
],
),
);
}
}
The problem
When you declare the following method
_lerArquivo() async {
try {
final arquivo = await _pegarArquivo();
return arquivo.readAsStringSync();
} catch (e) {
return Text('erro');
}
}
you're returning a String when you do
return arquivo.readAsStringSync();
and a Text when you do
return Text('erro');
The solution
To fix this, you can either
return a string in the second return:
_lerArquivo() async {
try {
final arquivo = await _pegarArquivo();
return arquivo.readAsStringSync();
} catch (e) {
return 'erro';
}
}
do nothing:
_lerArquivo() async {
final arquivo = await _pegarArquivo();
return arquivo.readAsStringSync();
}
The good practice
To avoid future errors (i.e. transform run-time errors into compile-time errors), declare your variable types, return types and type parameters explicitely:
String _lerArquivo() async {
try {
final arquivo = await _pegarArquivo();
return arquivo.readAsStringSync();
} catch (e) {
// ...
}
}

setState is not updating the UI

I am trying to fetch data from the API and I am able to get logs but setState is not working.
Overall what I want to achieve is if there is response show the data on the screen, if there is any error in the API or on server or anything else I want to show it in the snackbar. My moto is to show errors as well.
Below is my model class
import 'http.dart';
class User {
int userId;
int id;
String title;
String body;
User({this.userId, this.id, this.title, this.body});
User.fromJson(Map<String, dynamic> json) {
userId = json['userId'];
id = json['id'];
title = json['title'];
body = json['body'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = new Map<String, dynamic>();
data['userId'] = this.userId;
data['id'] = this.id;
data['title'] = this.title;
data['body'] = this.body;
return data;
}
}
class UserExt {
static getUserInfo(Function(User user) success, Function(String errorMesssage) error) async{
final response = await HTTP.get(api: "https://jsonplaceholder.typicode.com/posts/1");
if(response.isSuccess == true) {
success(User.fromJson(response.response));
} else {
error(response.response);
}
}
}
Below is my http.dart file
import 'dart:html';
import 'package:flutter/cupertino.dart';
import 'package:http/http.dart' as http;
import 'dart:convert' as convert;
import 'package:http/http.dart';
const _timeoutDuration = Duration(seconds: 5);
class HTTP {
static Future<HttpResponse> get({#required String api}) async {
try {
Response response = await http.get(api).timeout(_timeoutDuration);
return _modeledResponse(response);
} catch (error) {
return HttpResponse(isSuccess: false, response: error.toString());
}
}
static Future<HttpResponse> _modeledResponse(Response response) async {
try {
if(response.statusCode == HttpStatus.ok) {
var jsonResponse = convert.jsonDecode(response.body);
return HttpResponse(isSuccess: true, response: jsonResponse);
} else {
return HttpResponse(isSuccess: false, response: response.statusCode.toString());
}
} catch (error) {
return HttpResponse(isSuccess: false, response: error.toString());
}
}
}
class HttpResponse {
final bool isSuccess;
final dynamic response;
HttpResponse({#required this.isSuccess, #required this.response});
}
Below is my screen from where I am calling the API.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http_request/User.dart';
import 'http.dart';
class ApiCalling extends StatefulWidget {
#override
_ApiCallingState createState() => _ApiCallingState();
}
class _ApiCallingState extends State<ApiCalling> {
bool showLoader = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Stack(
children: <Widget>[
Center(
child: RaisedButton(
child: Text("Call API"),
onPressed: () {
setState(() {
showLoader = true;
});
UserExt.getUserInfo((user){
print("UUUser id = ${user.userId}");
Scaffold.of(context).showSnackBar(SnackBar(content: Text("${user.userId}"),));
setState(() {
showLoader = false;
});
}, (error){
Scaffold.of(context).showSnackBar(SnackBar(content: Text("${error}"),));
setState(() {
showLoader = false;
});
});
},
),
),
Visibility(child: CircularProgressIndicator(backgroundColor: Colors.pink,), visible: showLoader,),
],
),
),
);
}
}
In the current code indicator is not getting show/hide or snackbar is also not getting displayed.
Just made some changes and addons just check the below code :
import 'package:flutter/material.dart';
import 'package:sample_project_for_api/model.dart';
void main() => runApp(ApiCalling());
class ApiCalling extends StatefulWidget {
#override
_ApiCallingState createState() => _ApiCallingState();
}
class _ApiCallingState extends State<ApiCalling> {
bool showLoader = false;
final _scaffoldKey = GlobalKey<ScaffoldState>();
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
key: _scaffoldKey,
body: Center(
child: Stack(
children: <Widget>[
Builder(
builder: (context) {
return Column(
children: <Widget>[
RaisedButton(
child: Text(
"this is first api call under the builder widget"),
onPressed: () {
UserExt.getUserInfo((user) {
print("UUUser id = ${user.userId}");
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content:
Text("This is you user id ${user.userId}"),
));
}, (error) {
Scaffold.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 2),
backgroundColor: Colors.redAccent,
content: Text("${error.toString()}"),
));
});
},
),
RaisedButton(
child: Text(
"this is second api call under the builder widget"),
onPressed: () {
UserExt.getUserInfo((user) {
print("UUUser id = ${user.userId}");
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content:
Text("This is you user id ${user.userId}"),
));
}, (error) {
Scaffold.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 2),
backgroundColor: Colors.redAccent,
content: Text("${error.toString()}"),
));
});
},
)
],
);
},
),
Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
RaisedButton(
child: Text("call snacker using the global key"),
onPressed: () {
setState(() {
showLoader = true;
});
UserExt.getUserInfo((user) {
print("UUUser id = ${user.userId}");
_scaffoldKey.currentState.showSnackBar(new SnackBar(
duration: Duration(seconds: 2),
content: new Text(
"This is you user id :${user.userId}")));
setState(() {
showLoader = false;
});
}, (error) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
duration: Duration(seconds: 2),
content: new Text("${error.toString()}")));
setState(() {
showLoader = false;
});
});
},
),
Secondbutton(),
],
),
),
Visibility(
child: CircularProgressIndicator(
backgroundColor: Colors.pink,
),
visible: showLoader,
),
],
),
),
),
);
}
}
class Secondbutton extends StatefulWidget {
#override
_SecondbuttonState createState() => _SecondbuttonState();
}
class _SecondbuttonState extends State<Secondbutton> {
#override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("calling snacker without using the global key"),
onPressed: () {
UserExt.getUserInfo((user) {
print("UUUser id = ${user.userId}");
Scaffold.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
content: Text("This is you user id ${user.userId}"),
));
}, (error) {
Scaffold.of(context).showSnackBar(SnackBar(
duration: Duration(seconds: 2),
backgroundColor: Colors.redAccent,
content: Text("${error.toString()}"),
));
});
},
);
}
}
Your problem was because it was not getting the proper context.
From the official Documentation of flutter https://api.flutter.dev/flutter/material/Scaffold/of.html
When the Scaffold is actually created in the same build function, the context argument to the build function can't be used to find the Scaffold (since it's "above" the widget being returned in the widget tree). In such cases, the following technique with a Builder can be used to provide a new scope with a BuildContext that is "under" the Scaffold:
So basically the problem is with your context of Scaffold,so instead of using context of Direct parent that instantiate the Scaffold, use the context of the child.
Below code will work.
class _ApiCallingState extends State<ApiCalling> {
bool showLoader = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: Builder(
builder: (context)=>
Center(
child: Stack(
children: <Widget>[
Center(
child: RaisedButton(
child: Text("Call API"),
onPressed: () {
setState(() {
showLoader = true;
});
UserExt.getUserInfo((user) {
print("UUUser id = ${user.userId}");
print("context==$context");
Scaffold.of(context).showSnackBar(SnackBar(
content: Text(" User Id${user.userId}"),
));
setState(() {
showLoader = false;
});
}, (error) {
setState(() {
showLoader = false;
});
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("${error}"),
));
});
},
),
),
Visibility(
child:
Center(
child:CircularProgressIndicator(
backgroundColor: Colors.pink,
),
),
visible: showLoader,
)
],
),
),
)
);
}
}
declare a global key
final _scaffoldKey = GlobalKey();
and in UI
_scaffoldKey.currentState.showSnackBar(snackbar);

Flutter: I am unable to logout my app with google sign in library. How to do this?

I have tried below google sign in example , it is working fine. But when I moved _handleSignOut() function to another screen , it is not signing out. My requirement is after login success, my homepage is visible. On the top of homepage , there is a logout button. on the click of which , I want to logout my app with google.
import 'dart:async';
import 'dart:convert' show json;
import "package:http/http.dart" as http;
import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: <String>[
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
);
void main() {
runApp(
MaterialApp(
title: 'Google Sign In',
home: SignInDemo(),
),
);
}
class SignInDemo extends StatefulWidget {
#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();
}
});
_googleSignIn.signInSilently();
}
Future<void> _handleGetContact() async {
setState(() {
_contactText = "Loading contact info...";
});
final http.Response response = await http.get(
'https://people.googleapis.com/v1/people/me/connections'
'?requestMask.includeField=person.names',
headers: await _currentUser.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);
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'];
final Map<String, dynamic> contact = connections?.firstWhere(
(dynamic contact) => contact['names'] != null,
orElse: () => null,
);
if (contact != null) {
final Map<String, dynamic> name = contact['names'].firstWhere(
(dynamic name) => name['displayName'] != null,
orElse: () => null,
);
if (name != null) {
return name['displayName'];
}
}
return null;
}
Future<void> _handleSignIn() async {
try {
await _googleSignIn.signIn();
} catch (error) {
print(error);
}
}
Future<void> _handleSignOut() async {
_googleSignIn.disconnect();
}
Widget _buildBody() {
if (_currentUser != null) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
ListTile(
leading: GoogleUserCircleAvatar(
identity: _currentUser,
),
title: Text(_currentUser.displayName),
subtitle: Text(_currentUser.email),
),
const Text("Signed in successfully."),
Text(_contactText),
RaisedButton(
child: const Text('SIGN OUT'),
onPressed: _handleSignOut,
),
RaisedButton(
child: const Text('REFRESH'),
onPressed: _handleGetContact,
),
],
);
} else {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
const Text("You are not currently signed in."),
RaisedButton(
child: const Text('SIGN IN'),
onPressed: _handleSignIn,
),
],
);
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Google Sign In'),
),
body: ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: _buildBody(),
));
}
}
Use signOut() instead. If you are using FirebaseAuth, you need to log out from both
Future<void> _handleSignOut() async {
await FirebaseAuth.instance.signOut();
await _googleSignIn.signOut();
}
I found solution for this. I was creating again an object of googlesignin in logout screen.
It was my mistake.
Using same object of googlesignin as declared above
GoogleSignIn _googleSignIn = GoogleSignIn(....) in Logout screen will work. I just need to call this object like _googleSignIn.signOut().