google_sign_in_android 7.0.5 copy "google_sign_in_android: ^7.0.5" to clipboard
google_sign_in_android: ^7.0.5 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(),
      ),
    );
  }
}