@@ -10,13 +10,12 @@ import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sig
10
10
import 'package:flutter/material.dart' ;
11
11
import 'package:google_sign_in/google_sign_in.dart' ;
12
12
import 'package:googleapis/people/v1.dart' ;
13
+ // #docregion CreateAPIClient
13
14
import 'package:googleapis_auth/googleapis_auth.dart' as auth show AuthClient;
15
+ // #enddocregion CreateAPIClient
14
16
15
- final GoogleSignIn _googleSignIn = GoogleSignIn (
16
- // Optional clientId
17
- // clientId: '[YOUR_OAUTH_2_CLIENT_ID]',
18
- scopes: < String > [PeopleServiceApi .contactsReadonlyScope],
19
- );
17
+ /// The scopes used by this example.
18
+ const List <String > scopes = < String > [PeopleServiceApi .contactsReadonlyScope];
20
19
21
20
void main () {
22
21
runApp (
@@ -38,37 +37,84 @@ class SignInDemo extends StatefulWidget {
38
37
39
38
/// The state of the main widget.
40
39
class SignInDemoState extends State <SignInDemo > {
40
+ late Future <void > _signInInitialized;
41
41
GoogleSignInAccount ? _currentUser;
42
+ GoogleSignInClientAuthorization ? _authorization;
42
43
String _contactText = '' ;
43
44
44
45
@override
45
46
void initState () {
46
47
super .initState ();
47
- _googleSignIn.onCurrentUserChanged.listen ((GoogleSignInAccount ? account) {
48
+
49
+ final GoogleSignIn signIn = GoogleSignIn .instance;
50
+ _signInInitialized = signIn.initialize (
51
+ // Add your client IDs here as necessary for your supported platforms.
52
+ );
53
+ signIn.authenticationEvents.listen ((GoogleSignInAuthenticationEvent event) {
54
+ if (! mounted) {
55
+ return ;
56
+ }
48
57
setState (() {
49
- _currentUser = account;
58
+ switch (event) {
59
+ case GoogleSignInAuthenticationEventSignIn ():
60
+ _currentUser = event.user;
61
+ case GoogleSignInAuthenticationEventSignOut ():
62
+ _currentUser = null ;
63
+ _authorization = null ;
64
+ }
50
65
});
66
+
51
67
if (_currentUser != null ) {
52
- _handleGetContact ();
68
+ _checkAuthorization ();
53
69
}
70
+ }).onError ((Object error) {
71
+ debugPrint (error.toString ());
72
+ });
73
+
74
+ _signInInitialized.then ((void value) {
75
+ signIn.attemptLightweightAuthentication ();
54
76
});
55
- _googleSignIn.signInSilently ();
56
77
}
57
78
58
- Future <void > _handleGetContact () async {
79
+ void _updateAuthorization (GoogleSignInClientAuthorization ? authorization) {
80
+ if (! mounted) {
81
+ return ;
82
+ }
59
83
setState (() {
60
- _contactText = 'Loading contact info...' ;
84
+ _authorization = authorization ;
61
85
});
62
86
63
- // #docregion CreateAPIClient
64
- // Retrieve an [auth.AuthClient] from the current [GoogleSignIn] instance.
65
- final auth.AuthClient ? client = await _googleSignIn.authenticatedClient ();
87
+ if (authorization != null ) {
88
+ unawaited (_handleGetContact (authorization));
89
+ }
90
+ }
66
91
67
- assert (client != null , 'Authenticated client missing!' );
92
+ Future <void > _checkAuthorization () async {
93
+ _updateAuthorization (
94
+ await _currentUser? .authorizationClient.authorizationForScopes (scopes));
95
+ }
96
+
97
+ Future <void > _requestAuthorization () async {
98
+ _updateAuthorization (await _currentUser? .authorizationClient
99
+ .authorizeScopes (< String > [PeopleServiceApi .contactsReadonlyScope]));
100
+ }
101
+
102
+ Future <void > _handleGetContact (
103
+ GoogleSignInClientAuthorization authorization) async {
104
+ if (! mounted) {
105
+ return ;
106
+ }
107
+ setState (() {
108
+ _contactText = 'Loading contact info...' ;
109
+ });
110
+
111
+ // #docregion CreateAPIClient
112
+ // Retrieve an [auth.AuthClient] from a GoogleSignInClientAuthorization.
113
+ final auth.AuthClient client = authorization.authClient (scopes: scopes);
68
114
69
115
// Prepare a People Service authenticated client.
70
- final PeopleServiceApi peopleApi = PeopleServiceApi (client! );
71
- // Retrieve a list of the `names` of my `connections`
116
+ final PeopleServiceApi peopleApi = PeopleServiceApi (client);
117
+ // Retrieve a list of connected contacts' names.
72
118
final ListConnectionsResponse response =
73
119
await peopleApi.people.connections.list (
74
120
'people/me' ,
@@ -79,13 +125,15 @@ class SignInDemoState extends State<SignInDemo> {
79
125
final String ? firstNamedContactName =
80
126
_pickFirstNamedContact (response.connections);
81
127
82
- setState (() {
83
- if (firstNamedContactName != null ) {
84
- _contactText = 'I see you know $firstNamedContactName !' ;
85
- } else {
86
- _contactText = 'No contacts to display.' ;
87
- }
88
- });
128
+ if (mounted) {
129
+ setState (() {
130
+ if (firstNamedContactName != null ) {
131
+ _contactText = 'I see you know $firstNamedContactName !' ;
132
+ } else {
133
+ _contactText = 'No contacts to display.' ;
134
+ }
135
+ });
136
+ }
89
137
}
90
138
91
139
String ? _pickFirstNamedContact (List <Person >? connections) {
@@ -102,51 +150,72 @@ class SignInDemoState extends State<SignInDemo> {
102
150
103
151
Future <void > _handleSignIn () async {
104
152
try {
105
- await _googleSignIn. signIn ();
153
+ await GoogleSignIn .instance. authenticate ();
106
154
} catch (error) {
107
- print (error); // ignore: avoid_print
155
+ debugPrint (error. toString ());
108
156
}
109
157
}
110
158
111
- Future <void > _handleSignOut () => _googleSignIn.disconnect ();
159
+ // Call disconnect rather than signOut to more fully reset the example app.
160
+ Future <void > _handleSignOut () => GoogleSignIn .instance.disconnect ();
112
161
113
162
Widget _buildBody () {
114
- final GoogleSignInAccount ? user = _currentUser;
115
- if (user != null ) {
116
- return Column (
117
- mainAxisAlignment: MainAxisAlignment .spaceAround,
118
- children: < Widget > [
119
- ListTile (
120
- leading: GoogleUserCircleAvatar (
121
- identity: user,
122
- ),
123
- title: Text (user.displayName ?? '' ),
124
- subtitle: Text (user.email),
125
- ),
126
- const Text ('Signed in successfully.' ),
127
- Text (_contactText),
128
- ElevatedButton (
129
- onPressed: _handleSignOut,
130
- child: const Text ('SIGN OUT' ),
131
- ),
132
- ElevatedButton (
133
- onPressed: _handleGetContact,
134
- child: const Text ('REFRESH' ),
135
- ),
136
- ],
137
- );
138
- } else {
139
- return Column (
140
- mainAxisAlignment: MainAxisAlignment .spaceAround,
141
- children: < Widget > [
142
- const Text ('You are not currently signed in.' ),
143
- ElevatedButton (
144
- onPressed: _handleSignIn,
145
- child: const Text ('SIGN IN' ),
146
- ),
147
- ],
148
- );
149
- }
163
+ return FutureBuilder <void >(
164
+ future: _signInInitialized,
165
+ builder: (BuildContext context, AsyncSnapshot <void > snapshot) {
166
+ final GoogleSignInAccount ? user = _currentUser;
167
+ final GoogleSignInClientAuthorization ? authorization = _authorization;
168
+ final List <Widget > children;
169
+ if (snapshot.hasError) {
170
+ children = < Widget > [
171
+ const Text ('Error initializing sign in.' ),
172
+ ];
173
+ } else if (snapshot.connectionState == ConnectionState .done) {
174
+ children = < Widget > [
175
+ if (user != null ) ...< Widget > [
176
+ ListTile (
177
+ leading: GoogleUserCircleAvatar (
178
+ identity: user,
179
+ ),
180
+ title: Text (user.displayName ?? '' ),
181
+ subtitle: Text (user.email),
182
+ ),
183
+ const Text ('Signed in successfully.' ),
184
+ if (authorization != null ) ...< Widget > [
185
+ Text (_contactText),
186
+ ElevatedButton (
187
+ onPressed: () => _handleGetContact (authorization),
188
+ child: const Text ('REFRESH' ),
189
+ ),
190
+ ] else ...< Widget > [
191
+ ElevatedButton (
192
+ onPressed: _requestAuthorization,
193
+ child: const Text ('LOAD CONTACTS' ),
194
+ ),
195
+ ],
196
+ ElevatedButton (
197
+ onPressed: _handleSignOut,
198
+ child: const Text ('SIGN OUT' ),
199
+ ),
200
+ ] else ...< Widget > [
201
+ const Text ('You are not currently signed in.' ),
202
+ ElevatedButton (
203
+ onPressed: _handleSignIn,
204
+ child: const Text ('SIGN IN' ),
205
+ ),
206
+ ],
207
+ ];
208
+ } else {
209
+ children = < Widget > [
210
+ const CircularProgressIndicator (),
211
+ ];
212
+ }
213
+
214
+ return Column (
215
+ mainAxisAlignment: MainAxisAlignment .spaceAround,
216
+ children: children,
217
+ );
218
+ });
150
219
}
151
220
152
221
@override
0 commit comments