[英]How can I compress an image when sending to Firebase in this situation?
I am developing an app for android devices like WhatsApp.我正在为 WhatsApp 等 android 设备开发应用程序。 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.目标是压缩个人资料和封面照片,以减少 Firebase 存储上的空间。 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);
}
I'm using this object to compress an image to 1Mo max :我正在使用这个对象将图像压缩到 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
}
}
Ok.好的。 I was able to adapt my code to match what I wanted.我能够调整我的代码以匹配我想要的。 Here is the result.这是结果。
@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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.