首页 > 解决方案 > Flutter Firebase Phone Authentication 在验证时使 iOS 上的应用程序崩溃

问题描述

我正在使用电话身份验证与谷歌身份验证链接。这个实现之前是有效的,但突然之间就让应用程序崩溃了。

这是我的完整代码

import 'package:FaithMeetsLove/controller/authentication.dart';
import 'package:another_flushbar/flushbar.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_progress_hud/flutter_progress_hud.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:intl_phone_number_input/intl_phone_number_input.dart';
import 'package:pin_code_text_field/pin_code_text_field.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../constant/contact.dart';
import 'gender.dart';

class NumberOTP extends StatefulWidget {
  NumberOTP({Key key}) : super(key: key);

  @override
  _NumberOTPState createState() => _NumberOTPState();
}

class _NumberOTPState extends State<NumberOTP> {
  final phoneNumberInput = TextEditingController();
  final otpNumberInput = TextEditingController();
  String number123 = '';
  PhoneNumber number = PhoneNumber(isoCode: 'AF');
  String verificationId;

  Future<bool> signIn() async {
    try {
      //!here is where phone auth start
      final AuthCredential phoneCredential = PhoneAuthProvider.credential(
        verificationId: verificationId,
        smsCode: otpNumberInput.text,
      );
      final getuser =
          await (auth.currentUser?.linkWithCredential(phoneCredential));
      final user = getuser?.user;
      await firestore.collection('users').doc(user?.uid).update({
        'phoneNumber': user?.phoneNumber,
      });
      SharedPreferences pref = await SharedPreferences.getInstance();
      await pref.setBool('phoneAuth', true);
      return true;
    } catch (e) {
      return false;
    }
  }

  Future<void> phoneAuth(BuildContext context) async {
    try {
      final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
          (String verId) {
        verificationId = verId;
      };
      final PhoneCodeSent codeSent = (String verId, [int forceCodeResend]) {
        verificationId = verId;
        setState(() {
          next = false;
        });
      };
      final PhoneVerificationCompleted verificationCompleted =
          (phoneAuthCredential) {
        print('verified');
      };
      final PhoneVerificationFailed verificationFailed = (error) async {
        print('$error');
        await Flushbar(
          title: 'Error !!!',
          message: 'Error Phone Verification $error',
          duration: Duration(seconds: 3),
        ).show(context);
      };

      await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: number123,
        verificationCompleted: verificationCompleted,
        verificationFailed: verificationFailed,
        codeSent: codeSent,
        codeAutoRetrievalTimeout: codeAutoRetrievalTimeout,
        timeout: Duration(seconds: 10),
      );
    } catch (e) {
      await Flushbar(
        title: 'OTP Error !!!',
        message: 'Error in OTP $e',
        duration: Duration(seconds: 3),
      ).show(context);
    }
  }

  bool next = true;
  bool hasError = false;
  bool checkIfIsValid = false;

  Widget inputNumber() {
    return Scaffold(
      body: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () {
          FocusScope.of(context).unfocus();
        },
        child: ProgressHUD(
          child: Builder(
            builder: (context) => Container(
              padding: const EdgeInsets.all(17.0),
              height: double.infinity,
              width: double.infinity,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topRight,
                  end: Alignment.bottomLeft,
                  colors: [
                    Constants.color1,
                    Constants.color2,
                  ],
                ),
              ),
              child: Center(
                child: Container(
                  alignment: Alignment.center,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(10.0),
                        child: CircleAvatar(
                          radius: 60,
                          backgroundColor: Colors.white.withOpacity(0.4),
                          child: Icon(
                            FontAwesomeIcons.phoneAlt,
                            color: Colors.white,
                            size: 30,
                          ),
                        ),
                      ),
                      Flexible(
                        child: Text(
                          'Phone Number',
                          style: GoogleFonts.raleway(
                            textStyle: TextStyle(
                              fontSize: 35,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                      Flexible(
                        child: Padding(
                          padding: const EdgeInsets.all(15.0),
                          child: Text(
                            'Input Your Phone Number that will be Associated with your account',
                            textAlign: TextAlign.center,
                            style: GoogleFonts.raleway(
                              textStyle: TextStyle(
                                fontSize: 15,
                                color: Colors.white,
                              ),
                            ),
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(
                            vertical: 15.0, horizontal: 180),
                        child: Divider(
                          thickness: 5,
                          color: Colors.white.withOpacity(0.6),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: Container(
                          child: InternationalPhoneNumberInput(
                            maxLength: 11,
                            inputDecoration: InputDecoration(
                              focusedBorder: OutlineInputBorder(
                                borderSide:
                                    BorderSide(color: Colors.white, width: 1.0),
                                borderRadius: BorderRadius.circular(15),
                              ),
                              enabledBorder: OutlineInputBorder(
                                borderSide:
                                    BorderSide(color: Colors.white, width: 1.0),
                                borderRadius: BorderRadius.circular(15),
                              ),
                              hintText: 'Number',
                              hintStyle: TextStyle(
                                color: Colors.white,
                              ),
                            ),
                            textStyle:
                                TextStyle(color: Colors.white, fontSize: 25),
                            onInputChanged: (PhoneNumber number) {
                              number123 = number.phoneNumber;
                              print(number.phoneNumber);
                            },
                            onInputValidated: (bool value) {
                              checkIfIsValid = value;
                              print(value);
                            },
                            selectorConfig: SelectorConfig(
                              selectorType: PhoneInputSelectorType.BOTTOM_SHEET,
                            ),
                            ignoreBlank: false,
                            autoValidateMode: AutovalidateMode.disabled,
                            selectorTextStyle:
                                TextStyle(color: Colors.white, fontSize: 18),
                            initialValue: number,
                            textFieldController: phoneNumberInput,
                            formatInput: false,
                            keyboardType: TextInputType.numberWithOptions(
                                signed: true, decimal: true),
                            inputBorder: OutlineInputBorder(),
                            onSaved: (PhoneNumber number) {
                              print('On Saved: $number');
                            },
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(vertical: 18.0),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Expanded(
                              child: Container(
                                height: 60,
                                child: TextButton(
                                  onPressed: () async {
                                    final progress = ProgressHUD.of(context);
                                    progress?.showWithText('Sending OTP');
                                    try {
                                      if (checkIfIsValid) {
                                        await phoneAuth(context);
                                        progress?.dismiss();
                                        await Flushbar(
                                          title: 'OTP',
                                          message: 'OTP Sent',
                                          duration: Duration(seconds: 3),
                                        ).show(context);
                                      } else {
                                        progress?.dismiss();
                                        await Flushbar(
                                          title: 'Ops!',
                                          message:
                                              'Correct Your Phone Number........',
                                          duration: Duration(seconds: 3),
                                        ).show(context);
                                      }
                                    } catch (e) {
                                      await Flushbar(
                                        title: 'Ops!',
                                        message: '$e',
                                        duration: Duration(seconds: 3),
                                      ).show(context);
                                    }
                                  },
                                  child: Icon(
                                    Icons.check,
                                    color: Colors.red,
                                  ),
                                  style: TextButton.styleFrom(
                                    shape: RoundedRectangleBorder(
                                        borderRadius:
                                            BorderRadius.circular(18.0),
                                        side: BorderSide(color: Colors.red)),
                                    backgroundColor: Colors.white,
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  Widget inputOtp() {
    return Scaffold(
      body: GestureDetector(
        behavior: HitTestBehavior.translucent,
        onTap: () {
          FocusScope.of(context).unfocus();
        },
        child: ProgressHUD(
          child: Builder(
            builder: (context) => Container(
              padding: const EdgeInsets.all(17.0),
              height: double.infinity,
              width: double.infinity,
              decoration: BoxDecoration(
                gradient: LinearGradient(
                  begin: Alignment.topRight,
                  end: Alignment.bottomLeft,
                  colors: [
                    Constants.color1,
                    Constants.color2,
                  ],
                ),
              ),
              child: Center(
                child: Container(
                  alignment: Alignment.center,
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Padding(
                        padding: const EdgeInsets.all(10.0),
                        child: CircleAvatar(
                          radius: 60,
                          backgroundColor: Colors.white.withOpacity(0.4),
                          child: Icon(
                            Icons.phone_android_rounded,
                            color: Colors.white,
                            size: 60,
                          ),
                        ),
                      ),
                      Flexible(
                        child: Text(
                          'We sent a code',
                          style: GoogleFonts.raleway(
                            textStyle: TextStyle(
                              fontSize: 35,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                      Flexible(
                        child: Padding(
                          padding: const EdgeInsets.all(15.0),
                          child: Text(
                            'Enter the Secure OTP that was sent to the associated number',
                            textAlign: TextAlign.center,
                            style: TextStyle(
                              fontSize: 15,
                              fontWeight: FontWeight.bold,
                              color: Colors.white,
                            ),
                          ),
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(
                            vertical: 15.0, horizontal: 180),
                        child: Divider(
                          thickness: 5,
                          color: Colors.white.withOpacity(0.6),
                        ),
                      ),
                      Container(
                        child: PinCodeTextField(
                          autofocus: false,
                          controller: otpNumberInput,
                          hideCharacter: false,
                          highlight: true,
                          highlightColor: Colors.blue,
                          defaultBorderColor: Colors.black,
                          hasTextBorderColor: Colors.green,
                          highlightPinBoxColor: Colors.white,
                          maxLength: 6,
                          hasError: hasError,
                          //maskCharacter: "",
                          onTextChanged: (text) {
                            setState(() {
                              hasError = false;
                            });
                          },
                          onDone: (text) {
                            print("DONE $text");
                            print("DONE CONTROLLER ${otpNumberInput.text}");
                          },
                          pinBoxWidth: 50,
                          pinBoxHeight: 50,
                          hasUnderline: false,
                          wrapAlignment: WrapAlignment.spaceAround,
                          pinBoxDecoration:
                              ProvidedPinBoxDecoration.roundedPinBoxDecoration,
                          pinTextStyle:
                              TextStyle(fontSize: 15.0, color: Colors.black),
                          pinTextAnimatedSwitcherTransition:
                              ProvidedPinBoxTextAnimation.scalingTransition,
                          pinTextAnimatedSwitcherDuration:
                              Duration(milliseconds: 300),
                          highlightAnimationBeginColor: Colors.black,
                          highlightAnimationEndColor: Colors.white12,
                          keyboardType: TextInputType.number,
                        ),
                      ),
                      Padding(
                        padding: const EdgeInsets.symmetric(
                          vertical: 18.0,
                        ),
                        child: Row(
                          mainAxisAlignment: MainAxisAlignment.center,
                          children: [
                            Expanded(
                              child: Container(
                                height: 60,
                                child: TextButton(
                                  onPressed: () async {
                                    final progress = ProgressHUD.of(context);
                                    progress?.showWithText('Please wait');
                                    try {
                                      final isSiging = await signIn();
                                      if (isSiging) {
                                        Navigator.push(
                                          context,
                                          MaterialPageRoute(
                                            builder: (_) => SelectGender(),
                                          ),
                                        );
                                        progress?.dismiss();
                                      } else {
                                        progress?.dismiss();
                                        await Flushbar(
                                          title: 'Ops!',
                                          message:
                                              'Number already use or Wrong OTP',
                                          duration: Duration(seconds: 3),
                                        ).show(context);
                                      }
                                    } catch (e) {
                                      progress?.dismiss();
                                      await Flushbar(
                                        title: 'Ops!',
                                        message: '$e',
                                        duration: Duration(seconds: 3),
                                      ).show(context);
                                    }
                                  },
                                  child: Icon(
                                    Icons.check,
                                    color: Colors.red,
                                  ),
                                  style: TextButton.styleFrom(
                                    shape: RoundedRectangleBorder(
                                        borderRadius:
                                            BorderRadius.circular(18.0),
                                        side: BorderSide(color: Colors.red)),
                                    backgroundColor: Colors.white,
                                  ),
                                ),
                              ),
                            ),
                          ],
                        ),
                      )
                    ],
                  ),
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return next ? inputNumber() : inputOtp();
  }

  Widget makeInput({
    hintText,
    TextEditingController controller,
  }) {
    return TextField(
      controller: controller,
      textAlign: TextAlign.center,
      cursorColor: Colors.white,
      keyboardType: TextInputType.phone,
      decoration: InputDecoration(
        contentPadding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
        hintText: hintText,
        filled: true,
        fillColor: Colors.white.withOpacity(0.3),
        hintStyle: TextStyle(color: Colors.white.withOpacity(0.7)),
        focusedBorder: OutlineInputBorder(
          borderSide:
              BorderSide(color: Colors.red.withOpacity(0.2), width: 1.0),
          borderRadius: BorderRadius.circular(15),
        ),
        enabledBorder: OutlineInputBorder(
          borderSide:
              BorderSide(color: Colors.red.withOpacity(0.2), width: 1.0),
          borderRadius: BorderRadius.circular(15),
        ),
      ),
      style: TextStyle(
        fontSize: 25,
        color: Colors.white,
      ),
    );
  }
}

这是 info.plist

<string>APPL</string>
    <key>CFBundleShortVersionString</key>
    <string>$(FLUTTER_BUILD_NAME)</string>
    <key>CFBundleSignature</key>
    <string>????</string>
    <key>CFBundleURLTypes</key>
    <array>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>com.googleusercontent.apps.39...4890211-klbqki2me0m8fjccmb......</string>
            </array>
        </dict>
        <dict>
            <key>CFBundleTypeRole</key>
            <string>Editor</string>
            <key>CFBundleURLSchemes</key>
            <array>
                <string>fb368586070589462</string>
            </array>
        </dict>
    </array>
    <key>CFBundleVersion</key>
    <string>$(FLUTTER_BUILD_NUMBER)</string>
    <key>FacebookAppID</key>
    <string>368586070589462</string>
    <key>FacebookDisplayName</key>
    <string>FaithMeetsLove</string>
    <key>FirebaseAppDelegateProxyEnabled</key>
    <false/>
    <key>LSApplicationQueriesSchemes</key>
    <array>
        <string>fbapi</string>
        <string>fbapi20130214</string>
        <string>fbapi20130410</string>
        <string>fbapi20130702</string>
        <string>fbapi20131010</string>
        <string>fbapi20131219</string>
        <string>fbapi20140410</string>
        <string>fbapi20140116</string>
        <string>fbapi20150313</string>
        <string>fbapi20150629</string>
        <string>fbapi20160328</string>
        <string>fbauth</string>
        <string>fb-messenger-share-api</string>
        <string>fbauth2</string>
        <string>fbshareextension</string>
    </array>

我什至在调试时运行了仍然没有打印出错误。我立即单击以验证它只会使应用程序崩溃的数字。

标签: firebaseflutterdartfirebase-authentication

解决方案


推荐阅读