本文不做名词解释,不说明如何配置开发者相关后台,在配置都没有问题的情况下,直接梭哈食用。使用的第三方库也都是主流高分的,不需要担心维护问题!如果刚拿到需求,直接看本文,可能有点懵逼,建议先收藏,去看一下相关的文章,再来结合代码,实现需求!
开发环境:
flutter sdk: 3.0.1 + dart sdk : 2.17.1

yaml文件配置:
firebase_auth: ^3.6.0
google_sign_in: ^5.2.4
google_sign_in_web: ^0.10.0+5
flutter_login_facebook: ^1.6.0
sign_in_with_apple: ^4.1.0
fireBaseUtils
///@author zhc 2022/3/14 1:28 下午
///@description: fireBase管理工具
import 'dart:convert'
import 'package:firebase_auth/firebase_auth.dart'
import 'package:flutter/material.dart'
import 'package:google_sign_in/google_sign_in.dart'
// import 'package:flutter_facebook_login/flutter_facebook_login.dart'
import 'package:flutter_login_facebook/flutter_login_facebook.dart'
import 'package:nft_wallet/scr/util/toast_utils.dart'
import 'package:sign_in_with_apple/sign_in_with_apple.dart'
typedef void onData<T>(T value)
class FireBaseUtils {
static final FirebaseAuth _auth = FirebaseAuth.instance
static final GoogleSignIn _googleSignIn = GoogleSignIn(
scopes: <String>[
'email',
//********这里注意 没有获取账号联系人的需求 不要打开这个初始化范围 ******************
//********如果需要其他或者联系人 还要在google play console 同意屏幕上开通这个api范围 然后提交申请批申请 ******************
// 'https://www.googleapis.com/auth/contacts.readonly',
],
)
static final FacebookLogin facebookSignIn = FacebookLogin(debug: false)
/// facebook登录
static Future<String?> signInFacebook() async {
try {
final FacebookLoginResult result = await facebookSignIn
.logIn(permissions: [FacebookPermission.email]).catchError((err) {
debugPrint("face book ${err.toString()}")
})
switch (result.status) {
case FacebookLoginStatus.success:
///这里没问题
final FacebookAccessToken? accessToken = result.accessToken
if (accessToken != null) {
final AuthCredential credential =
FacebookAuthProvider.credential(accessToken.token)
//这里的user可能为空
final User? user =
(await _auth.signInWithCredential(credential)).user
if (user != null) {
IdTokenResult idTokenResult = await user.getIdTokenResult(true)
final String? idToken = idTokenResult.token
return idToken
}
}
return null
case FacebookLoginStatus.cancel:
debugPrint('Login cancelled by the user.')
break
case FacebookLoginStatus.error:
debugPrint('Something went wrong with the login process.\n'
'Here's the error Facebook gave us: ${result.error.toString()}')
break
}
} on FirebaseAuthException catch (e) {
if (e.code == 'account-exists-with-different-credential') {
// ...https://github.com/firebase/flutterfire/issues/4612
// 您已经使用google账号注册过应用了,请使用google账号登录
debugPrint("code : true")
//amtalktest01@gmail.com
debugPrint("email : ${e.email}")
// final List<String> list = await FirebaseAuth.instance.fetchSignInMethodsForEmail(e.email!)
// final UserCredential uc = await FirebaseAuth.instance.signInWithCredential(e.credential!)
// uc.user?.linkWithCredential(e.credential!)
ToastUtils.show(
"You have already registered the app with your google account, please log in with your google account")
}
}
return null
}
/// google登录
static Future<String?> signInWithGoogle() async {
final GoogleSignInAccount? googleUser = await _googleSignIn.signIn()
if (googleUser != null) {
final GoogleSignInAuthentication googleAuth =
await googleUser.authentication
final AuthCredential credential = GoogleAuthProvider.credential(
accessToken: googleAuth.accessToken,
idToken: googleAuth.idToken,
)
final User? user = (await _auth.signInWithCredential(credential)).user
assert(user?.email != null)
assert(user?.displayName != null)
assert(!user!.isAnonymous)
assert(await user?.getIdToken() != null)
IdTokenResult? idTokenResult = await user?.getIdTokenResult(true)
return idTokenResult?.token
}
return null
}
/// Apple login
/// 参考 : https://stackoverflow.com/questions/62805312/android-sign-in-with-apple-and-firebase-flutter
/// 参考 :https://github.com/aboutyou/dart_packages/issues/91
static Future<String?> signInWithApple() async {
var redirectURL = "https://SERVER_AS_PER_THE_DOCS.glitch.me/callbacks/sign_in_with_apple"
var clientID = "AS_PER_THE_DOCS"
final appleIdCredential = await SignInWithApple.getAppleIDCredential(
scopes: [
AppleIDAuthorizationScopes.email,
AppleIDAuthorizationScopes.fullName,
],
webAuthenticationOptions: WebAuthenticationOptions(
clientId: clientID,
redirectUri: Uri.parse(
redirectURL))
)
final oAuthProvider = OAuthProvider('apple.com')
final credential = oAuthProvider.credential(
idToken: appleIdCredential.identityToken,
accessToken: appleIdCredential.authorizationCode,
)
final User? user = (await _auth.signInWithCredential(credential)).user
assert(user?.email != null)
assert(user?.displayName != null)
assert(!user!.isAnonymous)
assert(await user?.getIdToken() != null)
IdTokenResult? idTokenResult = await user?.getIdTokenResult(true)
return idTokenResult?.token
}
///获取当前用户
static User? currentUser() {
return FirebaseAuth.instance.currentUser
}
///用户改变监听
void listener(onData listener) {
FirebaseAuth.instance.userChanges().listen((event) {
listener(event)
// if (event != null && mounted) {
// setState(() {
// user = event
// })
// }
})
}
/// sign out.
static Future<void> signOut() async {
await FirebaseAuth.instance.signOut()
await _googleSignIn.signOut()
await facebookSignIn.logOut()
}
}
使用:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:nft_wallet/application.dart';
import 'package:nft_wallet/generated/l10n.dart';
import 'package:nft_wallet/main.dart';
import 'package:nft_wallet/scr/login/api/login_api.dart';
import 'package:nft_wallet/scr/login/models/user_info.dart';
import 'package:nft_wallet/scr/login/utils/firebase_utils.dart';
import 'package:nft_wallet/scr/util/provider_util.dart';
import 'package:nft_wallet/scr/util/sp_utils.dart';
import 'package:nft_wallet/scr/util/toast_utils.dart';
import '../binding_email.dart';
class OtherLogin extends StatefulWidget {
final bool isSelectedUserProtocol;
const OtherLogin({Key? key, required this.isSelectedUserProtocol})
: super(key: key);
@override
State<OtherLogin> createState() => _OtherLoginState();
}
class _OtherLoginState extends State<OtherLogin> {
@override
Widget build(BuildContext context) {
return Column(
children: [
const SizedBox(
height: 20,
),
_buildOneKeyText(context),
const SizedBox(
height: 20,
),
_buildQuickLogin(context),
const SizedBox(
height: 20,
),
],
);
}
Widget _buildOneKeyText(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
height: 1,
width: 24,
color: Colors.grey,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Text(
S.of(context).login_Other_login_methods,
style: const TextStyle(
color: Color(0xFF888888),
fontSize: 13,
fontWeight: FontWeight.bold),
),
),
Container(
height: 1,
width: 24,
color: Colors.grey,
),
],
),
),
);
}
_buildQuickLogin(BuildContext context) {
return SizedBox(
width: MediaQuery.of(context).size.width,
child: Center(
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
GestureDetector(
onTap: () async {
if (!widget.isSelectedUserProtocol) {
ToastUtils.show(S.of(context).selected_user_protocol);
return;
}
String? idToken;
try {
EasyLoading.show(
status: S.of(context).loading,
maskType: EasyLoadingMaskType.black,
dismissOnTap: false,
);
var user = FireBaseUtils.currentUser();
if (user != null) {
await FireBaseUtils.signOut();
}
idToken = await FireBaseUtils.signInWithGoogle();
} catch (e) {
debugPrint("signInWithGoogle Auth error !${e.toString()}");
} finally {
EasyLoading.dismiss();
}
if (idToken != null) {
handlerToken(idToken);
}
},
child: Image.asset(
"assets/login/gmail.png",
width: 42,
fit: BoxFit.cover,
),
),
const SizedBox(
width: 24,
),
GestureDetector(
onTap: () async {
if (!widget.isSelectedUserProtocol) {
ToastUtils.show(S.of(context).selected_user_protocol);
return;
}
String? idToken;
try {
EasyLoading.show(
status: S.of(context).loading,
maskType: EasyLoadingMaskType.black,
dismissOnTap: false,
);
var user = FireBaseUtils.currentUser();
if (user != null) {
await FireBaseUtils.signOut();
}
idToken = await FireBaseUtils.signInFacebook();
} catch (e) {
debugPrint("signInWithGoogle Auth error !${e.toString()}");
} finally {
EasyLoading.dismiss();
}
if (idToken != null) {
handlerToken(idToken);
}
},
child: Image.asset(
"assets/login/facebook.png",
width: 42,
fit: BoxFit.cover,
),
),
if (Platform.isIOS)
GestureDetector(
onTap: () async {
if (!widget.isSelectedUserProtocol) {
ToastUtils.show(S.of(context).selected_user_protocol);
return;
}
String? idToken;
try {
EasyLoading.show(
status: S.of(context).loading,
maskType: EasyLoadingMaskType.black,
dismissOnTap: false,
);
var user = FireBaseUtils.currentUser();
if (user != null) {
await FireBaseUtils.signOut();
}
idToken = await FireBaseUtils.signInWithApple();
} catch (e) {
debugPrint("signInWithApple Auth error !${e.toString()}");
} finally {
EasyLoading.dismiss();
}
if (idToken != null) {
handlerToken(idToken);
}
},
child: Padding(
padding: const EdgeInsets.only(left: 24),
child: Image.asset(
"assets/login/apple.png",
width: 42,
fit: BoxFit.cover,
),
),
)
],
),
),
);
}
handlerToken(String idToken) async {
try {
EasyLoading.show(
status: S.of(context).loading,
maskType: EasyLoadingMaskType.black,
dismissOnTap: false,
);
debugPrint("idToken $idToken");
final data = await LoginApi.sendIdToken(idToken);
debugPrint("data:$data");
if (data != null && data['code'] == -1405) {
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => BindEmailPage(
idToken: idToken,
)));
return;
}
if (data != null && data['code'] == 200) {
ProviderUtil.publicProvider().setLogin(true);
UserInfo info = UserInfo.fromJson(data["data"]);
Application.userInfo = info;
await SPUtils.saveUserInfo(info);
Navigator.of(context).push(MaterialPageRoute(
builder: (_) => App(),
));
} else {
ToastUtils.show("unknown error, try again");
}
} finally {
if (EasyLoading.isShow) {
EasyLoading.dismiss();
}
}
}
}