signly_google 0.1.0
signly_google: ^0.1.0 copied to clipboard
Flutter plugin-style package that performs one-shot Google Sign-In for Android and iOS and returns only the requested token.
import 'package:flutter/material.dart';
import 'package:signly_google/signly_google.dart';
void main() {
runApp(const ExampleApp());
}
class ExampleApp extends StatelessWidget {
const ExampleApp({super.key});
@override
Widget build(BuildContext context) {
return const MaterialApp(home: GoogleSignInExamplePage());
}
}
class GoogleSignInExamplePage extends StatefulWidget {
const GoogleSignInExamplePage({super.key});
@override
State<GoogleSignInExamplePage> createState() => _GoogleSignInExamplePageState();
}
class _GoogleSignInExamplePageState extends State<GoogleSignInExamplePage> {
final _client = SignlyGoogleClient();
final _clientIdController = TextEditingController();
final _serverClientIdController = TextEditingController();
final _scopesController = TextEditingController(text: 'openid,email,profile');
GoogleRequestedTokenType _requestedTokenType = GoogleRequestedTokenType.idToken;
String _result = 'No request yet.';
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Google Sign-In Plugin Example')),
body: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
TextField(
controller: _clientIdController,
decoration: const InputDecoration(labelText: 'clientId (optional)'),
),
TextField(
controller: _serverClientIdController,
decoration: const InputDecoration(labelText: 'serverClientId (optional)'),
),
TextField(
controller: _scopesController,
decoration: const InputDecoration(
labelText: 'Scopes (comma-separated)',
),
),
const SizedBox(height: 12),
DropdownButton<GoogleRequestedTokenType>(
value: _requestedTokenType,
isExpanded: true,
items: GoogleRequestedTokenType.values
.map(
(value) => DropdownMenuItem(
value: value,
child: Text(value.name),
),
)
.toList(),
onChanged: (value) {
if (value == null) {
return;
}
setState(() => _requestedTokenType = value);
},
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: _runSignIn,
child: const Text('Request token and user data'),
),
const SizedBox(height: 16),
Expanded(
child: SingleChildScrollView(
child: Text(_result),
),
),
],
),
),
);
}
Future<void> _runSignIn() async {
final scopes = _scopesController.text
.split(',')
.map((scope) => scope.trim())
.where((scope) => scope.isNotEmpty)
.toList();
try {
final response = await _client.signIn(
GoogleSignInRequest(
clientId: _clientIdController.text.trim().isEmpty
? null
: _clientIdController.text.trim(),
serverClientId: _serverClientIdController.text.trim().isEmpty
? null
: _serverClientIdController.text.trim(),
scopes: scopes,
requestedTokenType: _requestedTokenType,
),
);
setState(() {
_result = '''
userId: ${response.userId}
requestedTokenType: ${response.requestedTokenType.name}
requestedToken: ${response.requestedToken}
user.email: ${response.userData.email}
user.displayName: ${response.userData.displayName}
user.photoUrl: ${response.userData.photoUrl}
''';
});
} catch (error) {
setState(() {
_result = 'Error: $error';
});
}
}
@override
void dispose() {
_clientIdController.dispose();
_serverClientIdController.dispose();
_scopesController.dispose();
super.dispose();
}
}