# #android #firebase #kotlin #firebase-authentication
Вопрос:
Я разрабатываю приложение для Android, которое использует аутентификацию Firebase. После создания нового пользователя я отправляю электронное письмо с подтверждением.
Firebase.auth.currentUser?.let {user ->
user.sendEmailVerification().addOnCompleteListener {verificationTask ->
if(verificationTask.isSuccessful){
_verificationSuccess.value = true
} else {
_verificationError.value = verificationTask.exception
}
}
}
В моем манифесте я добавил фильтр намерений, который открывает мое приложение, когда пользователь пытается открыть ссылку для проверки.
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<category android:name="android.intent.category.BROWSABLE"/>
<data
android:host="test-project.firebaseapp.com"
android:scheme="https"/>
</intent-filter>
Проблема в том, что, когда ссылка открывает мое приложение, электронная почта не проверяется. У меня есть эта проверка, которая всегда возвращает false
if(Firebase.auth.currentUser.isEmailVerified){
//Email verified
} else {
throw Exception("Email not verified")
}
Только когда ссылка для проверки открыта в веб-обозревателе, проверка возвращает значение true. Как я могу проверить электронную почту в своем приложении?
Ответ №1:
Применив фильтр намерений, который у вас есть, вы сообщили Android, что будете обрабатывать все целевые веб-запросы https://test-project.firebaseapp.com
. Теперь, когда ваше приложение заблокировало просмотр по этому URL-адресу, теперь вам нужно сделать запрос на сервер от имени пользователя.
По умолчанию, когда вы отправляете пользователю подтверждение электронной почты, он получит электронное письмо со ссылкой, которая выглядит следующим образом:
https://<PROJECT_ID>.firebaseapp.com/__/auth/action?mode=verifyEmailamp;oobCode=<VERIFICATION_CODE>amp;apiKey=<API_KEY>amp;lang=<LANGUAGE>
Примечание .Эти ссылки можно настроить с помощью пользовательских обработчиков действий или использовать динамические ссылки, чтобы не перехватывать все, к чему вы стремитесь https://test-project.firebaseapp.com
.
Поскольку пользователь может захотеть посетить веб-сайт вашего приложения в браузере, вам следует сделать фильтр намерений более конкретным для обработки действий по электронной почте.
<intent-filter android:label="@string/filter_view_handle_action_code">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https"
android:host="test-project.firebaseapp.com"
android:pathPrefix="/__/auth/action" />
</intent-filter>
Отказ от ответственности: Я не проверял, работает ли приведенный ниже метод, но теоретически он должен работать.
Если вы перехватываете такой URL-адрес, вам необходимо обработать его в onCreate
методе:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = this.getIntent();
if (intent.hasCategory(android.intent.category.BROWSABLE)) {
// intent came from browser
Uri data = intent.getData();
String mode = data.getQueryParameter("mode");
String oobCode = data.getQueryParameter("oobCode");
if (mode != "verifyEmail" || oobCode == null) {
Log.i("MyActivity", "Started with unexpected browsable intent");
return;
}
handleVerifyEmailActionCode(oobCode);
}
}
private handleVerifyEmailActionCode(String oobCode) {
String email = null;
FirebaseAuth.getInstance().checkActionCode(oobCode)
.onSuccessTask( actionCodeResult -> {
if (actionCodeResult.getOperation() != ActionCodeResult.VERIFY_EMAIL) {
throw new UnsupportedActionCodeOperationException(actionCodeResult.getOperation());
}
email = actionCodeResult.getInfo().getEmail();
return FirebaseAuth.getInstance().applyActionCode(oobCode);
})
.addOnCompleteListener( applyActionCodeTask -> {
if (!applyActionCodeTask.isSuccessful()) {
Exception ex = applyActionCodeTask.getException();
// TODO: Handle exceptions
Toast.makeText(getApplicationContext(), "Failed to verify email. " ex.getMessage(), Toast.LENGTH_SHORT).show();
return;
}
// email verified successfully!
// do something interesting
Toast.makeText(getApplicationContext(), email " was verified!", Toast.LENGTH_SHORT).show();
FirebaseUser user = FirebaseAuth.getCurrentUser(); // WARN: May not have finished initializing yet?
if (user != null amp;amp; user.getEmail() == email) {
user.reload()
.addOnFailureListener(ex -> {
Log.e(MyActivity.class, "Failed to refresh user token: " ex.getMessage());
});
} else {
Log.i(
MyActivity.class,
user == null
? "User wasn't signed in, skipping reload"
: "User email mismatch, skipping reload"
);
}
});
}
/**
* Custom exception to be used when a OOB code's `ActionCodeResult.Operation`
* doesn't match what it was expected to be.
*
* @see https://firebase.google.com/docs/reference/android/com/google/firebase/auth/ActionCodeResult#constant-summary
*/
public class UnsupportedActionCodeOperationException extends Exception {
protected int operation;
public UnsupportedActionCodeOperationException(int operation) {
super("The ActionCodeResult.Operation value of " operation " is not supported");
this.operation = operation;
}
public int getOperation() {
return this.operation;
}
}