I am developing an app for android devices like WhatsApp. It is already in a very advanced state and I am correcting minor problems that I was encountering. But this one I am having difficulty solving in particular.
The goal would be to compress the profile and cover photo to take up less space on Firebase Storage. Compression would then have to work for both Profile and Cover Image.
private boolean checkStoragePermissions(){
//check if storage permission is enabled or not
//return true if enabled
//return false if not enabled
boolean result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
== (PackageManager.PERMISSION_GRANTED);
return result;
}
private void requestStoragePermission(){
//request runtime storage permission
requestPermissions(storagePermissions, STORAGE_REQUEST_CODE);
}
private boolean checkCameraPermissions(){
//check if storage permission is enabled or not
//return true if enabled
//return false if not enabled
boolean result = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.CAMERA)
== (PackageManager.PERMISSION_GRANTED);
boolean result1 = ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE)
== (PackageManager.PERMISSION_GRANTED);
return result && result1;
}
private void requestCameraPermission(){
//request runtime storage permission
requestPermissions(cameraPermissions, CAMERA_REQUEST_CODE);
}
private void showEditProfileDialog() {
/*Show dialog containing options
* 1) Edit Profile Picture
* 2) Edit Cover Photo
* 3) Edit Name
* 4) Edit Profile Status*/
//options to show in dialog
String options[] = {"Edit Profile Picture", "Edit Cover Photo", "Edit Name", "Edit Profile Status"};
//alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//set title
builder.setTitle("Profile Settings");
//set items to dialog
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//handle dialog items clicks
if(which == 0){
//edit profile clicked
pd.setMessage("Updating Profile Picture");
profileOrCoverPhoto = "image"; //i.e. changing profile picture, make sure to assign same value
showImagePicDialog();
}
else if (which == 1){
//edit cover clicked
pd.setMessage("Updating Cover Image");
profileOrCoverPhoto = "cover"; //i.e. changing cover photo+, make sure to assign same value
showImagePicDialog();
}
else if (which == 2){
//edit name clicked
pd.setMessage("Updating Name");
//calling method and pass key "name" as parameter to update its value in database
showNameProfileStatusUpdateDialog("name");
}
else if (which == 3){
//edit phone clicked
pd.setMessage("Updating Profile Status");
showNameProfileStatusUpdateDialog("profileStatus");
}
}
});
//create and show dialog
builder.create().show();
}
private void showNameProfileStatusUpdateDialog(final String key) {
/*parameter "key" will contain value name and phone*/
//custom dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme);
builder.setTitle("Update");
//set layout of dialog
LinearLayout linearLayout = new LinearLayout(getActivity());
linearLayout.setOrientation(LinearLayout.VERTICAL);
linearLayout.setPadding(10,10,10,10);
//add edit text
final EditText editText = new EditText(getActivity());
editText.setHint("Write here");
linearLayout.addView(editText);
builder.setView(linearLayout);
//add button to dialog to update
builder.setPositiveButton("Update", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//input text from edittext
final String value = editText.getText().toString().trim();
if (!TextUtils.isEmpty(value)){
pd.show();
HashMap<String, Object> result = new HashMap<>();
result.put(key, value);
databaseReference.child(user.getUid()).updateChildren(result)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//updated, dismiss progress
pd.dismiss();
Toast.makeText(getActivity(), "Updated", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//failed updating progress. dismiss progress and show error message
pd.dismiss();
Toast.makeText(getActivity(), ""+e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
//if user edit his name, also change it from hist posts
if (key.equals("name")){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Posts");
Query query = ref.orderByChild("uid").equalTo(uid);
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
dataSnapshot.getRef().child(child).child("uName").setValue(value);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
//update name in current users comments on posts
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
if (dataSnapshot.child(child).hasChild("Comments")){
String child1 = ""+dataSnapshot.child(child).getKey();
Query child2 = FirebaseDatabase.getInstance().getReference("Posts").child(child1).child("Comments").orderByChild(uid).equalTo(uid);
child2.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
dataSnapshot.getRef().child(child).child("uName").setValue(value);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
else{
Toast.makeText(getActivity(), "Please enter"+key, Toast.LENGTH_SHORT).show();
}
}
});
//add button to dialog to cancel the update
builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
//create and show dialog
builder.create().show();
}
private void showImagePicDialog() {
//show dialog containing options camera and gallery to pick the image
String options[] = {"Camera", "Gallery"};
//alert dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//set title
builder.setTitle("Pick Image From");
//set items to dialog
builder.setItems(options, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//handle dialog items clicks
if(which == 0){
//camera clicked
if (!checkCameraPermissions()){
requestCameraPermission();
}
else {
pickFromCamera();
}
}
else if (which == 1){
//gallery clicked
if (!checkStoragePermissions()){
requestStoragePermission();
}
else{
pickFromGallery();
}
}
}
});
//create and show dialog
builder.create().show();
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
/*This method called when user press Allow or Deny from permission request dialog
* here we will handle permissions cases (allowed & denied)*/
switch (requestCode){
case CAMERA_REQUEST_CODE: {
//picking from camera, first check if camera and storage permission allowed or not
if (grantResults.length > 0){
boolean cameraAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
boolean writeStorageAccepted = grantResults[1] == PackageManager.PERMISSION_GRANTED;
if (cameraAccepted && writeStorageAccepted){
//permissions enabled
pickFromCamera();
}
else{
//permission denied
Toast.makeText(getActivity(), "Please enable camera and storage permissions", Toast.LENGTH_SHORT).show();
}
}
}
break;
case STORAGE_REQUEST_CODE: {
//picking from gallery, first check if storage permission allowed or not
if (grantResults.length > 0){
boolean writeStorageAccepted = grantResults[0] == PackageManager.PERMISSION_GRANTED;
if (writeStorageAccepted){
//permissions enabled
pickFromGallery();
}
else{
//permission deniad
Toast.makeText(getActivity(), "Please enable storage permissions", Toast.LENGTH_SHORT).show();
}
}
}
break;
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
/*this method will be called after picking image from camera or gallery*/
if (resultCode == RESULT_OK){
if (requestCode == IMAGE_PICK_GALLERY_CODE){
//image is picked from gallery, get uri of image
image_uri = data.getData();
uploadProfileCoverPhoto(image_uri);
}
if (requestCode == IMAGE_PICK_CAMERA_CODE){
//image is picked from camera, get uri of image
uploadProfileCoverPhoto(image_uri);
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void uploadProfileCoverPhoto(final Uri uri) {
//show progress
pd.show();
/*Instead of creating separate function for profile picture and cover photo this will work in the same function*/
//path and name of image to be stored in firebase storage
String filePathAndName = storagePath+ ""+ profileOrCoverPhoto +"_"+ user.getUid();
StorageReference storageReference2nd = storageReference.child(filePathAndName);
storageReference2nd.putFile(uri)
.addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
@Override
public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
//image uploaded to storage, now get its url and store in users database
Task<Uri> uriTask = taskSnapshot.getStorage().getDownloadUrl();
while (!uriTask.isSuccessful());
final Uri downloadUri = uriTask.getResult();
//check if image is uploading or not and url received
if (uriTask.isSuccessful()){
//image uploaded
//add/update url in users database
HashMap<String, Object> results = new HashMap<>();
/*first parameter is profileorcover photo thas has value "image" or "cover" which are keys in users database where url of the image
* be saved in of them
* Second parameter contains the url of the image stored in firebase storage, this url will be saved as value against key "image" or "cover"*/
results.put(profileOrCoverPhoto, downloadUri.toString());
databaseReference.child(user.getUid()).updateChildren(results)
.addOnSuccessListener(new OnSuccessListener<Void>() {
@Override
public void onSuccess(Void aVoid) {
//URL IN DATA BASE of user is add succesfully
//dismiss progress bar
pd.dismiss();
Toast.makeText(getActivity(), "Image Updated.", Toast.LENGTH_SHORT).show();
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//error adding url in database of user
//dismiss progress bar
pd.dismiss();
Toast.makeText(getActivity(), "An error occurred updating the image.", Toast.LENGTH_SHORT).show();
}
});
//if user edit his name, also change it from hist posts
if (profileOrCoverPhoto.equals("image")){
DatabaseReference ref = FirebaseDatabase.getInstance().getReference("Posts");
Query query = ref.orderByChild("uid").equalTo(uid);
query.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
dataSnapshot.getRef().child(child).child("uDp").setValue(downloadUri.toString());
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
//update user image in current users comments on posts
ref.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
if (dataSnapshot.child(child).hasChild("Comments")){
String child1 = ""+dataSnapshot.child(child).getKey();
Query child2 = FirebaseDatabase.getInstance().getReference("Posts").child(child1).child("Comments").orderByChild(uid).equalTo(uid);
child2.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot ds: dataSnapshot.getChildren()){
String child = ds.getKey();
dataSnapshot.getRef().child(child).child("uDp").setValue(downloadUri.toString());
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
else{
//error
pd.dismiss();
Toast.makeText(getActivity(), "An error has occurred.", Toast.LENGTH_SHORT).show();
}
}
})
.addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull Exception e) {
//there were some error, get and show error message, dismiss progress dialog
pd.dismiss();
Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show();
}
});
}
private void pickFromCamera() {
//intent of picking image from device camera
ContentValues values = new ContentValues();
values.put(MediaStore.Images.Media.TITLE, "Temp Pic");
values.put(MediaStore.Images.Media.DESCRIPTION, "Temp Description");
//put image uri
image_uri = getActivity().getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
//intent to start camera
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, image_uri);
startActivityForResult(cameraIntent, IMAGE_PICK_CAMERA_CODE);
}
private void pickFromGallery() {
//pick from gallery
Intent galleryIntent = new Intent(Intent.ACTION_PICK);
galleryIntent.setType("image/*");
startActivityForResult(galleryIntent, IMAGE_PICK_GALLERY_CODE);
}