android - 跳过 Flutter 应用上的登录页面(Google + FireBase)
问题描述
我正在制作一个 Flutter 应用程序,并希望通过 Google 强制登录。我已将登录后端与登录页面集成。该应用程序以 SplashScreen 作为根目录开始,然后进入登录页面。我将如下登录数据发送到 MainScreen。如果用户已经登录,如何跳过登录页面直接进入主屏幕?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:google_sign_in/google_sign_in.dart';
import 'mainscreen.dart';
import 'showup.dart';
import 'dart:async';
import 'dart:io';
import 'package:app_settings/app_settings.dart';
class LoginPage extends StatefulWidget {
@override
_LoginPageState createState() => _LoginPageState();
}
class _LoginPageState extends State<LoginPage> {
int dela = 500;
final FirebaseAuth _firebaseAuth = FirebaseAuth.instance;
final GoogleSignIn _googleSignIn = GoogleSignIn();
Future<FirebaseUser> _signIn(BuildContext context) async {
Scaffold.of(context).showSnackBar(SnackBar(
content: Text("Opening App..."),
duration: Duration(seconds: 1),
));
final GoogleSignInAccount googleUser = await _googleSignIn.signIn();
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication;
final AuthCredential credential = GoogleAuthProvider.getCredential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
);
FirebaseUser userDetails =
(await _firebaseAuth.signInWithCredential(credential)).user;
ProviderDetails providerInfo = new ProviderDetails(userDetails.providerId);
List<ProviderDetails> providerData = List<ProviderDetails>();
providerData.add(providerInfo);
UserDetails details = UserDetails(
userDetails.providerId,
userDetails.displayName,
userDetails.photoUrl,
userDetails.email,
userDetails.phoneNumber,
providerData);
Navigator.pushReplacement(
context,
CupertinoPageRoute(
fullscreenDialog: true,
builder: (context) => MainScreen(detailsUser: details)),
);
return userDetails;
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Builder(
builder: (context) => Padding(
padding: const EdgeInsets.fromLTRB(15.0, 0, 15, 0),
child: SingleChildScrollView(
child: Center(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 100,
),
ShowUp(
delay: dela+2000,
child: ClipRRect(
borderRadius: BorderRadius.circular(20),
child: Container(
color: Colors.white.withOpacity(0.15),
child: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
SizedBox(
height: 20,
),
Center(
child: Container(
child: Text(
"Welcome",
style: TextStyle(
fontSize: 25,
color: Colors.white,
),
),
),
),
SizedBox(height: 30),
ClipRRect(
borderRadius: BorderRadius.circular(30),
child: GestureDetector(
onTap: () async {
try{
final result = await InternetAddress.lookup('google.com');
if(result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
_signIn(context)
.then((FirebaseUser user) => print(user))
.catchError((e) => print(e));
}
}on SocketException catch (_) {
showDialog(context: context,
builder: (_) => AlertDialog(
contentPadding: EdgeInsets.fromLTRB(23,28,28,28),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20)),
elevation: 10,
backgroundColor: Colors.grey[900],
title: Text("Not Connected",
style: TextStyle(
color: Colors.white,
fontSize: 18,
fontWeight: FontWeight.bold
),
),
content: Text("You are not connected to the internet.\n\nCheck your connection and try again",
style: TextStyle(
color: Colors.white,
fontSize: 14)),
actions: <Widget>[
FlatButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel",
style: TextStyle(
color: Colors.white,
),)
),
FlatButton(
onPressed: () {
AppSettings.openDataRoamingSettings();
},
child: Text("Network Settings",
style: TextStyle(color: Colors.red),)
),
],
));
}
},
child: Container(
width: 210,
height: 50,
color: Colors.white,
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: <Widget>[
CircleAvatar(
child: Image.asset(
'Assets/google-logo.png'),
backgroundColor: Colors.white,
radius: 10,
),
SizedBox(width: 10),
Text("Continue with Google"),
],
),
),
),
),
SizedBox(
height: 30,
),
],
),
),
),
),
),
],
),
),
),
),
),
);
}
}
class UserDetails {
final String provDet;
final String userName;
final String photoURL;
final String userEmail;
final String userPhone;
final List<ProviderDetails> providerData;
UserDetails(this.provDet, this.userName, this.photoURL, this.userEmail,
this.userPhone, this.providerData);
}
class ProviderDetails {
ProviderDetails(this.providerDetails);
final String providerDetails;
}
我已经在 StackOverFlow 上搜索了答案,但没有找到确切的方法,即在不通过 LoginPage 登录的情况下如何将 UserDetails 发送到主屏幕。有没有办法在不废弃整个代码的情况下完成这项工作?
编辑
这就是 mainscreen.dart 的样子
import 'package:flutter/material.dart';
import 'login.dart';
class MainScreen extends StatefulWidget {
final UserDetails detailsUser;
MainScreen({Key key, @required this.detailsUser}) : super(key: key);
@override
_MainScreenState createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.black,
body: Column (
children: <Widget>[
Text(widget.detailsUser.userName),
Text(widget.detailsUser.userEmail), //basically accessed using widget.detailsUser.whatever
]),
);
}
}
解决方案
1) 首次登录时将数据保存到 sharedpreferences
2)在splashscreen中检查用户是否登录,如果登录,从sharedpreferences获取数据并传递给mainScreen
这是演示...
var islogin = // put your logic to check user is already login or not
if(islogin){
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => MainScreen(detailsUser: details),
),
);
}else{
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) => Login(),
),
);
}
推荐阅读
- android - 如何根据前景图像在android中动态更改状态栏的颜色?
- php - Laravel hasMany 关系选择特定列问题
- python-3.x - 调用服务器后如何恢复调用功能?
- asp.net - 如何将图像路径添加到数据库+将图像与相册关联?
- javascript - JavaScript 三元运算符表达式中的返回语句
- twitter-bootstrap-3 - Bootstrap3嵌套列冲突
- python - 删除python数据框中包含空格的行
- windows - 有没有办法使用powershell单击应用程序中的按钮
- .net - 如何让 sitecore 保持活力开箱即用
- python - Python Pandas 下一个序列号