Firebase AuthログインをFacebookと統合するための https://firebase.google.com/docs/auth/Android/facebook-login からチュートリアルコードを正常にデプロイしました。 Firebase Authコンソールでユーザーが正常に作成されました。
ただし、ユーザーオブジェクトの[電子メール]フィールドが空(—)であることに気付きました。奇妙なことに、取得したトークンを使用してGraphRequestを使用して、プロバイダー結果オブジェクトから直接電子メール情報を正常に取得できました。
読んだドキュメントに基づいて( https://firebase.google.com/docs/reference/Android/com/google/firebase/auth/FirebaseUser.html#getEmail() )、メールフィールドログインプロバイダーから入力する必要があります。
いくつかの追加の奇妙な動作:
見逃したり、何か間違ったことをしたことがありますか?
ここに私のコードがあります:
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LOGIN_ACTIVITY";
private static final int RC_SIGN_IN = 777;
private EventBus eventBus;
private SweetAlertDialog pDialog;
private FirebaseAuth mAuth;
private FirebaseAuth.AuthStateListener mAuthListener;
private CallbackManager mCallbackManager;
private ImageView mPasswordVisibilityView;
private TextView txtPassword;
private boolean justEnteredAuthStateChanged = false;
private GoogleApiClient mGoogleApiClient;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(getApplicationContext());
setContentView(R.layout.login);
// Firebase
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull final FirebaseAuth firebaseAuth) {
final FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Util.logassert("Auth Provider = " + firebaseAuth.getCurrentUser().getProviderId()); // this is called twice, values of Provider = Firebase
Util.logassert("total provider = " + user.getProviderData().size()); // output = 2. "Firebase" and "facebook.com"
for (int i = 0; i < user.getProviderData().size(); i++) {
UserInfo info = user.getProviderData().get(i);
Util.logassert(info.getProviderId() + ", email = " + info.getEmail()); // both empty
Util.logassert("current provider = " + info.getProviderId() + " - " + info);
}
} else {
Util.logassert("onAuthStateChanged user logged out");
}
// ...
}
};
mAuth.addAuthStateListener(mAuthListener);
// Firebase Facebook TapAuth
// Initialize Facebook Login button
mCallbackManager = CallbackManager.Factory.create();
LoginManager.getInstance().registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Util.logassert("facebook:onSuccess:" + loginResult);
handleFacebookAccessToken(loginResult.getAccessToken());
Util.logassert("granted = " + loginResult.getRecentlyGrantedPermissions()); // output [email and public_profile]
Util.logassert("denied = " + loginResult.getRecentlyDeniedPermissions());
}
@Override
public void onCancel() {
Util.logassert("facebook:onCancel");
// ...
}
@Override
public void onError(FacebookException error) {
Util.logassert("facebook:onError" + error.getMessage());
// ...
}
});
FancyButton btnFacebook = (FancyButton) findViewById(R.id.btn_facebook_share);
btnFacebook.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
LoginManager.getInstance().logInWithReadPermissions(LoginActivity.this, Arrays.asList("public_profile", "email"));
Util.logassert("try facebook login");
}
});
txtPassword = (EditText) findViewById(R.id.input_password);
}
private void handleFacebookAccessToken(AccessToken token) {
Util.logassert("handleFacebookAccessToken:" + token);
GraphRequest request = GraphRequest.newMeRequest(
token,
new GraphRequest.GraphJSONObjectCallback() {
@Override
public void onCompleted(
JSONObject object,
GraphResponse response) {
// Application code
Log.v("LoginActivity", response.toString());
Util.logassert("graph res = " + response.getRawResponse());
try {
/* successfully output email address from graph request here */
FbGraphEvent event = new FbGraphEvent(response.getJSONObject().getString("email"), response.getJSONObject().getString("name"));
EventBus.getDefault().postSticky(event);
} catch (Exception e) {
Log.e("MomInvoice", "Error in parsing json fb graph", e);
}
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "email,name");
request.setParameters(parameters);
request.executeAsync();
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Util.logassert("signInWithCredential:onComplete:" + task.isSuccessful());
if (!task.isSuccessful()) {
Util.logassert("signInWithCredential failed coz = " + task.getException().getMessage());
Toast.makeText(LoginActivity.this, "Authentication failed :(",
Toast.LENGTH_SHORT).show();
}
}
});
}
@Override
public void onStart() {
super.onStart();
Util.logassert("masuk onStart LoginActivity");
}
@Override
protected void onStop() {
super.onStop();
}
@Override
protected void onDestroy() {
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
super.onDestroy();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (mCallbackManager != null) {
mCallbackManager.onActivityResult(requestCode, resultCode, data);
Util.logassert("hasilx " + requestCode + " = " + resultCode);
}
}
}
firebase-talk googleグループの投稿をここで読んだ後 https://groups.google.com/forum/#!topic/firebase-talk/gPGNq-IkTLo で、答えを見つけました。この問題は、Firebase Authのサインイン方法で「同じメールアドレスで複数のアカウントの作成を許可する」を使用しているために発生しました。
そこで、オプションを「同じメールアドレスで複数のアカウントが作成されるのを防ぐ」に変更し、現在は正常に機能するようにします。それは簡単です。同じメールアドレスを持つアカウントをマージするためにもっとロジックが必要なのは事実ですが、それでも大丈夫です。
たぶん同じ問題を抱えている他の誰もがこれを試すことができ、うまくいけば同様に解決されるでしょう。
Firebase authでメールが「-」に設定されている同じ問題が見つかりました。メールを読む許可がありませんでした。
LoginButton mFacebookSignInButton = (LoginButton) findViewById(R.id.facebook_sign_in_button);
mFacebookSignInButton.setReadPermissions("email", "public_profile");
これが将来同じ問題を抱えている人の助けになることを願っています。
一部のFacebookアカウントは携帯電話番号を使用して作成されるため、メールアドレスをリクエストするたびに空の文字列を取得します。
次の画像では、Facebookアカウントがプライマリ連絡先をメールアドレスまたはモバイルとして設定できることがわかります。数値。そのため、ユーザーが携帯電話番号をプライマリとしてマークしている場合、そのメールアドレスは取得できません。
私の場合、Facebookのアカウントを確認するのを忘れていましたので、最初は私の連絡先はプライマリ連絡先にも表示されませんでした。 ですので、メールアドレスを取得できない場合は、一般設定に移動して、プライマリアカウントがメールアドレスに設定されているかどうかを確認してください。
私は解決策を見つけました。ここに私のコードがあります
import Android.app.ProgressDialog;
import Android.content.Intent;
import Android.support.v7.app.AppCompatActivity;
import Android.os.Bundle;
import Android.view.View;
import Android.view.View.OnClickListener;
import Android.widget.ImageButton;
import com.app.pizzawheel.Common.Globals;
import com.facebook.AccessToken;
import com.facebook.AccessTokenTracker;
import com.facebook.CallbackManager;
import com.facebook.FacebookCallback;
import com.facebook.FacebookException;
import com.facebook.FacebookSdk;
import com.facebook.GraphRequest;
import com.facebook.GraphResponse;
import com.facebook.login.LoginManager;
import com.facebook.login.LoginResult;
import com.facebook.login.widget.LoginButton;
import com.google.Android.gms.tasks.OnCompleteListener;
import com.google.Android.gms.tasks.Task;
import com.google.firebase.auth.AuthCredential;
import com.google.firebase.auth.AuthResult;
import com.google.firebase.auth.FacebookAuthProvider;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.auth.FirebaseUser;
import Android.support.annotation.NonNull;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import Java.util.Arrays;
public class GetStartedActivity extends AppCompatActivity {
CallbackManager callbackManager;
AccessTokenTracker accessTokenTracker;
AccessToken accessToken;
private FirebaseAuth mAuth;
ProgressDialog progress;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FacebookSdk.sdkInitialize(this.getApplicationContext());
setContentView(R.layout.activity_getstarted);
getSupportActionBar().hide();
mAuth = FirebaseAuth.getInstance();
callbackManager = CallbackManager.Factory.create();
final LoginButton loginButton = (LoginButton) findViewById(R.id.fb_login);
final ImageButton btnFBLogin = (ImageButton)findViewById(R.id.btn_fb_login);
loginButton.setReadPermissions("email", "public_profile");
if (loginButton != null) {
loginButton.registerCallback(callbackManager,
new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
// App code
loginButton.setVisibility(View.INVISIBLE);
btnFBLogin.setVisibility(View.VISIBLE);
accessToken = loginResult.getAccessToken();
FBLogin();
}
@Override
public void onCancel() {
// App code
}
@Override
public void onError(FacebookException exception) {
// App code
}
});
}
if(AccessToken.getCurrentAccessToken()!=null) {
accessToken = AccessToken.getCurrentAccessToken();
btnFBLogin.setVisibility(View.VISIBLE);
}
btnFBLogin.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
FBLogin();
}
});
}
private void FBLogin(){
progress = new ProgressDialog(GetStartedActivity.this);
progress.setMessage("Please Wait...");
progress.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progress.setCancelable(false);
progress.show();
AuthCredential credential = FacebookAuthProvider.getCredential(accessToken.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(GetStartedActivity.this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
GraphRequest request = GraphRequest.newMeRequest(accessToken, new GraphRequest.GraphJSONObjectCallback(){
@Override
public void onCompleted(JSONObject object, GraphResponse response) {
progress.hide();
progress.dismiss();
try {
Globals.email_address = object.getString("email");
Globals.first_name = object.getString("first_name");
Globals.last_name = object.getString("last_name");
} catch (JSONException e) {
e.printStackTrace();
}
Intent intent = new Intent(GetStartedActivity.this, WelcomeActivity.class);
startActivity(intent);
finish();
}
});
Bundle parameters = new Bundle();
parameters.putString("fields","id,email,first_name,last_name");
request.setParameters(parameters);
request.executeAsync();
// Sign in success, update UI with the signed-in user's information
} else {
progress.hide();
progress.dismiss();
// If sign in fails, display a message to the user.
// Log.w(TAG, "signInWithCredential:failure", task.getException());
// Toast.makeText(FacebookLoginActivity.this, "Authentication failed.",
// Toast.LENGTH_SHORT).show();
// updateUI(null);
}
}
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
callbackManager.onActivityResult(requestCode, resultCode, data);
}
@Override
public void onDestroy() {
super.onDestroy();
}
}
このように解決しました
_facebookLoginButton.setReadPermissions(Arrays.asList(
"email", "public_profile"));
_facebookLoginButton.registerCallback(callbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
credential = FacebookAuthProvider.getCredential(facebookAccessToken.getToken());
GraphRequest request = GraphRequest.newMeRequest(
loginResult.getAccessToken(), (me, response) -> {
if (response.getError() != null) {
// handle error
hideProgress();
Logcum.w(" GirisActivity ", "facebookSignIn: Giriş anında hata oluştu", response.getError().getException());
} else {
user_email = response.getJSONObject().optString("email");
facebookSignInCredential(user_email);
}
});
Bundle parameters = new Bundle();
parameters.putString("fields", "email");
request.setParameters(parameters);
request.executeAsync();
}
@Override
public void onCancel() {
Log.d(TAG, "facebook:onCancel");
hideProgress(); // progresi gizle
}
@Override
public void onError(FacebookException error) {
Log.d(TAG, "facebook:onError", error);
hideProgress(); // progresi gizle
}
});
@Muhammad Rayhan。私も同じことをしました。 Fb GraphRequestから電子メールを受け取った後、FirebaseUser.updateEmail()
を使用しました。問題なく機能しました。
同じ問題がありました。これは、読み取り許可なしでFacebookログインを作成し、ログインをテストしたため、すべてOKでした。その後、メールの読み取り許可を追加しました。
Facebookは更新された権限ダイアログを表示しましたが、Firebaseは新しいメールを取得しませんでした。
Firebaseコンソールでユーザーを削除する必要がありました。アプリを再度実行してログインすると、メールが表示されます。