I have made image compress long ago it was working well until android 10 but above android its not working.
public class ImageCompress {
private static final int IMAGE_QUALITY = 99;
private static final int MAX_SIZE_PIXELS = 1200;
public static Bitmap decodeFile(File file, int width, int height) {
try {
// decode image size
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(new FileInputStream(file), null, options);
// the new size we want to scale to
final int REQUIRED_WIDTH = width;
final int REQUIRED_HIGHT = height;
// find the correct scale value. It should be the power of 2.
int scale = 1;
while (options.outWidth / scale / 2 >= REQUIRED_WIDTH
&& options.outHeight / scale / 2 >= REQUIRED_HIGHT)
scale *= 2;
// decode with inSampleSize
BitmapFactory.Options newOptions = new BitmapFactory.Options();
newOptions.inSampleSize = scale;
return BitmapFactory.decodeStream(new FileInputStream(file), null, newOptions);
} catch (FileNotFoundException e) {
return null;
}
}
public static File compressImage(final File file, String outputDirectory, Context context) {
String path = file.getPath();
String format = path.substring(path.lastIndexOf(".")).substring(1);
Bitmap source;
try {
source = decodeFile(file, MAX_SIZE_PIXELS, MAX_SIZE_PIXELS);
} catch (Exception e) {
Log.d(ImageCompress.class.toString(), e.toString() + " Something happened wrong");
return null;
}
Bitmap.CompressFormat compressFormat;
// if png pr webp have allowed resolution then not compress it
if ("png".equals(format) || "webp".equals(format)) return file;
// select format
switch (format) {
case "png":
compressFormat = Bitmap.CompressFormat.PNG;
break;
case "webp":
compressFormat = Bitmap.CompressFormat.WEBP;
break;
case "gif":
return file;
default:
compressFormat = Bitmap.CompressFormat.JPEG;
}
// resize image
Bitmap resizedBmp;
//getting error on source.getHeight() line
if (source.getHeight() > MAX_SIZE_PIXELS || source.getWidth() > MAX_SIZE_PIXELS) {
resizedBmp = resizeBitmap(source, MAX_SIZE_PIXELS);
} else {
resizedBmp = source;
}
File result = null;
OutputStream fOut = null;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
ContentResolver resolver = BaseApplication.getInstance().getContentResolver();
ContentValues contentValues = new ContentValues();
contentValues.put(MediaStore.MediaColumns.DISPLAY_NAME, file.getName());
contentValues.put(MediaStore.MediaColumns.MIME_TYPE, "image/" + format);
contentValues.put(MediaStore.MediaColumns.RELATIVE_PATH, Constants.MULTIMEDIA_CHATROOM_11);
Uri imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues);
try {
fOut = resolver.openOutputStream(imageUri);
result = new File(Utils.getPath(BaseApplication.getInstance(), imageUri));
} catch (FileNotFoundException e) {
e.printStackTrace();
}
} else {
// create directory if not exist
File directory = new File(outputDirectory);
int code = context.getPackageManager().checkPermission(
android.Manifest.permission.WRITE_EXTERNAL_STORAGE,
context.getPackageName());
if (code == PackageManager.PERMISSION_GRANTED) {
Log.i(ImageCompress.class.getSimpleName(), "creating directory");
if (!directory.isDirectory() || !directory.exists()) {
directory.mkdirs();
}
} else {
Log.i(ImageCompress.class.getSimpleName(), "failed access");
}
// compress image
result = new File(outputDirectory, file.getName());
try {
if (!result.exists()) {
result.createNewFile();
fOut = new FileOutputStream(result);
} else {
fOut = new FileOutputStream(result);
}
} catch (IOException e) {
e.printStackTrace();
}
}
try {
resizedBmp.compress(compressFormat, IMAGE_QUALITY, fOut);
fOut.flush();
fOut.close();
source.recycle();
resizedBmp.recycle();
} catch (Exception e) {
e.printStackTrace();
return null;
}
// copy EXIF orientation from original image
try {
ExifInterface oldExif = new ExifInterface(file.getPath());
String exifOrientation = oldExif.getAttribute(ExifInterface.TAG_ORIENTATION);
if (exifOrientation != null) {
ExifInterface newExif = new ExifInterface(result.getPath());
newExif.setAttribute(ExifInterface.TAG_ORIENTATION, exifOrientation);
newExif.saveAttributes();
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
private static Bitmap resizeBitmap(Bitmap source, int maxSizePixels) {
int targetWidth, targetHeight;
double aspectRatio;
if (source.getWidth() > source.getHeight()) {
targetWidth = maxSizePixels;
aspectRatio = (double) source.getHeight() / (double) source.getWidth();
targetHeight = (int) (targetWidth * aspectRatio);
} else {
targetHeight = maxSizePixels;
aspectRatio = (double) source.getWidth() / (double) source.getHeight();
targetWidth = (int) (targetHeight * aspectRatio);
}
return Bitmap.createScaledBitmap(source, targetWidth, targetHeight, false);
}
}
My app is made for social entertainment purpose so I don’t have storage access like before due to policies. so we can use only session scope way to access files. am getting error at line source.getHeight() and source.getWidth() as both are zero. Help me to fix this for all android versions this issue.
Please note: I noticed this error comes in few pictures from gallery.
2
Answers
If you get a
NullPointerException
onsource.getHeight()
then this meanssource
has been set tonull
.The only point where
source
is set is on the lineThis means the method
decodeFile
has to return a null value.Looking at the method
decodeFile
you can see tha there are only two different code paths that return a value. The first code path returns the value ofBitmapFactory.decodeStream(..)
which AFAIK should never returnnull
.The it is most likely the other code path in the
FileNotFoundException
catch clause.This leads to the conclusion that at some point you are trying to read a File that does not exist or on that you don’t have read permissions.
As your app is older the chance is high that if it is a permission problem and the file is on the shared storage (
/sdcard
or subfolder) this is because the app does not make use of scoped storage system introduced with Android 10/11.