Android上的Firebase电话验证

时间:2019-09-24 16:30:53

标签: firebase flutter firebase-authentication

我已经正确实现了Firebase电子邮件和Google登录,并且在iOS和Android上均可正常运行。 然后,我尝试实现“电话验证”功能,首先它在iPhone上不起作用,但随后我做了一些研究,似乎我必须上传一些APN,最后我正确设置了它,现在它可以在iPhone上使用,但是当我尝试将SMS发送到Android时,它没有收到,而是向我发送了一条消息,指示该代码已发送,就像在iPhone上一样。

最奇怪的是,如果我输入iPhone的手机号码,它将获得SMS代码。因此,我想知道是否必须像在iPhone上那样在Android上启用某种类型的Push通知,或者是否必须设置一些真实的开发人员帐户,原因是我现在没有Google的开发者帐户,或者我还有其他功能我不见了。

有人可以帮我吗?

我正在使用的auth方法是Flutter示例之一:

class _PhoneSignInSection extends StatefulWidget {
  _PhoneSignInSection(this._scaffold);

  final ScaffoldState _scaffold;
  @override
  State<StatefulWidget> createState() => _PhoneSignInSectionState();
}

class _PhoneSignInSectionState extends State<_PhoneSignInSection> {
  final TextEditingController _phoneNumberController = TextEditingController();
  final TextEditingController _smsController = TextEditingController();

  String _message = '';
  String _verificationId;

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          child: const Text('Test sign in with phone number'),
          padding: const EdgeInsets.all(16),
          alignment: Alignment.center,
        ),
        TextFormField(
          controller: _phoneNumberController,
          decoration:
              InputDecoration(labelText: 'Phone number (+x xxx-xxx-xxxx)'),
          validator: (String value) {
            if (value.isEmpty) {
              return 'Phone number (+x xxx-xxx-xxxx)';
            }
            return null;
          },
        ),
        Container(
          padding: const EdgeInsets.symmetric(vertical: 16.0),
          alignment: Alignment.center,
          child: RaisedButton(
            onPressed: () async {
              _verifyPhoneNumber();
            },
            child: const Text('Verify phone number'),
          ),
        ),
        TextField(
          controller: _smsController,
          decoration: InputDecoration(labelText: 'Verification code'),
        ),
        Container(
          padding: const EdgeInsets.symmetric(vertical: 16.0),
          alignment: Alignment.center,
          child: RaisedButton(
            onPressed: () async {
              _signInWithPhoneNumber();
            },
            child: const Text('Sign in with phone number'),
          ),
        ),
        Container(
          alignment: Alignment.center,
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Text(
            _message,
            style: TextStyle(color: Colors.red),
          ),
        )
      ],
    );
  }

  // Example code of how to verify phone number
  void _verifyPhoneNumber() async {
    setState(() {
      _message = '';
    });
    final PhoneVerificationCompleted verificationCompleted =
        (AuthCredential phoneAuthCredential) {
      _auth.signInWithCredential(phoneAuthCredential);
      setState(() {
        _message = 'Received phone auth credential: $phoneAuthCredential';
      });
    };

    final PhoneVerificationFailed verificationFailed =
        (AuthException authException) {
      setState(() {
        _message =
            'Phone number verification failed. Code: ${authException.code}. Message: ${authException.message}';
      });
    };

    final PhoneCodeSent codeSent =
        (String verificationId, [int forceResendingToken]) async {
      widget._scaffold.showSnackBar(SnackBar(
        content:
            const Text('Please check your phone for the verification code.'),
      ));

      _verificationId = verificationId;
    };

    final PhoneCodeAutoRetrievalTimeout codeAutoRetrievalTimeout =
        (String verificationId) {
      _verificationId = verificationId;
    };

    await _auth.verifyPhoneNumber(
        phoneNumber: _phoneNumberController.text,
        timeout: const Duration(seconds: 5),
        verificationCompleted: verificationCompleted,
        verificationFailed: verificationFailed,
        codeSent: codeSent,
        codeAutoRetrievalTimeout: codeAutoRetrievalTimeout);
  }

  // Example code of how to sign in with phone.
  void _signInWithPhoneNumber() async {
    final AuthCredential credential = PhoneAuthProvider.getCredential(
      verificationId: _verificationId,
      smsCode: _smsController.text,
    );
    final FirebaseUser user =
        (await _auth.signInWithCredential(credential));
    final FirebaseUser currentUser = await _auth.currentUser();
    assert(user.uid == currentUser.uid);
    setState(() {
      if (user != null) {
        _message = 'Successfully signed in, uid: ' + user.uid;
      } else {
        _message = 'Sign in failed';
      }
    });
  }
}

我的应用程序级别build.gradle具有以下依赖关系:

dependencies {
    implementation 'com.google.firebase:firebase-auth:19.0.0'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

如指南所述:

  

将Firebase身份验证Android库的依赖项添加到   您的模块(应用程序级)Gradle文件(通常为app / build.gradle):   实施'com.google.firebase:firebase-auth:19.0.0'

当然,我在同一build.gradle中有apply plugin: 'com.google.gms.google-services'

编辑:当它使用列入白名单的电话号码进行测试时,我已成功在Android上登录。

1 个答案:

答案 0 :(得分:1)

iPhone中的电话号码已成功从Android和iOS应用接收短信。
从Android或iOS应用接收的任何SMS中都没有收到Android中的电话号码。

因此,问题并非出在应用程序上,而是Android手机中的电话号码/ SIM卡。 如果手机在道路上或没有电话号码的任何限制,则Firebase可能不会发送SMS的情况会发生。显然,这是正在发生的事情。为确保这是问题所在,最好使用其他电话号码进行测试。如果使用新电话号码,我们可以使用特定的电话号码来解决问题,但不能使用您的电话。

您可能想重新编写以下代码(在这些行中):

_auth.signInWithCredential(phoneAuthCredential);
setState(() {
  _message = 'Received phone auth credential: $phoneAuthCredential';
});

_auth.signInWithCredential(phoneAuthCredential)
.then((user) {setState(){
  _message = 'Received phone auth credential: $phoneAuthCredential';
}})
.catchError((error) {
  _message = 'Something went wrong: $error';
});

因此,在通知用户之前,请确保确保_auth.signInWithCredential成功。

相关问题