I haven't touched this code since August and it was working fine, but since I started back on it yesterday, I've been getting this error:
W/TAG: createUserWithEmail:failure
com.google.firebase.FirebaseException: An internal error has occurred. [ Unable to resolve host "www.googleapis.com":No address associated with hostname ]
All of my dependencies are set up correctly. I checked countless times as well as spending hours on YouTube, redownloaded the json file, updated Android Studio and my emulators. This is my last resort. I hope someone can help. Here's my code
mAuth.createUserWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "createUserWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
Toast.makeText(Register.this, "Sign up success! Taking you to login...",
Toast.LENGTH_SHORT).show();
} else {
// If sign in fails, display a message to the user.
Log.w(TAG, "createUserWithEmail:failure", task.getException());
Toast.makeText(Register.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Log.d(TAG, e.getMessage());
Log.d(TAG, "FAIL");
}
});
The last time I used firebase auth I used this code:
AuthUI.IdpConfig googleIdp = new AuthUI.IdpConfig.EmailBuilder()
.build();
startActivityForResult(AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(false)
.setTosAndPrivacyPolicyUrls("PolĂtica de privacidad", "http://twitter.com")
.setAvailableProviders(Arrays.asList(new AuthUI.IdpConfig.EmailBuilder().build(),
facebookIdp, googleIdp))
.setTheme(R.style.GreenTheme)
.setLogo(R.drawable.img_multi_login)
.build(), RC_SIGN_IN);
And for the result:
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == RC_SIGN_IN) {
if (resultCode == RESULT_OK) {
Toast.makeText(this, "Welcome", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "Something went wrong", Toast.LENGTH_SHORT).show();
}
}
}
And use an AuthStateListener to change the data of the user if something changed or if the user is logged or not.
I think this is the easiest way to implement firebase auth on Android.
Related
I am trying to make it so that the user can enter in various importation and that firebase can enter this information into the Runtime DB. However, when I press the button that makes the code below happen, it results in the progress bar loading forever. I tried throwing in the log to try to catch some exception, but no exceptions came up. On the firebase console, the user was not created in the authentication and nothing was added to the RunTime DB. I am not sure what is causing this to happen, and I would appreciate any and all help.
Code:
User user = new User(fullName, email, bio, username,location,realstatus,profilePic);
FirebaseDatabase db = FirebaseDatabase.getInstance();
DatabaseReference root = db.getReference().child("Users");
progressBar.setVisibility(ViewStub.VISIBLE);
mAuth.createUserWithEmailAndPassword(email,password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful()) {
Toast.makeText(Register.this, "Create User Succeeded", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(Register.this, "Failed to Authenticate :( ", Toast.LENGTH_SHORT).show();
}
}
});
root.push().setValue(user).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if(task.isSuccessful()) {
progressBar.setVisibility(ViewStub.GONE);
Toast.makeText(Register.this, "Data Saved", Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(Register.this, "Failed to Register User :( ", Toast.LENGTH_SHORT).show();
Log.e("Create user", "Failed to create user", task.getException());
}
}
});
Error:
com.google.firebase.FireBaseException:
An internal error has occured. [ socket failed EPERM:(Operation not permitted) ]
Add a completion listener to the createUser so you can know why it isn't working.
mAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(LoginActivity.this, task -> {
binding.progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
//get the error here with task.toString();
} else {
save your database data here
}
});
That will at least help you get to the bottom of why it is failing. Also make sure you have
enabled email auth in firebase console
Have properly set up your app, the SHA-1s, the google-services json and all
I'm trying to set up google sign in for my app but it keeps failing, I click on a button, get a popup, select account and a Toast pops up telling me that sign in failed. Any ways I can fix this? The problem lies in onActivityResult() method and the said Toast says "Auth went wrong". I've searched all over the internet but failed to find a solution or even a reason why this is happening. Line 80 is this
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
public class SignInActivity extends AppCompatActivity {
static final int GOOGLE_SIGN_IN = 2;
FirebaseAuth mAuth;
Button btn_login;
GoogleSignInClient mGoogleSignInClient;
FirebaseAuth.AuthStateListener mAuthListener;
#Override
protected void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sign_in);
btn_login = findViewById(R.id.login);
mAuth = FirebaseAuth.getInstance();
mAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
if (firebaseAuth.getCurrentUser() != null) {
Switch();
}
}
};
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(this, gso);
btn_login.setOnClickListener(v -> signIn());
}
private void signIn() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, GOOGLE_SIGN_IN);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == GOOGLE_SIGN_IN) {
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
try {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = task.getResult(ApiException.class);
firebaseAuthWithGoogle(account);
} catch (ApiException e) {
// Google Sign In failed, update UI appropriately
Log.w("TAG", "Google sign in failed", e);
Toast.makeText(SignInActivity.this, "Auth went wrong :/", Toast.LENGTH_SHORT).show();
// ...
}
}
}
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d("TAG", "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, task -> {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d("TAG", "signInWithCredential:success");
FirebaseUser user = mAuth.getCurrentUser();
Toast.makeText(SignInActivity.this, "Success!", Toast.LENGTH_SHORT).show();
updateUI(user);
Switch();
} else {
// If sign in fails, display a message to the user.
Log.w("TAG", "signInWithCredential:failure", task.getException());
Toast.makeText(SignInActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show();
updateUI(null);
}
});
}
}
2019-03-23 12:13:35.569 6312-6312/com.charpik.agropomocnik W/TAG: Google sign in failed
com.google.android.gms.common.api.ApiException: 10:
at com.google.android.gms.common.internal.ApiExceptionUtil.fromStatus(Unknown Source:4)
at com.google.android.gms.auth.api.signin.GoogleSignIn.getSignedInAccountFromIntent(Unknown Source:8)
at com.charpik.agropomocnik.SignInActivity.onActivityResult(SignInActivity.java:80)
at android.app.Activity.dispatchActivityResult(Activity.java:7701)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5037)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5084)
at android.app.ActivityThread.-wrap20(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2053)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7529)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.Zygote$MethodAndArgsCaller.run(Zygote.java:245)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:921)
I fixed the similar issue by using the latest version of the appcompat library.
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
If it's not the case, try without requestIdToken(getString(R.string.default_web_client_id)). And if the error is not occurred, you should check the credential part again.
Check these:
Is SHA-1 fingerprint correct?
Is SHA-1 fingerprint for debug or release?
Is package name correct?
Did you use the web application type client ID?
I've followed the instructions exactly, in fact, I even used the code from the Firebase helper in android studio. My issue is as such, nor login or failure to login is occurring with my code! What am I missing?
public void toSubscribe(View v) {
Log.d("OK", "this part first");
String strUsername, strPassword;
strUsername = ((EditText) findViewById(R.id.username)).getText().toString();
strPassword = ((EditText) findViewById(R.id.password)).getText().toString();
if (strUsername.matches("")) {
Toast.makeText(MainActivity.this, "You did not enter a username.", Toast.LENGTH_SHORT).show();
return;
}
if (strPassword.matches("")) {
Toast.makeText(MainActivity.this, "You did not enter a password.", Toast.LENGTH_SHORT).show();
return;
}
mAuth.signInWithEmailAndPassword(strUsername, strPassword)
.addOnCompleteListener(MainActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
Log.d("TAG", "signInWithEmail:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w("TAG", "signInWithEmail", task.getException());
Toast.makeText(MainActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}
Not much else to say... I tried using a new JSON file and it still doesn't work. I've Googled tons of stuff but nothing really worked.
please check the following:
1-you install and add Gson file correctly from firebase console
2- you enable firebase authentication from firebase console
3- you mAuth initialized correctly
In my Firebase application I created a fragment that allows users to update their information like namn & email and so far all is going well, however my issue is after the user have updated the information - the changes are not visible untill next relaunch of the application.
How can I reflect the changes directly from the databse without promoting the User to relaunch the app?
I have created a Method called restart(); that will like the name says says restart the application - But still the changes are not being reflected!
/**
* Update Name Only
*/
private void updateDisplayNameOnly() {
showProgress();
AuthCredential credential = EmailAuthProvider
.getCredential(FirebaseAuth.getInstance().getCurrentUser().getEmail(), mConfirm.getText().toString());
FirebaseAuth.getInstance().getCurrentUser().reauthenticate(credential)
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdate = new UserProfileChangeRequest.Builder()
.setDisplayName(mName.getText().toString())
//.setPhotoUri(Uri.parse("https://avatarfiles.alphacoders.com/862/86285.jpg"))
.build();
user.updateProfile(profileUpdate);
Log.d(TAG, "onComplete: User Profile updated");
Toast.makeText(getActivity(), "Name is updated", Toast.LENGTH_SHORT).show();
restartApp();
} else {
Toast.makeText(getActivity(), "Name was not updated", Toast.LENGTH_SHORT).show();
}
hideProgress();
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
hideProgress();
Toast.makeText(getActivity(), "You have entered wrong password", Toast.LENGTH_SHORT).show();
}
});
}
Restart Method
public void restartApp() {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
finish();
}
Firebase has a listener onDataChange(), so when you query data from firebase, make sure you implement that, see doc. If you want to reflect the change, implement it in this method (like resetting the text fields). There is no need for a restart method.
Update profile call is asynchronous, and its results are not available immediately, so for some time you'll still observe "obsolete" data.
When you call updateProfile, you get a task as a result. You can subscribe on completion of this task, and if it's completed successfully, then you will be able to get updated data from user instance. E.g.:
final FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
Log.i("MyActivity", "before updateProfile: username=" + currentUser.getDisplayName());
UserProfileChangeRequest profileUpdate = new UserProfileChangeRequest.Builder()
.setDisplayName("UPDATED_NAME")
.build();
final Task<Void> task = currentUser.updateProfile(profileUpdate);
Log.i("MyActivity", "after updateProfile: username=" + currentUser.getDisplayName());
task.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Log.i("MyActivity", "onComplete: username=" + currentUser.getDisplayName());
}
});
And here is an output:
I/MyActivity: before updateProfile: username=old name
I/MyActivity: after updateProfile: username=old name
I/MyActivity: onComplete: username=UPDATED_NAME
Also there is a method user.reload(), which force reload user data from Firebase server. This is useful when your client user cache is obsolete for some reason. It is also an asynchronous method, which gives you Task and you need to subscribe on its completion.
I'm writing this question and answer because I haven't seen a full solution to the integration of Google sign in on Android using Facebook's Parse SDK (or Sashido in my case) as a back-end without cloud code.
Related Questions:
How to link Google + signed in users on Parse backend on Android?
Google Plus Login issues - Parse.com
How would one go about integrating Google Sign in with Parse back-end without Cloud Code?
First of all, follow the steps provided by Android Developers on starting and implementing the integration.
Start Integrating Google Sign-In into Your Android App
Integrating Google Sign-In into Your Android App
In the onCreate your activity you need to build the GoogleSignInOptions
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
You can get your web_client_id when you add Google Services to your project to your Google Developers account. Find out more at: Creating a Google API Console project and client ID
Build your GoogleApiClient (make it a global instance private GoogleApiClient mGoogleApiClient;)
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this, new GoogleApiClient.OnConnectionFailedListener() {
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.e("Failed", "failed" + connectionResult.getErrorMessage());
}
})
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
Listen out for the click on the dedicated button for your Google sign in and then start a Auth.GoogleSignInApi.getSignIntent(mGoogleApiClient);
case R.id.btn_google:
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
break;
Make sure you've assigned a value to RC_SIGN_IN (I've done 1000)
Now start adding implementation to your onActivityResult method
// Result returned from launching the Intent from
// GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
handleSignInResult(result);
} else {
ParseFacebookUtils.onActivityResult(requestCode, resultCode, data);
}
Now to handle the sign in request:
`private void handleSignInResult(GoogleSignInResult result) {
Log.e("handleSignIn", "handleSignInResult:" + result.isSuccess());
if (result.isSuccess()) {
// Signed in successfully, show authenticated UI.
final GoogleSignInAccount acct = result.getSignInAccount();
if (acct != null) {
ParseQuery<ParseObject> query = ParseQuery.getQuery("_User");
query.setLimit(10000);
query.whereEqualTo("email", acct.getEmail());
query.findInBackground(new FindCallback<ParseObject>() {
#Override
public void done(List<ParseObject> objects, ParseException e) {
if (e == null) {
if (objects.size() == 0) {
saveNewUserGoogle(acct);
} else {
loginGoogleUser(objects.get(0), acct);
}
} else {
saveNewUserGoogle(acct);
}
}
});
}
} else {
Log.e("failed", "failed to sign in");
// Signed out, show unauthenticated UI.
}
}`
So what this method does is if the request to the GoogleSignIn Request is successful, get the account details, query the _User table in your database and to see if the email with the account matches. If it does, Log the user in.
private void loginGoogleUser(ParseObject j, GoogleSignInAccount acct) {
ParseUser.logInInBackground(j.getString("username"), String.valueOf(acct.getId()), new LogInCallback() {
public void done(ParseUser user, ParseException e) {
if (user != null) {
Intent i = new Intent(AllLoginActivity.this, MainActivity.class);
startActivity(i);
finish();
} else {
Log.e("failed", "could not be validated");
}
}
});
}
else sign the user up:
private void saveNewUserGoogle(GoogleSignInAccount acct) {
google = true;
final ParseUser user = new ParseUser();
String mFullName = acct.getDisplayName();
String mEmail = acct.getEmail();
String mProfilePic = String.valueOf(acct.getPhotoUrl());
String mUsername = acct.getId();
String password = acct.getId();
user.setUsername(mUsername);
user.setEmail(mEmail);
user.setPassword(password);
user.put("userEmail", mEmail);
user.put("uniqueID", mUsername);
user.put("name", mFullName);
user.put("loginMethod", "Google");
user.put("profilePicture", mProfilePic);
user.signUpInBackground(new SignUpCallback() {
public void done(ParseException e) {
if (e == null) {
Log.e("SaveTest", "Successful");
//sign user up
} else {
switch (e.getCode()) {
case ParseException.USERNAME_TAKEN:
Toast.makeText(context, "Sorry, this username has already been taken.", Toast.LENGTH_SHORT).show();
break;
case ParseException.USERNAME_MISSING:
Toast.makeText(context, "Sorry, a username is needed", Toast.LENGTH_SHORT).show();
break;
case ParseException.PASSWORD_MISSING:
Toast.makeText(context, "Sorry, a password is needed.", Toast.LENGTH_SHORT).show();
break;
case ParseException.OBJECT_NOT_FOUND:
Toast.makeText(context, "invalid credentials", Toast.LENGTH_SHORT).show();
break;
case ParseException.CONNECTION_FAILED:
Toast.makeText(context, "Sorry, internet is needed.", Toast.LENGTH_SHORT).show();
break;
default:
Log.d("Testing", e.getLocalizedMessage());
break;
}
}
}
});
}
So for this if you set the password on Parse as the clientID it'll be unique to that user and can be read by Parse and given by Google.
Note: I'm setting the username as the Google Identifier and then when they have successfully connected and signed up I display a username dialog box where they enter a username, so it can be displayed as something in plain text rather than numerics.