Flutter Google Sign-In 插件 google_sign_in_tizen 的使用
Flutter Google Sign-In 插件 google_sign_in_tizen 的使用
google_sign_in_tizen
google_sign_in_tizen
是对 google_sign_in
插件的 Tizen 实现。
使用方法
此插件不是官方支持的实现。因此,在你的 pubspec.yaml
文件中,你需要同时包含 google_sign_in
和 google_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 存储在代码中被认为是一个不良实践,因为它暴露了安全漏洞。你应该采取额外的步骤来保护你的客户端凭据。
-
不要将凭据上传到公共存储库
任何人都可以访问你的凭据并冒充你的应用。确保不要在任何源代码存储库中上传生产环境的凭据。请查看示例应用程序中的
credentials.dart
文件中的注释。 -
在生产环境中混淆代码
即使通过反向工程也可以提取 client secret,但可以通过 代码混淆 来增加难度。
flutter-tizen build tpk --obfuscate --split-debug-info=/<project-name>/<directory>
更多信息请参阅 Obfuscating Dart code。
将插件的 navigatorKey 对象分配给 MaterialApp 或 CupertinoApp
在使用设备流进行 Google Sign-In 时,客户端会显示一个包含 user_code 和 verification url 的小部件,并指示用户在另一台设备(例如移动电话上的浏览器)上访问验证 URL 并输入 user_code。当 GoogleSignInTizen.navigatorKey
被分配给 MaterialApp
或 CupertinoApp
的 navigatorKey
参数时,插件能够显示此小部件。
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
更多关于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。
- 打开 Google API 控制台。
- 创建一个新项目或选择现有项目。
- 导航到“凭据”页面,然后点击“创建凭据”并选择“OAuth 客户端 ID”。
- 选择“Web 应用程序”作为应用程序类型。
- 在“授权重定向 URI”中添加
https://your-domain.com/oauth2callback
(如果你没有域名,可以使用http://localhost:8080
作为占位符)。 - 点击“创建”并记下生成的客户端 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