Как я могу сжать изображение при отправке в Firebase в этой ситуации? - PullRequest
1 голос
/ 13 января 2020

Я разрабатываю приложение для android устройств, таких как WhatsApp. Он уже в очень продвинутом состоянии, и я исправляю мелкие проблемы, с которыми я столкнулся. Но эту проблему мне, в частности, трудно решить.

Цель - сжать профиль и фотографию обложки, чтобы занять меньше места в Firebase Storage. Тогда сжатие должно работать как для профиля, так и для обложки.

 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);
}

Ответы [ 2 ]

1 голос
/ 13 января 2020

Я использую этот объект для сжатия изображения до 1Mo max:

/**
 * Definition of the BitmapUtils object.
 */
object BitmapUtils {
    const val ONE_KO = 1024
    const val ONE_MO = ONE_KO * ONE_KO

    /**
     * Compress, if needed, an image file to be lower than or equal to 1 Mo
     *
     * @param filePath Image file path
     *
     * @return Stream containing data of the compressed image. Can be null
     */
    fun compressedImageFile(filePath: String): InputStream? {
        var quality = 100
        var inputStream: InputStream? = null
        if (filePath.isNotEmpty()) {
            var bufferSize = Integer.MAX_VALUE
            val byteArrayOutputStream = ByteArrayOutputStream()
            try {
                val bitmap = BitmapFactory.decodeFile(filePath)
                do {
                    if (bitmap != null) {
                        byteArrayOutputStream.reset()
                        bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream)
                        bufferSize = byteArrayOutputStream.size()
                        logD { "quality: $quality -> length: $bufferSize" }
                        quality -= 10
                    }
                } while (bufferSize > ONE_MO)
                inputStream = ByteArrayInputStream(byteArrayOutputStream.toByteArray())
                byteArrayOutputStream.close()
            } catch (e: Exception) {
                logE { "Exception when compressing file image: ${e.message}" }
            }
        }
        return inputStream
    }
}
0 голосов
/ 17 января 2020

Хорошо. Я смог адаптировать свой код, чтобы соответствовать тому, что я хотел. Вот результат.

@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    //this method will be called after picking image from camera or gallery

    if (requestCode == IMAGE_PICK_GALLERY_CODE && resultCode ==  RESULT_OK){
        Uri imagePath = data.getData();

        CropImage.activity(imagePath)
                .setGuidelines(CropImageView.Guidelines.ON)
                .start(ProfileSettingsActivity.this);
    }

    if (requestCode == IMAGE_PICK_CAMERA_CODE && resultCode ==  RESULT_OK){

        CropImage.activity(image_rui)
                .setGuidelines(CropImageView.Guidelines.ON)
                .start(ProfileSettingsActivity.this);
    }

    if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE){

        CropImage.ActivityResult result = CropImage.getActivityResult(data);


        if (resultCode == RESULT_OK){

            image_rui = result.getUri();
            //Log.d(TAG, "onActivityResult: Image Uri " + image_rui.toString());


            File actualImage = new File(image_rui.getPath());

            try {
                Bitmap compressedImage = new Compressor(this)
                        .setMaxWidth(250)
                        .setMaxHeight(250)
                        .setQuality(25)
                        .compressToBitmap(actualImage);

                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                compressedImage.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                byte[] final_image = baos.toByteArray();

                //show progress
                /*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);

                UploadTask uploadTask = storageReference2nd.putBytes(final_image);

                uploadTask
                        .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(ProfileSettingsActivity.this, "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(ProfileSettingsActivity.this, "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(ProfileSettingsActivity.this, "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(ProfileSettingsActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
                            }
                        });
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    super.onActivityResult(requestCode, resultCode, data);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...