google_sign_in_android 7.0.1 copy "google_sign_in_android: ^7.0.1" to clipboard
google_sign_in_android: ^7.0.1 copied to clipboard

PlatformAndroid

Android implementation of the google_sign_in plugin.

example/lib/main.dart

// 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, avoid_print

import 'dart:async';
import 'dart:convert' show json;

import 'package:flutter/material.dart';
import 'package:google_sign_in_platform_interface/google_sign_in_platform_interface.dart';
import 'package:http/http.dart' as http;

const List<String> _scopes = <String>[
  'https://www.googleapis.com/auth/contacts.readonly',
];

void main() {
  runApp(
    const MaterialApp(
      title: 'Google Sign In',
      home: SignInDemo(),
    ),
  );
}

class SignInDemo extends StatefulWidget {
  const SignInDemo({super.key});

  @override
  State createState() => SignInDemoState();
}

class SignInDemoState extends State<SignInDemo> {
  GoogleSignInUserData? _currentUser;
  bool _isAuthorized = false;
  String _contactText = '';
  String _errorMessage = '';
  // Future that completes when `init` has completed on the sign in instance.
  Future<void>? _initialization;

  @override
  void initState() {
    super.initState();
    _signIn();
  }

  Future<void> _ensureInitialized() {
    // The example app uses the parsing of values from google-services.json
    // to provide the serverClientId, otherwise it would be required here.
    return _initialization ??=
        GoogleSignInPlatform.instance.init(const InitParameters())
          ..catchError((dynamic _) {
            _initialization = null;
          });
  }

  void _setUser(GoogleSignInUserData? user) {
    setState(() {
      _currentUser = user;
    });
    if (user != null) {
      // Try getting contacts, in case authorization is already granted.
      _handleGetContact(user);
    }
  }

  Future<void> _signIn() async {
    await _ensureInitialized();
    try {
      final AuthenticationResults? result = await GoogleSignInPlatform.instance
          .attemptLightweightAuthentication(
              const AttemptLightweightAuthenticationParameters());
      _setUser(result?.user);
    } on GoogleSignInException catch (e) {
      setState(() {
        _errorMessage = e.code == GoogleSignInExceptionCode.canceled
            ? ''
            : 'GoogleSignInException ${e.code}: ${e.description}';
      });
    }
  }

  Future<void> _handleAuthorizeScopes(GoogleSignInUserData user) async {
    try {
      final ClientAuthorizationTokenData? tokens = await GoogleSignInPlatform
          .instance
          .clientAuthorizationTokensForScopes(
              ClientAuthorizationTokensForScopesParameters(
                  request: AuthorizationRequestDetails(
                      scopes: _scopes,
                      userId: user.id,
                      email: user.email,
                      promptIfUnauthorized: true)));

      setState(() {
        _isAuthorized = tokens != null;
        _errorMessage = '';
      });
      if (_isAuthorized) {
        unawaited(_handleGetContact(user));
      }
    } on GoogleSignInException catch (e) {
      setState(() {
        _errorMessage = 'GoogleSignInException ${e.code}: ${e.description}';
      });
    }
  }

  Future<Map<String, String>?> _getAuthHeaders(
      GoogleSignInUserData user) async {
    final ClientAuthorizationTokenData? tokens =
        await GoogleSignInPlatform.instance.clientAuthorizationTokensForScopes(
            ClientAuthorizationTokensForScopesParameters(
                request: AuthorizationRequestDetails(
                    scopes: _scopes,
                    userId: user.id,
                    email: user.email,
                    promptIfUnauthorized: false)));
    if (tokens == null) {
      return null;
    }

    return <String, String>{
      'Authorization': 'Bearer ${tokens.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 Map<String, String>? headers = await _getAuthHeaders(user);
    setState(() {
      _isAuthorized = headers != null;
    });
    if (headers == null) {
      return;
    }
    final http.Response response = await http.get(
      Uri.parse('https://people.googleapis.com/v1/people/me/connections'
          '?requestMask.includeField=person.names'),
      headers: headers,
    );
    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();
      final AuthenticationResults result = await GoogleSignInPlatform.instance
          .authenticate(const AuthenticateParameters());
      _setUser(result.user);
    } on GoogleSignInException catch (e) {
      setState(() {
        _errorMessage = e.code == GoogleSignInExceptionCode.canceled
            ? ''
            : 'GoogleSignInException ${e.code}: ${e.description}';
      });
    }
  }

  Future<void> _handleSignOut() async {
    await _ensureInitialized();
    await GoogleSignInPlatform.instance.disconnect(const DisconnectParams());
  }

  Widget _buildBody() {
    final GoogleSignInUserData? user = _currentUser;
    return Column(
      mainAxisAlignment: MainAxisAlignment.spaceAround,
      children: <Widget>[
        if (user != null) ...<Widget>[
          ListTile(
            title: Text(user.displayName ?? ''),
            subtitle: Text(user.email),
          ),
          const Text('Signed in successfully.'),
          ElevatedButton(
            onPressed: _handleSignOut,
            child: const Text('SIGN OUT'),
          ),
          if (_isAuthorized) ...<Widget>[
            // The user has Authorized all required scopes.
            if (_contactText.isNotEmpty) Text(_contactText),
            ElevatedButton(
              child: const Text('REFRESH'),
              onPressed: () => _handleGetContact(user),
            ),
          ] else ...<Widget>[
            // The user has NOT Authorized all required scopes.
            const Text('Authorization needed to read your contacts.'),
            ElevatedButton(
              onPressed: () => _handleAuthorizeScopes(user),
              child: const Text('REQUEST PERMISSIONS'),
            ),
          ],
        ] else ...<Widget>[
          const Text('You are not currently signed in.'),
          ElevatedButton(
            onPressed: _handleSignIn,
            child: const Text('SIGN IN'),
          ),
        ],
        if (_errorMessage.isNotEmpty) Text(_errorMessage),
      ],
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Google Sign In'),
        ),
        body: ConstrainedBox(
          constraints: const BoxConstraints.expand(),
          child: _buildBody(),
        ));
  }
}