Google登录及获取Calendar信息

Google登录及获取Calendar信息

firebase方案(实际是一个三方登录集成,由于是google的所以使用Google账户登录以后可以使用google api)

firebase官网
使用firebase Auth集成并登录
firebase创建项目后会在google cloud中创建并关联项目,登录成功后接着就可以按照下述方法使用google api获取相应信息。

flutter中用到的插件:
firebase_auth
firebase_core
参考firebase flutter网站

在google开发者平台构建项目(单独集成)

进入Google Cloud登录并注册,之后按照提示构建项目。

进入Apis&Services->Credentials下点击CREATE CREDENTIALS创建OAuth 2.0 Client IDs。(ios和android需分别创建)。

创建过程中根据提示android需要配置sha-1签名证书,ios需要配置url scheme。

android需要配置签名:

Android 怎么创建签名文件和解析签名文件

将生成好的签名文件放到工程app文件夹下,与app的build.gradle平行,之后再app的build.gradle中做如下配置:

...
android{
    ...
    buildTypes {
        release {
            signingConfig signingConfigs.debug
        }
        debug {
            signingConfig signingConfigs.debug
        }
    }

    signingConfigs {
        debug {
            storeFile file("nearhubone.keystore")//签名文件名
            storePassword "123456"//密码
            keyAlias "nearhubone"//别名
            keyPassword "123456"//密码
        }

        release {
            storeFile file("nearhubone.keystore")
            storePassword "123456"
            keyAlias "nearhubone"
            keyPassword "123456"
        }
    }
    ...
}

申请需要使用的api

点击Google Cloud-APIs&Services下的Enabled APIs&services,enable需要使用的api,如Google Calendar API。需要创建api key的则创建api key(非所有api都需要创建api key)。

集成到对于项目

Flutter中集成

需要使用的插件有:

google_sign_in//用于登录

extension_google_sign_in_as_googleapis_auth//配合拓展google_sign_in用于提供api初始化需要的Client

googleapis//提供丰富的google api

Flutter使用 Google API
Flutter使用 Google API 英文

流程如下:

使用google_sign_in插件实现登录

  • serverClientId参数填写OAuth 2.0 Client IDs里相对应的ClientId。
  • 注意初始化配置中的scopes,这个scopes用于用户授权范围,只有填入的scopes才会显示在用户授权页上并得到授权,否则api将会调用失败。这个scopes的字段在api文档里可得。如CalendarList get这个api在其文档里的Authorization就可看到scope列表。

登录的示例代码如下:

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';//登录所需插件
import 'package:http/http.dart' as http;
import 'dart:convert' show json;

//配置google登录
GoogleSignIn _googleSignIn = GoogleSignIn(
  // Optional clientId
  serverClientId: '781114075503-2qscj6a0ahsqedt6cellol0ur7qij645.apps.googleusercontent.com',
  //授权范围(用户授权页会提示用户授权)
  scopes: <String>[
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
    'https://www.googleapis.com/auth/calendar',//获取日历信息授权
  ],
);

class SignInDemo extends StatefulWidget {
  const SignInDemo({Key? key}) : super(key: key);

  
  State createState() => SignInDemoState();
}

class SignInDemoState extends State<SignInDemo> {
  GoogleSignInAccount? _currentUser;
  String _contactText = '';

  
  void initState() {
    super.initState();
    //注册登录回调
    _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? account) {
      setState(() {
        _currentUser = account;
      });
      if (_currentUser != null) {
        _handleGetContact(_currentUser!);
      }
    });
    _googleSignIn.signInSilently();

  }
    
  //【非登录必须流程】登录后获取用户个人信息用于显示    
  Future<void> _handleGetContact(GoogleSignInAccount user) async {
    setState(() {
      _contactText = 'Loading contact info...';
    });
    //通过http请求获取用户个人信息
    final http.Response response = await http.get(
      Uri.parse('https://people.googleapis.com/v1/people/me/connections'
          '?requestMask.includeField=person.names'),
      headers: await user.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) as Map<String, dynamic>;
    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'] as List<dynamic>?;
    final Map<String, dynamic>? contact = connections?.firstWhere(
          (dynamic contact) => contact['names'] != null,
      orElse: () => null,
    ) as Map<String, dynamic>?;
    if (contact != null) {
      final Map<String, dynamic>? name = contact['names'].firstWhere(
            (dynamic name) => name['displayName'] != null,
        orElse: () => null,
      ) as Map<String, dynamic>?;
      if (name != null) {
        return name['displayName'] as String?;
      }
    }
    return null;
  }

  //登录
  Future<void> _handleSignIn() async {
    try {
      await _googleSignIn.signIn();
    } catch (error) {
      print(error);
    }
  }

 //登出
  Future<void> _handleSignOut() => _googleSignIn.disconnect();

 //界面展示
  Widget _buildBody() {
    final GoogleSignInAccount? user = _currentUser;
    if (user != null) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          ListTile(
            leading: GoogleUserCircleAvatar(
              identity: user,
            ),
            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'),
          ),
        ],
      );
    }
  }

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

参考:
官方示例

获取日历信息

获取日历信息可使用两种方式:

  • 一种方式直接使用http请求,无需其他插件,只需在请求头中添加登录信息
    api查看官方文档
import 'package:google_sign_in/google_sign_in.dart';
    ...
class SignInDemo extends State<SignInDemo> {   
    ...
    
    GoogleSignInAccount? _currentUser;
    
      void initState() {
        super.initState();
        //注册登录回调
        _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? account) {
          setState(() {
            _currentUser = account;
          });
          ...
          
        });
      }
    ...
    
    onGetCalendarClick(){
        handleGetCalendar(_currentUser);
    }
    ...
    
    //获取谷歌日历列表信息(http方式)
      handleGetCalendar(GoogleSignInAccount user) async {
        final http.Response response = await http.get(
          Uri.parse('https://www.googleapis.com/calendar/v3/calendars/primary/events'),//api查看官方文档
          headers: await user.authHeaders,//在请求头中添加登录信息
        );
        if (response.statusCode != 200) {
          print('Calendar API ${response.statusCode} response: ${response.body}');
        } else {
	    final Map<String, dynamic> data =
	      json.decode(response.body) as Map<String, dynamic>;
	      debugPrint(data.toString());
        }
      }

  }
  • 【推荐】另一种方式使用googleapis插件配合google登录拓展插件extension_google_sign_in_as_googleapis_auth使用

由于googleapis初始化对应api时需要提供client,extension_google_sign_in_as_googleapis_auth插件可以配合google_sign_in提供client。

代码如下:

import 'package:google_sign_in/google_sign_in.dart';
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:googleapis/calendar/v3.dart';
//获取谷歌日历列表信息(sdk方式)
  getCalendarEvent() async {
    var httpClient = (await _googleSignIn.authenticatedClient())!;
    var calendar = CalendarApi(httpClient);
    var calEvents = calendar.events.list("primary");
    calEvents.then((events) => {
      events.items?.forEach((event) => print("EVENT ${event.summary}"))
    });
  }

参考:
如何在flutter中使用google日历api获取一个月内的所有活动 (仅参考使用googleapis-CalendarApi部分)

获取身份验证后的 HTTP 客户端

完整代码参考:

google_sign_in_get_calendar_demo.dart

import 'package:flutter/material.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'package:extension_google_sign_in_as_googleapis_auth/extension_google_sign_in_as_googleapis_auth.dart';
import 'package:googleapis/calendar/v3.dart';
import 'package:http/http.dart' as http;
import 'dart:convert' show json;

//配置google登录
GoogleSignIn _googleSignIn = GoogleSignIn(
  // Optional clientId
  serverClientId: '781114075503-2qscj6a0ahsqedt6cellol0ur7qij645.apps.googleusercontent.com',
  //授权范围(用户授权页会提示用户授权)
  scopes: <String>[
    'email',
    'https://www.googleapis.com/auth/contacts.readonly',
    'https://www.googleapis.com/auth/calendar',
  ],
);

class SignInDemo extends StatefulWidget {
  const SignInDemo({Key? key}) : super(key: key);

  
  State createState() => SignInDemoState();
}

class SignInDemoState extends State<SignInDemo> {
  GoogleSignInAccount? _currentUser;
  String _contactText = '';

  
  void initState() {
    super.initState();
    //注册登录回调
    _googleSignIn.onCurrentUserChanged.listen((GoogleSignInAccount? account) {
      setState(() {
        _currentUser = account;
      });
      if (_currentUser != null) {
        _handleGetContact(_currentUser!);
      }
    });
    _googleSignIn.signInSilently();

  }

  //【非登录必须流程】登录后获取用户个人信息用于显示
  Future<void> _handleGetContact(GoogleSignInAccount user) async {
    setState(() {
      _contactText = 'Loading contact info...';
    });
    //通过http请求获取用户个人信息
    final http.Response response = await http.get(
      Uri.parse('https://people.googleapis.com/v1/people/me/connections'
          '?requestMask.includeField=person.names'),
      headers: await user.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) as Map<String, dynamic>;
    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'] as List<dynamic>?;
    final Map<String, dynamic>? contact = connections?.firstWhere(
          (dynamic contact) => contact['names'] != null,
      orElse: () => null,
    ) as Map<String, dynamic>?;
    if (contact != null) {
      final Map<String, dynamic>? name = contact['names'].firstWhere(
            (dynamic name) => name['displayName'] != null,
        orElse: () => null,
      ) as Map<String, dynamic>?;
      if (name != null) {
        return name['displayName'] as String?;
      }
    }
    return null;
  }

  //登录
  Future<void> _handleSignIn() async {
    try {
      await _googleSignIn.signIn();
    } catch (error) {
      print(error);
    }
  }

  //登出
  Future<void> _handleSignOut() => _googleSignIn.disconnect();

  //获取谷歌日历列表信息(sdk方式)
  getCalendarEvent() async {
    var httpClient = (await _googleSignIn.authenticatedClient())!;
    var calendar = CalendarApi(httpClient);
    var calEvents = calendar.events.list("primary");
    calEvents.then((events) => {
      events.items?.forEach((event) => print("EVENT ${event.summary}"))
    });
  }

  //获取谷歌日历列表信息(http方式)
  handleGetCalendar(GoogleSignInAccount user) async {
    final http.Response response = await http.get(
      Uri.parse('https://www.googleapis.com/calendar/v3/users/me/calendarList/primary'),//api查看官方文档
      headers: await user.authHeaders,//在请求头中添加登录信息
    );
    if (response.statusCode != 200) {
      print('Calendar API ${response.statusCode} response: ${response.body}');
    } else {

    }
  }


  //界面展示
  Widget _buildBody() {
    final GoogleSignInAccount? user = _currentUser;
    if (user != null) {
      return Column(
        mainAxisAlignment: MainAxisAlignment.spaceAround,
        children: <Widget>[
          ListTile(
            leading: GoogleUserCircleAvatar(
              identity: user,
            ),
            title: Text(user.displayName ?? ''),
            subtitle: Text(user.email),
          ),
          const Text('Signed in successfully.'),
          Text(_contactText),
          ElevatedButton(
            onPressed: ()=>handleGetCalendar(user),
            child: const Text('getCalendarEvent http'),
          ),
          ElevatedButton(
            onPressed: getCalendarEvent,
            child: const Text('getCalendarEvent'),
          ),
          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'),
          ),
        ],
      );
    }
  }

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

pubspec.yaml

dependencies:
  flutter:
    sdk: flutter

  flutter_signin_button: ^2.0.0
  google_sign_in: ^5.1.0
  extension_google_sign_in_as_googleapis_auth: ^2.0.7
  googleapis: ^9.2.0
  googleapis_auth: ^1.3.1
  url_launcher: ^6.1.5

dev_dependencies:
  flutter_test:
    sdk: flutter
  drive: 1.0.0-1.0.nullsafety.1
  flutter_driver:
    sdk: flutter
  http: ^0.13.3
  flutter_lints: ^2.0.0
其他参考

Flutter: Use Google Calendar API — Adding the events to Calendar

将dart和flutter与Google Calendar API结合使用以获取用户日历上的事件列表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值