Wait for a method completed first, before continue running - java

I'm trying to run a method called uploadProfilePhoto() but the code after this method invocation runs first even though uploadProfilePhoto() has not finish running. Is there anyway i can let uploadProfilePhoto() finish it's process first before continuing?
I tried using AsynTask but it still doesn't work. Seems like it is because doInBackground() is for a series of code, not method.
AsyncTask
protected class MyAsyncTask extends AsyncTask<Void, Void, Void>
{
#Override
protected Void doInBackground(Void... params) {
uploadProfilePhoto();
return null;
}
#Override
protected void onPostExecute(Void result) {
Toast.makeText(ProfileSetup.this, "Account created successfully.", Toast.LENGTH_SHORT).show();
mAuth.signInWithEmailAndPassword(email, password);
startActivity(new Intent(ProfileSetup.this, MainActivity.class));
}
}
uploadProfilePhoto()
private void uploadProfilePhoto() {
if (mImageUri != null) {
final StorageReference imageReference = storageReference.child(System.currentTimeMillis() + "." + getFileExtension(mImageUri));
storageTask = imageReference.putFile(mImageUri);
storageTask.continueWithTask(new Continuation() {
#Override
public Task<Uri> then(#NonNull Task task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
return imageReference.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
myUrl = downloadUri.toString();
String myid = getIntent().getStringExtra("uid");
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users").child(myid);
reference.child("profilePicUrl").setValue(myUrl);
finish();
} else {
Toast.makeText(ProfileSetup.this, "Failed", Toast.LENGTH_SHORT).show();
}
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(ProfileSetup.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
} else {
Toast.makeText(this, "No image selected", Toast.LENGTH_SHORT).show();
}
}

I can think of two ways
storageTask = imageReference.putFile(mImageUri);
storageTask.addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
myUrl = task.getResult().toString();
String myid = getIntent().getStringExtra("uid");
DatabaseReference reference =
FirebaseDatabase.getInstance().getReference("Users").child(myid);
reference.child("profilePicUrl").setValue(myUrl);
startActivity(new Intent(ProfileSetup.this, MainActivity.class));
finish();
} else {
Toast.makeText(ProfileSetup.this, "Failed",
Toast.LENGTH_SHORT).show();
}
}
2nd way which is not very clean and nice actually should be considered as a bad practice , but knowing alternative way is no harm so
you can start MainActivity Imidiately after saying imageReference.putFlie(mImageUri);
imgeReference.putFile(mImageUri);
startActivity(new Intent(ProfileSetup.this, MainActivity.class));
Now in the MainActivity
while(ProfileSetup.getImageUrl() == null){ // define a method to return the url
Systemclock.sleep(500); // if it is small image you can hote it will be uplaoded in seconds
}
Picasso.with(this).load(ProfileSetup.getImageUrl()).fit().into(imageView); // the while loop terminates when your image gets uploaded because getImageUrl() did not return null , now you know image is there you can download and set it to imageView by using Piccaso
With this approach you don't need a completeListener but i don't recommend doing it because it is more complex and doesn't deal with any failure of imageUploading

Related

android java to upload and retrieve picture from the firestore

I'm trying to get pictures from firebase storage and save it into the firestore.
I upload the picture once, and then I tried to open this app but it keeps stop.
java.lang.IllegalArgumentException: uri cannot be null
It shows this error.
Here is my code, and this is the part occurring error.
private void postButtonClicked(){
//immutable read-only variable
final String title = ((EditText)findViewById(R.id.titleEditText)).getText().toString();
final String contents = ((EditText)findViewById(R.id.contentsEditText)).getText().toString();
if(!title.trim().isEmpty() || !contents.trim().isEmpty()){
final StorageReference postRef = storageReference.child("post_images").child(FieldValue.serverTimestamp().toString()+".jpg");
postRef.putFile(postImageUri).addOnCompleteListener(new OnCompleteListener<UploadTask.TaskSnapshot>() {
#Override
public void onComplete(#NonNull Task<UploadTask.TaskSnapshot> task) {
if(task.isSuccessful()){
postRef.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
HashMap<String, Object> writeinfoMap = new HashMap<>();
writeinfoMap.put("image", uri.toString());
writeinfoMap.put("title", title);
writeinfoMap.put("contents", contents);
writeinfoMap.put("time", FieldValue.serverTimestamp());
// postMap.put("user", user);
firestore.collection("post").add(writeinfoMap).addOnCompleteListener(new OnCompleteListener<DocumentReference>() {
#Override
public void onComplete(#NonNull Task<DocumentReference> task) {
if(task.isSuccessful()){
startActivity(new Intent(WritePostActivity.this, MainActivity.class));
Toast.makeText(WritePostActivity.this, "posted!", Toast.LENGTH_SHORT).show();
finish();
}else{
String error = task.getException().getMessage();
Toast.makeText(WritePostActivity.this,"Error: "+error,Toast.LENGTH_SHORT).show();
}
}
});
}
});
}else{
String error = task.getException().getMessage();
Toast.makeText(WritePostActivity.this,"Error: "+error,Toast.LENGTH_SHORT).show();
}
}
});
}else{
Toast.makeText(this,"please enter the title.", Toast.LENGTH_SHORT).show();
}
}
please help me to find out the error and fix it. Thanks

Why does a method in another activity gets called before succesful Firebase signIn?

My app uses FirebaseAuth. In my SignInActivity, on clicking the sign in button, the signInWithEmailAndPassword onCompleteListener starts my DashboardActivity with an Intent. In the DashboardActivity, there is a method which calls FirebaseAuth.getInstance().getCurrentUser().getUid() which crashes my app if the user trying to signIn does not exist.
The question here is: why does the method get called at all if the Intent was not sent? or was the intent sent?
here is my SignInActivity signIn Button code:
signIn.setOnClickListener((new View.OnClickListener() {
#Override
public void onClick(View view) {
if (!email.getText().toString().equals("") && !password.getText().toString().equals("")) {
showProgressBar();
FirebaseAuth.getInstance().signInWithEmailAndPassword(email.getText().toString(), password.getText().toString()).addOnCompleteListener((new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
hideProgressBar();
Toast.makeText(SignInActivity.this, "Signed In", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(SignInActivity.this, DashboardActivity.class);
startActivity(intent);
finish();
}
})).addOnFailureListener((new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
hideProgressBar();
Toast.makeText(SignInActivity.this, "Failed to Sign In", Toast.LENGTH_SHORT).show();
}
}));
} else {
Toast.makeText(SignInActivity.this, "please fill all fields", Toast.LENGTH_SHORT).show();
}
}
}));
DashboardActivity code (that crashes the app):
private void queryDB() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference();
Query query = reference.child(getString(R.string.users))
.child(FirebaseAuth.getInstance().getCurrentUser().getUid())
.child("securityLevel");
query.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
String secLevel = dataSnapshot.getValue(String.class);
if (secLevel.equals("1")) {
fab.hide();
} else {
fab.show();
}
Log.d(TAG, "onDataChange: +-+ " + secLevel);
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
The Logcat:
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String com.google.firebase.auth.FirebaseUser.getUid()' on a null object reference
at com.quwaysim.regapp.DashboardActivity.queryDB(DashboardActivity.java:191)
at com.quwaysim.regapp.DashboardActivity.onCreate(DashboardActivity.java:60)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127).......
OnComplete will execute even if the authorization passed or not. You need to add OnSuccessListener and handle the intent there.
You are not checking if task is successful or not. You have to do it like:
#Override
public void onClick(View view) {
if (!email.getText().toString().equals("") && !password.getText().toString().equals("")) {
showProgressBar();
FirebaseAuth.getInstance().signInWithEmailAndPassword(email.getText().toString(), password.getText().toString()).addOnCompleteListener((new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if(task.isSuccessful() && task.getResult() != null){
hideProgressBar();
Toast.makeText(SignInActivity.this, "Signed In", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(SignInActivity.this, DashboardActivity.class);
startActivity(intent);
finish();
}
}
})).addOnFailureListener((new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
hideProgressBar();
Toast.makeText(SignInActivity.this, "Failed to Sign In", Toast.LENGTH_SHORT).show();
}
}));
} else {
Toast.makeText(SignInActivity.this, "please fill all fields", Toast.LENGTH_SHORT).show();
}
}
}));

Unable to put image url to Firestore database after uploading the image to firebase storage

I'm trying to upload some images to firestore storage and put the image URL to firebase database. The images are uploading successfully but the image URLs aren't being added to the database. The problem that I think might be causing this is that the image URL is being added to the Hashmap after uploading the image but the database upload process isn't waiting for the URL instead, adding all other HashMap keys to the database before the Upload task returns the URL. This way all other keys get added to the database but not the Image URLs. In the below code product id is being added successfully to the database, also if I leave any image unselected its url alse gets added as empty to the database which is working fine but if I select an image to upload, The hashmap to database upload finishes even before getting the uploaded image URL.
public class AddProductDataActivity extends AppCompatActivity {
String productId;
EditText productIdEditText;
ImageView addProductImage3;
Button addProductSubmit;
final int IMAGE3_REQUEST = 30;
Uri image3LocationPath;
StorageReference objectStorageReference;
FirebaseFirestore objectFireBaseFireStore;
Map<String, String> objectMap = new HashMap<>();
StorageReference img3Store;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_product_data);
brandNameEditText =(EditText)
addProductImage3 = (ImageView) findViewById(R.id.add_product_image3);
objectStorageReference =
FirebaseStorage.getInstance().getReference("images");
objectFireBaseFireStore = FirebaseFirestore.getInstance();
addProductImage3.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent objectIntent = new Intent();
objectIntent.setType("image/*");
objectIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(objectIntent, IMAGE3_REQUEST);
}
});
addProductSubmit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
productId = productIdEditText.getText().toString();
if(image3LocationPath != null)
{
final String image3Name = productId + "_image3." + getExtension(image3LocationPath);
img3Store = objectStorageReference.child(image3Name);
UploadTask imageUploadTask = img3Store.putFile(image3LocationPath);
imageUploadTask.continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
#Override
public Task<Uri> then(#NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if(!task.isSuccessful())
{
Toast.makeText(AddProductDataActivity.this, "Task Unsuccessful", Toast.LENGTH_SHORT).show();
}
return img3Store.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if(task.isSuccessful())
{
String image_3_url = task.getResult().toString();
objectMap.put("image3_url",image_3_url);
}
else
{
Toast.makeText(AddProductDataActivity.this, task.getException().toString(), Toast.LENGTH_SHORT).show();
}
}
});
}
else
{
objectMap.put("image3_url","");
}
objectFireBaseFireStore.collection("images").document(productId).set(objectMap).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Toast.makeText(AddProductDataActivity.this, "Product Added Successfully.", Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(AddProductDataActivity.this, "Error in Adding Product. Please Try Again.\n"+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
switch (requestCode){
case 30:
try
{
if(resultCode == RESULT_OK && data != null && data.getData() != null)
{
image3LocationPath = data.getData();
Bitmap objectBitmap = MediaStore.Images.Media.getBitmap(getContentResolver(), image3LocationPath);
addProductImage3.setImageBitmap(objectBitmap);
}
}
catch (Exception e)
{
Toast.makeText(this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
break;
default:
break;
}
private String getExtension(Uri uri){
try
{
ContentResolver objectContentResolver = getContentResolver();
MimeTypeMap objectMimeTypeMap = MimeTypeMap.getSingleton();
return objectMimeTypeMap.getExtensionFromMimeType(objectContentResolver.getType(uri));
}
catch (Exception e)
{
Toast.makeText(AddProductDataActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
}
return null;
}
}
}
Your code
objectFireBaseFireStore.collection("images").document(productId).set(objectMap)
executes before
objectMap.put("image3_url",image_3_url)
Which means when you are setting your url, your objectMap does not have the key image3_url
Try to set values to database inside onComplete() or use different workaround to set only the url.
You forgot to add your HashMap to Database Reference of Firebase.
This is reference from my current project code.
private void uploadVideo() {
StorageReference mStorageRef = FirebaseStorage.getInstance().getReference();
final StorageReference riversRef = mStorageRef.child(Constants.STORAGE_PATH + "/" + mFinalUploadUri.getLastPathSegment());
riversRef.putFile(mFinalUploadUri).continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
#Override
public Task<Uri> then(#NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw Objects.requireNonNull(task.getException());
}
// Continue with the task to get the download URL
return riversRef.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
FirebaseFirestore database = FirebaseFirestore.getInstance();
String mSelectedCategory = binding.categorySpinner.getSelectedItem().toString();
DocumentReference newDocumentReference = database.collection(PENDING_PATH).document();
VideoModel videoModel = new VideoModel();
videoModel.setDocumentId(newDocumentReference.getId());
videoModel.setTitle(mTitle);
videoModel.setCategory(mSelectedCategory);
//videoModel.setTime(FieldValue.serverTimestamp());
videoModel.setUrl(downloadUri != null ? downloadUri.toString() : null);
newDocumentReference.set(videoModel).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
binding.progressBar.setVisibility(View.GONE);
binding.button.setVisibility(View.VISIBLE);
binding.videoView.setVisibility(View.GONE);
selectedUri = null;
Toast.makeText(AdminVideoUploadActivity.this, R.string.uploaded_successfully, Toast.LENGTH_SHORT).show();
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
Toast.makeText(AdminVideoUploadActivity.this, R.string.failed_to_upload, Toast.LENGTH_SHORT).show();
}
});
}
}
});
}
Now you can check code and find where you have done mistake. Just add lines of code of inserting in database.
Thank you.

How to write an Upload firebase method with ProgressBar out of the Activity?

I am using Firebase upload and I want to write the uploaded method in a class out of the activity as I want to use it several times and at the same time I want to use ProgressBar that shows the progress and as it is known we can't use findViewById out of activity or Fragment.
uploadTask.addOnProgressListener(new OnProgressListener<UploadTask.TaskSnapshot>() {
#Override
public void onProgress(UploadTask.TaskSnapshot taskSnapshot) {
taskSnapshot.getError();
float progress = (float) ((100.0 * taskSnapshot.getBytesTransferred()) / taskSnapshot.getTotalByteCount());
System.out.println("Upload is " + progress + "% done");
**Here I wanna use a progressBar**
}
}).addOnPausedListener(new OnPausedListener<UploadTask.TaskSnapshot>() {
#Override
public void onPaused(UploadTask.TaskSnapshot taskSnapshot) {
System.out.println("Upload is paused");
}
}).addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception exception) {
// Handle unsuccessful uploads
int errorCode = ((StorageException) exception).getErrorCode();
String errorMessage = exception.getMessage();
// test the errorCode and errorMessage, and handle accordingly
Log.d(TAG, "onSuccess: The photo has NOT been uploaded" + errorCode + errorMessage);
Toast.makeText(mContext, "Sorry the photo has not been uploaded .. Please Try again", Toast.LENGTH_SHORT);
}
}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
circleProgressBar.setVisibility(View.GONE);
Log.d(TAG, "onSuccess: The photo is being uploaded");
Toast.makeText(mContext, "The photo has been uploaded successfully", Toast.LENGTH_SHORT).show();
//
}
}).continueWithTask(new Continuation<UploadTask.TaskSnapshot, Task<Uri>>() {
#Override
public Task<Uri> then(#NonNull Task<UploadTask.TaskSnapshot> task) throws Exception {
if (!task.isSuccessful()) {
throw task.getException();
}
// Continue with the task to get the download URL
return ref.getDownloadUrl();
}
}).addOnCompleteListener(new OnCompleteListener<Uri>() {
#Override
public void onComplete(#NonNull Task<Uri> task) {
if (task.isSuccessful()) {
Uri downloadUri = task.getResult();
if (downloadUri != null){
String photoStringUrl = downloadUri.toString();
Log.d(TAG, "onComplete: Upload " + photoStringUrl);
//Inserting the profile photo into database {user_profile_account}
firebaseUtilities.saveProfilePhotoToDatabase(photoStringUrl);
}
}
You can pass Activity as a parameter instead of Context.

Firebase Storage "retrieves a long lived download URL" using getDownloadUrl() now deprecated

This getDownloadUrl() method showed deprecated after updating to
'com.google.firebase:firebase-storage:15.0.2'
Nothing on the official site to another way to achieve the url, So there's any way to achieve the Url in non deprecated way?
/** #deprecated */
#Deprecated
#Nullable
public Uri getDownloadUrl() {
StorageMetadata var1;
return (var1 = this.getMetadata()) != null ? var1.getDownloadUrl() : null;
}
}
In the docs it says this:
The getDownloadUrl() and getDownloadUrls() methods of the StorageMetadata class are now deprecated. Use getDownloadUrl() from StorageReference instead.
So you need to use getDownloadUrl() that is inside the StorageReference
public Task<Uri> getDownloadUrl ()
Asynchronously retrieves a long lived download URL with a revokable token. This can be used to share the file with others, but can be revoked by a developer in the Firebase Console if desired.
more information here:
https://firebase.google.com/docs/reference/android/com/google/firebase/storage/StorageReference#getDownloadUrl()
final StorageReference filePath = mImageStore.child("profile_images").child("full_image").child(userId + ".jpg");
filePath.getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
//Bitmap hochladen
uploadBitMap(uri.toString());
}
});strong text
Or
final UploadTask uploadTask = thumb_file.putBytes(thumb_bite);
uploadTask.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//Url laden
taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map imageUrls = new HashMap();
imageUrls.put("image", fullImageUrl);
imageUrls.put("thumb_image", uri.toString());
//In database
mAlarmsDatabaseReference.updateChildren(imageUrls).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
//Progressbar beende + Bild wieder anzeigen
progressBar.setVisibility(View.GONE);
circleProfilePicture.setVisibility(View.VISIBLE);
if(task.isSuccessful()){
Toast.makeText(SettingsActivity.this, getResources().getString(R.string.ProfilbildUpdate), Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(SettingsActivity.this, "FAILED", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
});
final UploadTask uploadTask = thumb_file.putBytes(thumb_bite);
uploadTask.addOnSuccessListener(new OnSuccessListener() {
#Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//Url laden
taskSnapshot.getStorage().getDownloadUrl().addOnSuccessListener(new OnSuccessListener<Uri>() {
#Override
public void onSuccess(Uri uri) {
Map imageUrls = new HashMap();
imageUrls.put("image", fullImageUrl);
imageUrls.put("thumb_image", uri.toString());
//In database
mAlarmsDatabaseReference.updateChildren(imageUrls).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
//Progressbar beende + Bild wieder anzeigen
progressBar.setVisibility(View.GONE);
circleProfilePicture.setVisibility(View.VISIBLE);
if(task.isSuccessful()){
Toast.makeText(SettingsActivity.this, getResources().getString(R.string.ProfilbildUpdate), Toast.LENGTH_SHORT).show();
}else{
Toast.makeText(SettingsActivity.this, "FAILED", Toast.LENGTH_SHORT).show();
}
}
});
}
});
}
});

Categories

Resources