blob: 526cf8b69ccfb7e66ff605cfc29f7a5209aa47f5 [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// ignore_for_file: public_member_api_docs
import 'dart:async';
import 'dart:convert' show json;
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:http/http.dart' as http;
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> {
GoogleSignInUserData? _currentUser;
String _contactText = '';
// Future that completes when `init` has completed on the sign in instance.
Future<void>? _initialization;
@override
void initState() {
super.initState();
_signIn();
}
Future<void> _ensureInitialized() {
return _initialization ??= GoogleSignInPlatform.instance.init(
scopes: <String>[
'email',
'https://www.googleapis.com/auth/contacts.readonly',
],
)..catchError((dynamic _) {
_initialization = null;
});
}
void _setUser(GoogleSignInUserData? user) {
setState(() {
_currentUser = user;
if (user != null) {
_handleGetContact(user);
}
});
}
Future<void> _signIn() async {
await _ensureInitialized();
final GoogleSignInUserData? newUser =
await GoogleSignInPlatform.instance.signInSilently();
_setUser(newUser);
}
Future<Map<String, String>> _getAuthHeaders() async {
final GoogleSignInUserData? user = _currentUser;
if (user == null) {
throw StateError('No user signed in');
}
final GoogleSignInTokenData response =
await GoogleSignInPlatform.instance.getTokens(
email: user.email,
shouldRecoverAuth: true,
);
return <String, String>{
'Authorization': 'Bearer ${response.accessToken}',
// TODO(kevmoo): Use the correct value once it's available.
// See https://github.com/flutter/flutter/issues/80905
'X-Goog-AuthUser': '0',
};
}
Future<void> _handleGetContact(GoogleSignInUserData 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 _getAuthHeaders(),
);
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 int contactCount =
(data['connections'] as List<dynamic>?)?.length ?? 0;
setState(() {
_contactText = '$contactCount contacts found';
});
}
Future<void> _handleSignIn() async {
try {
await _ensureInitialized();
_setUser(await GoogleSignInPlatform.instance.signIn());
} catch (error) {
final bool canceled =
error is PlatformException && error.code == 'sign_in_canceled';
if (!canceled) {
print(error);
}
}
}
Future<void> _handleSignOut() async {
await _ensureInitialized();
await GoogleSignInPlatform.instance.disconnect();
}
Widget _buildBody() {
final GoogleSignInUserData? user = _currentUser;
if (user != null) {
return Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
ListTile(
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(),
));
}
}