Flutter Google Sign-In 插件 google_sign_in_tizen 的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter Google Sign-In 插件 google_sign_in_tizen 的使用

google_sign_in_tizen

pub package

google_sign_in_tizen 是对 google_sign_in 插件的 Tizen 实现。

使用方法

此插件不是官方支持的实现。因此,在你的 pubspec.yaml 文件中,你需要同时包含 google_sign_ingoogle_sign_in_tizen 作为依赖项。

dependencies:
  google_sign_in: ^5.4.1
  google_sign_in_tizen: ^0.1.3

有关如何使用 google_sign_in 的详细说明,请访问 https://pub.dev/packages/google_sign_in#usage


Tizen 集成

google_sign_in_tizen 的实现基于 Google Sign-In for TVs and Limited Input Devices。请注意,该方法仅支持有限范围的 API,具体允许的范围请参见 Allowed scopes

插件使用了 OAuth 2.0 Device Authorization Grant(也称为设备流),与在官方平台上使用的 Authorization Code Grant with PKCE 授权流程不同。在设备流中,用户需要在另一台设备(如 PC、平板或桌面)上完成授权过程。

为了允许用户通过 google_sign_in 登录到他们的账户,你首先需要为你的应用创建凭据(即“Client ID”和“Client Secret”)。有关如何创建这些凭据,请参考 register your application for TVs and limited input devices

你还需要在应用中添加一些额外的代码以完全集成 google_sign_in 在 Tizen 上的功能。


添加 OAuth 凭证

与“Authorization Code Grant with PKCE”不同,“设备流”需要在 Google Sign-In 期间提供一个 client secret 参数。在调用 google_sign_in 的 API 之前,必须使用 GoogleSignInTizen.setCredentials 函数设置你的客户端的 OAuth 凭证。

import 'package:google_sign_in_tizen/google_sign_in_tizen.dart';

GoogleSignInTizen.setCredentials(
  clientId: 'YOUR_CLIENT_ID',
  clientSecret: 'YOUR_CLIENT_SECRET',
);

⚠️ 安全注意事项

将 client secret 存储在代码中被认为是一个不良实践,因为它暴露了安全漏洞。你应该采取额外的步骤来保护你的客户端凭据。

  1. 不要将凭据上传到公共存储库

    任何人都可以访问你的凭据并冒充你的应用。确保不要在任何源代码存储库中上传生产环境的凭据。请查看示例应用程序中的 credentials.dart 文件中的注释。

  2. 在生产环境中混淆代码

    即使通过反向工程也可以提取 client secret,但可以通过 代码混淆 来增加难度。

    flutter-tizen build tpk --obfuscate --split-debug-info=/<project-name>/<directory>

    更多信息请参阅 Obfuscating Dart code


将插件的 navigatorKey 对象分配给 MaterialApp 或 CupertinoApp

在使用设备流进行 Google Sign-In 时,客户端会显示一个包含 user_codeverification url 的小部件,并指示用户在另一台设备(例如移动电话上的浏览器)上访问验证 URL 并输入 user_code。当 GoogleSignInTizen.navigatorKey 被分配给 MaterialAppCupertinoAppnavigatorKey 参数时,插件能够显示此小部件。

import 'package:google_sign_in_tizen/google_sign_in_tizen.dart';

MaterialApp(
  title: 'Google Sign In',
  navigatorKey: GoogleSignInTizen.navigatorKey,
  home: const SignInDemo(),
);

如果你需要为 MaterialApp(或 CupertinoApp)分配自定义的 navigatorKey,则必须将该 key 设置为插件也要使用的 key。

import 'package:google_sign_in_tizen/google_sign_in_tizen.dart';

GoogleSignInTizen.navigatorKey = GlobalKey<NavigatorState>();
MaterialApp(
  title: 'Google Sign In',
  navigatorKey: GoogleSignInTizen.navigatorKey,
  home: const SignInDemo(),
);

必需的权限

在执行 Google Sign-In 期间,你的应用请求的网络操作需要 http://tizen.org/privilege/internet 权限。在应用的 <tizen-manifest.xml> 中添加所需的权限。

<privileges>
  <privilege>http://tizen.org/privilege/internet</privilege>
</privileges>

支持的设备

所有运行 Tizen 5.5 或更高版本的设备。


示例代码

以下是一个完整的示例代码,展示了如何在 Tizen 上使用 google_sign_in_tizen 进行 Google Sign-In。

// 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:google_sign_in/google_sign_in.dart';
import 'package:google_sign_in_tizen/google_sign_in_tizen.dart';
import 'package:http/http.dart' as http;

import 'credentials.dart' as credentials;

GoogleSignIn _googleSignIn = GoogleSignIn(
  scopes: [
    'email',
    'profile',
  ],
);

void main() {
  GoogleSignInTizen.setCredentials(
    clientId: credentials.cliendId,
    clientSecret: credentials.clientSecret,
  );
  runApp(
    MaterialApp(
      title: 'Google Sign In',
      navigatorKey: GoogleSignInTizen.navigatorKey,
      home: const SignInDemo(),
    ),
  );
}

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

  [@override](/user/override)
  State createState() => SignInDemoState();
}

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

  [@override](/user/override)
  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...';
    });
    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: [
          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: [
          const Text('You are not currently signed in.'),
          ElevatedButton(
            onPressed: _handleSignIn,
            child: const Text('SIGN IN'),
          ),
        ],
      );
    }
  }

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

更多关于Flutter Google Sign-In 插件 google_sign_in_tizen 的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter Google Sign-In 插件 google_sign_in_tizen 的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


google_sign_in_tizen 是一个用于在 Tizen 平台上实现 Google 登录的 Flutter 插件。它基于 google_sign_in 插件,但专门为 Tizen 设备进行了适配。以下是如何在 Flutter 项目中使用 google_sign_in_tizen 插件的步骤:

1. 添加依赖

首先,在 pubspec.yaml 文件中添加 google_sign_in_tizen 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  google_sign_in_tizen: ^1.0.0

然后运行 flutter pub get 来获取依赖。

2. 配置 Google API 控制台

在使用 Google 登录之前,你需要在 Google API 控制台中创建一个项目并配置 OAuth 2.0 客户端 ID。

  1. 打开 Google API 控制台
  2. 创建一个新项目或选择现有项目。
  3. 导航到“凭据”页面,然后点击“创建凭据”并选择“OAuth 客户端 ID”。
  4. 选择“Web 应用程序”作为应用程序类型。
  5. 在“授权重定向 URI”中添加 https://your-domain.com/oauth2callback(如果你没有域名,可以使用 http://localhost:8080 作为占位符)。
  6. 点击“创建”并记下生成的客户端 ID 和客户端密钥。

3. 初始化 Google Sign-In

在你的 Flutter 代码中,初始化 GoogleSignIn 并配置客户端 ID:

import 'package:flutter/material.dart';
import 'package:google_sign_in_tizen/google_sign_in_tizen.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: GoogleSignInScreen(),
    );
  }
}

class GoogleSignInScreen extends StatefulWidget {
  @override
  _GoogleSignInScreenState createState() => _GoogleSignInScreenState();
}

class _GoogleSignInScreenState extends State<GoogleSignInScreen> {
  final GoogleSignIn _googleSignIn = GoogleSignIn(
    scopes: [
      'email',
      'https://www.googleapis.com/auth/contacts.readonly',
    ],
  );

  Future<void> _handleSignIn() async {
    try {
      final GoogleSignInAccount? account = await _googleSignIn.signIn();
      if (account != null) {
        print('User signed in: ${account.displayName}');
      }
    } catch (error) {
      print('Error signing in: $error');
    }
  }

  Future<void> _handleSignOut() async {
    try {
      await _googleSignIn.signOut();
      print('User signed out');
    } catch (error) {
      print('Error signing out: $error');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Google Sign-In Tizen'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ElevatedButton(
              onPressed: _handleSignIn,
              child: Text('Sign in with Google'),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _handleSignOut,
              child: Text('Sign out'),
            ),
          ],
        ),
      ),
    );
  }
}

4. 处理登录和登出

在上面的代码中,_handleSignIn 方法用于处理用户登录,_handleSignOut 方法用于处理用户登出。你可以根据需要扩展这些方法,例如在登录成功后获取用户的详细信息或执行其他操作。

5. 运行应用

确保你的 Tizen 设备已连接并配置好开发环境,然后运行应用:

flutter run -d tizen
回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!