There's a mistake in this code:
String download_url=task.getResult.getStorage.getDownloadUrl.toString);
When I run the program, I choose a picture from the gallery and I post it, and I get a message:
User is not authenticated, please authenticate using Firebase Authentication and try again
final StorageReference newPhoto=mPhotosStrorage.child(imageUri.getLastPathSegment());
newPhoto.putFile(imageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if (task.isSuccessful())
{
final String myKey=mPhotosDatabase.push().getKey();
//this error String download_url=task.getResult().getDownloadUrl().toString();
String datem=getDateTime();
DatabaseReference newDatabase=mPhotosDatabase.child(myKey);
newDatabase.child("postid").setValue(myKey);
newDatabase.child("postedby").setValue(userId);
newDatabase.child("postedon").setValue(datem);
newDatabase.child("postdetails").setValue(post);
newDatabase.child("postlikes");
newDatabase.child("postviews");
newDatabase.child("postcomments");
newDatabase.child("postimage").setValue(download_url).addOnCompleteListener(new OnCompleteListener<Void>() {
#RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful())
{
pb.setVisibility(View.GONE);
Pair[] pairs=new Pair[1];
pairs[0]=new Pair<View,String>(homeLayout,"etTransition");
ActivityOptions options=ActivityOptions.makeSceneTransitionAnimation(PostActivity.this,pairs);
startActivity(new Intent(PostActivity.this,HomeActivity.class),options.toBundle());
}
}
});
}else {
Toast.makeText(PostActivity.this, "Error:"+task.getException().getMessage(), Toast.LENGTH_SHORT).show();
}
}
});
Please help solve it and rewrite the code for me.
According to your last comment, the problem is at the following line of code:
String download_url=task.getResult().getDownloadUrl().toString();
Please note that this is not how you get the download URL nowadays. Converting that Task object to String isn't helpful at all. To solve this, please use the following lines of code:
storageRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
String url = uri.toString();
//Do what you need to do with the URL
}
});
Besides that, always make sure to have the user authenticated, as that error occurs only when the user is not authenticated and the rules are set to reject the operations.
Related
I am working on a simple app that should work like uber, I want each driver to upload the image of his/her car while setting up his/her profile. I have successfully picked the two images and was able to save them to the firebaseStorage, I want to retrieve the link to the downloaded car Image and save it to the driver database reference along with his profile picture and other information but I am unable to do that. I create a method that returns a String so that I can use the String returned by that method as the link to the car Image but it's showing null in my database.
The method that should return the link to the downloaded car image:
private Uri profileImageUri, carImageUri;
private StorageReference storageProfilePicsRef, storageCarImageRef;
private StorageTask uploadProfileTask, uploadCarImageTask;
private String myProfileImaeUri = "", myCarImageUri = "";
private String uploadCarImage() {
if (carImageUri != null) {
final StorageReference storageReference = storageCarImageRef.child(mAuth.getCurrentUser().getUid() + ".jpg");
uploadCarImageTask = storageReference.putFile(carImageUri);
uploadCarImageTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return storageReference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadCarUri = task.getResult();
myCarImageUri = downloadCarUri.toString();
}
}
});
} else {
Toast.makeText(SettingsActivity.this, "Car Image Not Selected", Toast.LENGTH_SHORT).show();
}
return myCarImageUri;
}
This is the method that upload both the profile image and other information of the driver:
private void uploadProfilePicture() {
String carImageUriFromTheMethod = uploadCarImage();//I was trying to assigned the method that returns the carImage link as a String to this String type variable so that I can use it
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setTitle("Updating Profile");
progressDialog.setMessage("Please wait while we are updating your account information");
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.show();
if (profileImageUri != null) {
final StorageReference fileRef = storageProfilePicsRef.child(mAuth.getCurrentUser().getUid() + ".jpg");
uploadProfileTask = fileRef.putFile(profileImageUri);
uploadProfileTask.continueWithTask(new Continuation() {
#Override
public Object then(#NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return fileRef.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
myProfileImaeUri = downloadUri.toString();
int selectedID = radioGroup.getCheckedRadioButtonId();
male = (RadioButton)findViewById(selectedID);
female = (RadioButton) findViewById(selectedID);
if (male.isChecked()){
selectedGender = male.getText().toString();
}else if (female.isChecked()){
selectedGender = female.getText().toString();
}else {
selectedGender = "Not specify";
}
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("ProfileImage", myProfileImaeUri);
hashMap.put("name", name.getText().toString());
hashMap.put("city", city.getText().toString());
hashMap.put("age", age.getText().toString());
hashMap.put("maritalStatus", maritalStatus.getText().toString());
hashMap.put("phoneNumber", phoneNumber.getText().toString());
hashMap.put("country", country.getText().toString());
hashMap.put("address", address.getText().toString());
hashMap.put("gender", selectedGender);
hashMap.put("carName",carName.getText().toString());
hashMap.put("carColour", carColor.getText().toString());
hashMap.put("carPlateNumber", carPlateNumber.getText().toString());
hashMap.put("carImage", carImageUriFromTheMethod);//I now call the string here
}
databaseReference.child(mAuth.getCurrentUser().getUid()).updateChildren(hashMap);
progressDialog.dismiss();
if (getType.equalsIgnoreCase("Driver")) {
startActivity(new Intent(SettingsActivity.this, DriversMapsActivity.class));
Toast.makeText(SettingsActivity.this, "Profile Information Updated Successfully", Toast.LENGTH_SHORT).show();
finish();
} else {
startActivity(new Intent(SettingsActivity.this, CustomerMapsActivity.class));
Toast.makeText(SettingsActivity.this, "Profile Information Updated Successfully", Toast.LENGTH_SHORT).show();
finish();
}
} else {
Toast.makeText(SettingsActivity.this, "Error Occured", Toast.LENGTH_SHORT).show();
progressDialog.dismiss();
}
}
});
} else {
Toast.makeText(SettingsActivity.this, "Profile Image Not Selected", Toast.LENGTH_SHORT).show();
}
}
Here is my database which shows that the carImage is null, but there is a car Image in the firebaseStorage:
"Driver": {
"2oKrtyUa3FX1wyHAhplsxbVaPZU2": {
"ProfileImage": "https://firebasestorage.googleapis.com/v0/b/ride-booking-app-e8a95.appspot.com/o/Profile%20Images%2F2oKrtyUa3FX1wyHAhplsxbVaPZU2.jpg?alt=media&token=442b14b3-ffb8-4356-b0c0-4c77021fe391",
"address": "Ikot Obong",
"age": "28",
"carColour": "black",
"carImage": "",//this is where the link supposed to appear as it's seen in the profile image
"carName": "Range Rover sport",
"carPlateNumber": "aa377-ktm",
"city": "Ikot Abasi",
"country": "Nigeria",
"gender": "Male",
"maritalStatus": "single",
"name": "Captain Elijah",
"phoneNumber": "08168989070"
}
}
Thanks for help
All the operations you are doing (uploading the image, getting its download URL, and writing to the database) are asynchronous, which your code ignores.
If you log the myCarImageUri in uploadCarImage right before you return it, you'll see it's null, which is the case because your onComplete for the upload hasn't run yet (another log would show that too).
The correct way to handle the uploads is as you already do for the myProfileImaeUri in your uploadProfilePicture method: nesting the callbacks, so that they execute in the correct order. You'll need to do the same for the car image.
To learn more about this problem, I recommend checking out some of the top answers on the asynchronous behavior of getDownloadUrl(), such as my answers to:
Can someone help me with logic of the firebase on success listener
How do I get files synchronized from Firebase in Android?
Why can't this retieve the download URL of an image on Firebase Storage?
I'd also recommend reading Doug's excellent series of blog posts on becoming a Firebase task master.
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 try to do a firebase connection with email and password, but i ah two symbol errors when i try to build.
the first one come from the AnotherActivity.class i don't know how to resolve it
public void updateUI(FirebaseUser account){
if(account != null){
Toast.makeText(this,"U Signed In successfully",Toast.LENGTH_LONG).show();
startActivity(new Intent(this,AnotherActivity.class));
}else {
Toast.makeText(this,"U Didnt signed in",Toast.LENGTH_LONG).show();
}
}
and the second come from EmailPasswordActivity.this
private void callsignin(String email, String password) {
mAuth.signInWithEmailAndPassword(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("success", "signInWithEmail:success");
FirebaseUser user = mAuth.getCurrentUser();
updateUI(user);
} else {
// If sign in fails, display a message to the user.
Log.w("failed", "signInWithEmail:failure", task.getException());
Toast.makeText(EmailPasswordActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
updateUI(null);
}
}
});
}
i think i need to write something in the manifest file but i don't what. Thank you for your attention and I hope you can help me
errors :
settings :
import :
It seems that the import statements are missing for AnotherActivity and EmailPasswordActivity.
At the top of your file, just below the package line, add these lines:
import <package_name>.AnotherActivity
import <package_name>.EmailPasswordActivity
For Android Studio shortcuts, Please refer to this post on how to use import in Android.
https://stackoverflow.com/a/30731266/9636037
I am trying to get a verification SMS from Firebase Authentication
When I click on (Verify my phone number) it crashes and returns null reference on the line of verifyPhoneNumber
please help me
I tried to change the phone number
and I searched very much and cannot solve it
private void sendVerificationCode(String phone) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
phone, // Phone number to verify
60, // Timeout duration
TimeUnit.SECONDS, // Unit of timeout
this, // Activity (for callback binding)
mCallbacks); // OnVerificationStateChangedCallbacks
}
Caused by: java.lang.NullPointerException: null reference
at com.google.android.gms.common.internal.Preconditions.checkNotNull(Unknown
Source:2)
at com.google.firebase.auth.PhoneAuthProvider.verifyPhoneNumber(com.google.firebase:firebase-auth##19.1.0:9)
at com.ullb.help.VerifyPhoneActivity.sendVerificationCode(VerifyPhoneActivity.java:67)
at com.ullb.help.VerifyPhoneActivity.onCreate(VerifyPhoneActivity.java:39)
at android.app.Activity.performCreate(Activity.java:7383)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3256)
If everything with firestore is okay and still not working than the problem may you put the callbacks in wrong position . You should implement callback in on create cycle after the send button is clicked. And this doesn't work if you are using emulator so use real android device one and it will work.
Callback
private PhoneAuthProvider.OnVerificationStateChangedCallbacks mCallbacks = new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onVerificationCompleted(#NonNull PhoneAuthCredential phoneAuthCredential) {
String code = phoneAuthCredential.getSmsCode();
if (code != null) {
verifyCode(code);
phoneOtpEdt.setText(code);
}
}
#Override
public void onVerificationFailed(#NonNull FirebaseException e) {
Toast.makeText(getApplicationContext(), e.getMessage() + "Verification Failed", Toast.LENGTH_SHORT).show();
}
#Override
public void onCodeSent(#NonNull String s, #NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationID = s; //Create your own instance variable
}
};
Sending OTP to the inputed number (Country code is a must)
private void sendOtpToUser(String number) {
PhoneAuthProvider.getInstance().verifyPhoneNumber(
"+91" + number,
60,
TimeUnit.SECONDS,
TaskExecutors.MAIN_THREAD,
mCallbacks);
}
Verifying the received OTP
private void verifyCode(String code) {
PhoneAuthCredential credential = PhoneAuthProvider.getCredential(verificationID, code);
FirebaseAuth auth = FirebaseAuth.getInstance();
auth.signInWithCredential(credential).addOnCompleteListener(LogInActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// do something
} else
// do something
}
});
Don't forget to enable the Phone Sign-in method in Firebase Auth.
I hope it help :)
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.