app/src/main/java/com/sdp/movemeet/utility/ImageHandler.java
package com.sdp.movemeet.utility;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.android.gms.tasks.Task;
import com.google.firebase.storage.UploadTask;
import com.sdp.movemeet.backend.BackendManager;
import com.sdp.movemeet.backend.firebase.storage.StorageImageManager;
import com.sdp.movemeet.models.Image;
import com.sdp.movemeet.view.activity.ActivityDescriptionActivity;
import com.sdp.movemeet.view.activity.ActivityDescriptionActivityUnregister;
import com.sdp.movemeet.view.chat.ChatActivity;
import com.sdp.movemeet.view.profile.EditProfileActivity;
import com.sdp.movemeet.view.profile.ProfileActivity;
import static com.sdp.movemeet.utility.ActivityPictureCache.loadFromCache;
import static com.sdp.movemeet.utility.ActivityPictureCache.saveToCache;
import static com.sdp.movemeet.utility.PermissionChecker.isStorageReadPermissionGranted;
import static com.sdp.movemeet.utility.PermissionChecker.isStorageWritePermissionGranted;
/**
* This class allows to both load images from and upload images to the Firebase Storage service.
* In case the image is not present in the local cache, it is fetched from Firebase Storage.
* On the contrary, if the the image is already in the local cache, it is simply loaded from there.
*/
public abstract class ImageHandler {
private static final String TAG = "ImageHandler";
public static final String USER_IMAGE_NAME = "profile.jpg";
public static final String ACTIVITY_IMAGE_NAME = "activityImage.jpg";
public static final String CHAT_IMAGE_NAME = "chatImage.jpg";
public static final String PATH_SEPARATOR = "/";
private static BackendManager<Image> imageBackendManager;
/**
* Fetch an image (user profile picture, activity header picture or chat image) from Firebase Storage.
*
* @param image Image object to be loaded from Firebase Storage or from the local cache.
* @param activity Activity on which we want to fetch the image
*/
public static void loadImage(Image image, Activity activity) {
Log.d(TAG, "loading image");
ProgressBar progressBar = getProgressBar(activity);
if (progressBar != null) {
progressBar.setVisibility(View.VISIBLE);
}
Bitmap bitmap = null;
ImageView imageView = image.getImageView();
String imagePath = image.getDocumentPath();
//First, we load from cache (will return null if bitmap is not in cache)
if (isStorageReadPermissionGranted(activity)) bitmap = loadFromCache(imagePath);
if (bitmap != null) {
// bitmap was successfully loaded from cache
Log.d(TAG, "bitmap stored");
imageView.setImageBitmap(bitmap);
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
}
//Then load from database
imageBackendManager = new StorageImageManager();
Task<Uri> document = (Task<Uri>) imageBackendManager.get(image.getDocumentPath());
document.addOnSuccessListener(uri -> {
Log.d(TAG, "Image successfully fetched from Firebase Storage!");
image.setImageUri(uri);
setImageBitMapAndSaveToCache(image, activity);
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
}).addOnFailureListener(exception -> {
Log.d(TAG, "Image could not be fetched from Firebase Storage! Don't panic!" +
" It's probably because no images have been saved in Firebase Storage for" +
" this document yet!");
if (progressBar != null) {
progressBar.setVisibility(View.GONE);
}
});
}
/**
* For a given image, sets the corresponding bitmap and saves it to cache (if permission)
*
* @param image Image we want to store in the cache
* @param activity Activity from which we want to save the image
*/
private static void setImageBitMapAndSaveToCache(Image image, Activity activity) {
Glide.with(activity)
.asBitmap()
.load(image.getImageUri())
.into(new CustomTarget<Bitmap>() {
@Override
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
image.getImageView().setImageBitmap(resource);
Log.d(TAG, "storage write permissions " + isStorageWritePermissionGranted(activity));
if (isStorageWritePermissionGranted(activity))
saveToCache(resource, image.getDocumentPath());
}
@Override
public void onLoadCleared(@Nullable Drawable placeholder) {
}
});
}
/**
* Upload an image (user profile picture, activity header picture or chat image) to Firebase Storage.
*
* @param image Image object to be uploaded to Firebase Storage or saved to the local cache.
* @param activity Activity from which we want to upload the image
*/
public static void uploadImage(Image image, Activity activity) {
imageBackendManager = new StorageImageManager();
UploadTask uploadTask = (UploadTask) imageBackendManager.add(image, image.getDocumentPath());
uploadTask.addOnSuccessListener(taskSnapshot -> {
setImageBitMapAndSaveToCache(image, activity);
loadImage(image, activity);
}).addOnFailureListener(e -> {
Toast.makeText(activity.getApplication(), "you need an internet connection to change your profile picture !", Toast.LENGTH_LONG);
getProgressBar(activity).setVisibility(View.GONE);
});
}
/**
* Get the progress bar from an Activity
*
* @param activity Activity from which we get the progress bar
* @return the progress bar of the activity
*/
private static ProgressBar getProgressBar(Activity activity) {
ProgressBar progressBar = null;
if (activity instanceof ActivityDescriptionActivity)
progressBar = ((ActivityDescriptionActivity) activity).getProgressBar();
else if (activity instanceof ActivityDescriptionActivityUnregister)
progressBar = ((ActivityDescriptionActivityUnregister) activity).getProgressBar();
else if (activity instanceof EditProfileActivity)
progressBar = ((EditProfileActivity) activity).getProgressBar();
else if (activity instanceof ProfileActivity)
progressBar = ((ProfileActivity) activity).getProgressBar();
return progressBar;
}
/* Convert the Firebase Storage URL of the image into a path in Firebase Storage
*
* @param imageUrl URL of the image in Firebase Storage
* @return the converted image path
*/
public static String convertURLtoPath(String imageUrl) {
int startIdx = imageUrl.indexOf(ChatActivity.CHATS_CHILD);
int endIdx = imageUrl.indexOf(ImageHandler.CHAT_IMAGE_NAME) + ImageHandler.CHAT_IMAGE_NAME.length();
String imagePath = imageUrl.substring(startIdx, endIdx);
imagePath = imagePath.replace("%2F", ImageHandler.PATH_SEPARATOR);
return imagePath;
}
}