在这种情况下,如何在发送到 Firebase 时压缩图像?



我正在为WhatsApp等Android设备开发一个应用程序。它已经处于非常先进的状态,我正在纠正我遇到的小问题。但是这个问题我特别难以解决。

目标是压缩个人资料和封面照片,以减少Firebase存储上的空间。 然后,压缩必须同时适用于配置文件和封面图像。

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

我正在使用此对象将图像压缩到最大 1Mo :

/**
* 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
}
}

好的。我能够调整我的代码以匹配我想要的。这是结果。

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

最新更新