我正在使用 firebase flutter 实现电话身份验证。但是有一个问题

Posted

技术标签:

【中文标题】我正在使用 firebase flutter 实现电话身份验证。但是有一个问题【英文标题】:I am implementing phone authentication using firebase flutter. But there's a problem 【发布时间】:2021-06-05 01:16:39 【问题描述】:

我想使用手机验证短信登录,每当新用户打开应用程序时,他都会输入他的电话号码并点击验证按钮,一旦点击,用户将在他的手机中收到一条验证短信,他将输入在验证文本字段中。但是当我运行该应用程序时,它会启动,当我输入电话号码并单击验证按钮时,该应用程序只是自行关闭而不是向我发送消息。代码如下:

    import 'dart:async';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:sms_autofill/sms_autofill.dart';

Future<void> main() async 
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());


class MyApp extends StatelessWidget 
  @override
  Widget build(BuildContext context) 
    return MaterialApp(
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(title: 'Flutter Auth Demo'),
    );
  


class MyHomePage extends StatefulWidget 
  MyHomePage(Key key, this.title) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();


class _MyHomePageState extends State<MyHomePage> 

  final FirebaseAuth _auth = FirebaseAuth.instance;
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  final TextEditingController _phoneNumberController = TextEditingController();
  final TextEditingController _smsController = TextEditingController();
  String _verificationId;
  final SmsAutoFill _autoFill = SmsAutoFill();

  void verifyPhoneNumber() async 

  //  Callback for when the user has already previously signed in with this phone no. on this device
    PhoneVerificationCompleted verificationCompleted = (PhoneAuthCredential phoneAuthCredential) async 
      await _auth.signInWithCredential(phoneAuthCredential);
      showSnackbar("Phone no. automatically verified and user signed in as: $_auth.currentUser.uid");
    ;

    PhoneVerificationFailed verificationFailed = (FirebaseAuthException authException) 
      showSnackbar('Phone number verification failed. Code: $authException.code. Message:$authException.message');
    ;

  //  Callback for when the code is sent
    PhoneCodeSent phoneCodeSent = (String verificationId,[int forceResendToken]) async 
      showSnackbar("Please check your phone for the verification code.");
      _verificationId = verificationId;
    ;

    PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout = (String verificationId) async 
      showSnackbar("Verification Code: "+verificationId);
      _verificationId = verificationId;
    ;
    try 
      await _auth.verifyPhoneNumber(
          phoneNumber: _phoneNumberController.text,
          timeout: const Duration(seconds: 5),
          verificationCompleted: verificationCompleted,
          verificationFailed: verificationFailed,
          codeSent: phoneCodeSent,
          codeAutoRetrievalTimeout: codeAutoRetrievalTimeout
      );
     catch(e) 
      showSnackbar("Failed to verify phone number: $e");
    
  
  void showSnackbar(String message) 
    _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text(message)));
  

  void signInWithPhoneNumber() async 
    try
      final AuthCredential credential = PhoneAuthProvider.credential(
          verificationId: _verificationId,
          smsCode: _smsController.text
      );
      final User user = (await _auth.signInWithCredential(credential)).user;
      showSnackbar("Successfully signed in with uid: $user.uid");
    catch(e)
      showSnackbar("Failed to sign in: "+e.toString());
    
  
  @override
  Widget build(BuildContext context) 
    return Scaffold(
        appBar: AppBar(
          title: Text(widget.title),
        ),
        key: _scaffoldKey,
        resizeToAvoidBottomPadding: false,
        body: Padding(padding: const EdgeInsets.all(8),
          child: Padding(
              padding: EdgeInsets.all(16),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: <Widget>[
                  TextFormField(
                    controller: _phoneNumberController,
                    decoration: const InputDecoration(
                        labelText: 'Phone number (+xx xxx-xxx-xxxx)'
                    ),
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 16.0),
                    alignment: Alignment.center,
                    child: RaisedButton(
                        child: Text("Get current number"),
                        onPressed: () async => 
                          _phoneNumberController.text = await _autoFill.hint,
                          print("_phoneNumberController.text: $_phoneNumberController.text")
                        ,
                        color: Colors.greenAccent[700],
                    ),
                  ),
                  Container(
                    padding: EdgeInsets.symmetric(vertical: 16.0),
                    alignment: Alignment.center,
                    child: RaisedButton(
                        color: Colors.greenAccent[400],
                        child: Text("Verify Number"),
                        onPressed: () async 
                          verifyPhoneNumber();
                          Navigator.of(context).pop();
                        
                    ),
                  ),
                  TextFormField(
                    controller: _smsController,
                    decoration: const InputDecoration(labelText: 'Verification Code'),
                  ),
                  Container(
                    padding: EdgeInsets.only(top: 16.0),
                    alignment: Alignment.center,
                    child: RaisedButton(
                      color: Colors.greenAccent[200],
                      onPressed: () async 
                        signInWithPhoneNumber();
                      ,
                      child: Text("Sign In"),
                    ),
                  ),
                ],
              )
          ),
        )
    );
  

应用关闭时出现的错误是“设备连接丢失”:

E/androidRuntime(18860): 在 dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:196) E/AndroidRuntime(18860): 在 java.lang.ClassLoader.loadClass(ClassLoader.java:379) E/AndroidRuntime (18860): 在 java.lang.ClassLoader.loadClass(ClassLoader.java:312) E/AndroidRuntime(18860): ... 12 更多 I/Process (18860): 发送信号。 PID:18860 SIG:9

【问题讨论】:

看看这个答案***.com/a/66039511/11039164 它对我有用,谢谢。 【参考方案1】:

从此代码 sn-p remove Navigator.of(context).pop(); 它使您的应用弹出关闭应用程序的唯一屏幕,并最终显示失去连接,因为应用程序不再可见。

Container(
 padding: EdgeInsets.symmetric(vertical: 16.0),
 alignment: Alignment.center,
    child: RaisedButton(
      color: Colors.greenAccent[400],
        child: Text("Verify Number"),
           onPressed: () async 
              verifyPhoneNumber();
              Navigator.of(context).pop();
           
         ),
       ),

【讨论】:

是的,它也造成了问题,然后我删除了这个 pop() 行,它很好。

以上是关于我正在使用 firebase flutter 实现电话身份验证。但是有一个问题的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Flutter 和 Firebase 实时数据库实现邀请系统 [关闭]

使用 Flutter 的电子邮件进行 Firebase 身份验证

使用提供程序在 Flutter 中进行 Firebase 电话身份验证 [关闭]

使用flutter firebase在线/离线的用户存在

使用 BLoC 进行 Flutter Firebase 电话身份验证

Flutter Firebase前台推送通知未显示但后台正在运行