I am having a bit of trouble finding the solution to my problem. This is the third day working on it (not that I work on it all day) but still I am unable to fix it. I am adding a function to my app which is taking a photography, shorten it, compressing it and converting it to Base64 so I can send it as part of the information for a document. I have been able to do all of it but I am having two problems that I suppose are related to each other. The first one and the one I am having troubles with is that if after taking the photography successfully the user decides that he needs to change it by taking another photography a second time, the app crashes. Sometimes I have been able to take a second photography but a third time the app crashes. The user can decide how many pictures wants to take for finally deciding what to send, so I am not planing on limiting him to just take one. I am thinking that it has to do with memory leaks or something with the Activity lifecycle (which is also related to the memory as I understand) that gives me the problem. The second problem is that if the user decides to take a photography and is taken successfully, then decides to take another but later he decides to not take it giving a resultCode = 0 as expected, the Activity seems to be refreshed and all the EditText data stays intact but the previous photography is not shown. I could get it back in the onResume callback but I am not sure if there is something better to do.
Here are the snippets to my code:
public void tomarFotografia(View view) {
Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (cameraIntent.resolveActivity(getPackageManager()) != null) {
File photoFile = null;
try {
photoFile = createImageFile();
} catch (IOException e) {
e.printStackTrace();
}
if (photoFile != null) {
Uri photoURI = FileProvider.getUriForFile(this, "com.thesageelder.pmt.remisiones", photoFile);
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI);
// cameraIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
// cameraIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
List<ResolveInfo> resolvedIntentActivities = getPackageManager().queryIntentActivities(cameraIntent, PackageManager.MATCH_DEFAULT_ONLY);
for (ResolveInfo resolvedIntentInfo : resolvedIntentActivities) {
String packageName = resolvedIntentInfo.activityInfo.packageName;
grantUriPermission(packageName, photoURI, Intent.FLAG_GRANT_WRITE_URI_PERMISSION | Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
startActivityForResult(cameraIntent, CAMERA_REQUEST);
}
}
}
private File createImageFile() throws IOException {
File storageDir = getExternalFilesDir(Environment.DIRECTORY_PICTURES);
File image = File.createTempFile(
"RemisionPMT" + new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US).format(Calendar.getInstance().getTime()),
".jpg",
storageDir
);
currentPhotoFile = image.getAbsolutePath();
return image;
}
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == CAMERA_REQUEST && resultCode == Activity.RESULT_OK) {
File photoFile = new File(currentPhotoFile);
try {
Bitmap fullPhoto = MediaStore.Images.Media.getBitmap(getContentResolver(), Uri.fromFile(photoFile));
float aspectRatio = fullPhoto.getWidth() / (float) fullPhoto.getHeight();
int w = 1024;
int h = Math.round(w / aspectRatio);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
Bitmap.createScaledBitmap(fullPhoto, w, h, true).compress(Bitmap.CompressFormat.JPEG, 70, byteArrayOutputStream);
byte[] byteArray = byteArrayOutputStream.toByteArray();
EncodedPhoto = Base64.encodeToString(byteArray, Base64.DEFAULT);
try {
ExifInterface exif = new ExifInterface(currentPhotoFile);
int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 1);
int rotationDegrees = 0;
switch (orientation) {
case ExifInterface.ORIENTATION_ROTATE_90:
rotationDegrees = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
rotationDegrees = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
rotationDegrees = 270;
break;
}
Bitmap photoThumnail = ThumbnailUtils.extractThumbnail(BitmapFactory.decodeFile(currentPhotoFile), fullPhoto.getScaledWidth(getResources().getDisplayMetrics()) / 4, fullPhoto.getScaledHeight(getResources().getDisplayMetrics()) / 4);
if (rotationDegrees != 0) {
Matrix matrix = new Matrix();
matrix.postRotate(rotationDegrees);
photoThumnail = Bitmap.createBitmap(photoThumnail, 0, 0, photoThumnail.getWidth(), photoThumnail.getHeight(), matrix, true);
}
ivFotoPreview.setImageBitmap(photoThumnail);
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
And this is the logcat:
18819-18819 E/AndroidRuntime: FATAL EXCEPTION: main Process: com.thesageelder.pmt.remisiones, PID: 18819 java.lang.RuntimeException: Unable to resume activity {com.thesageelder.pmt.remisiones/com.thesageelder.pmt.remisiones.RemisionView}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2000, result=-1, data=null} to activity {com.thesageelder.pmt.remisiones/com.thesageelder.pmt.remisiones.RemisionView}: java.lang.NullPointerException at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2797) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2826) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.access$800(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1200) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606) at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=2000, result=-1, data=null} to activity {com.thesageelder.pmt.remisiones/com.thesageelder.pmt.remisiones.RemisionView}: java.lang.NullPointerException at android.app.ActivityThread.deliverResults(ActivityThread.java:3384) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2784) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2826) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.access$800(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1200) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606) at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.NullPointerException at java.io.File.fixSlashes(File.java:185) at java.io.File.(File.java:134) at com.thesageelder.pmt.remisiones.RemisionView.onActivityResult(RemisionView.java:749) at android.app.Activity.dispatchActivityResult(Activity.java:5467) at android.app.ActivityThread.deliverResults(ActivityThread.java:3380) at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2784) at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2826) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2257) at android.app.ActivityThread.access$800(ActivityThread.java:139) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1200) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:790) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:606) at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:132) at dalvik.system.NativeStart.main(Native Method)
I have placed a breakpoint in the very first line in the onActivityResult super.onActivityResult(requestCode, resultCode, data);
and the app crashes without even stopping there.
I have no idea what is the problem and being unable to debug it, I finally decide to ask here after some days searching for it. I think that all the other questions and answers I have read are related to not managing the result code or not reading correctly the data portion of the delivery result for the Activity. In my case I am expecting a resultCode different to -1 from the user and the data portion returns null since I want the full photography (since I found no way to having it from the data's extras).
Any help would be appreciated and sorry for the long question, I hope that writing this much detail would help understand my problem.
Not sure if it helps or not, but I am using an LG L70 with KitKat 4.4.2 to test it. Maybe with a more powerful device I would not have the problem, but the devices that the users are going to use wont be that more powerful.
Regards,
Elder
PD1: I do have the permission for <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
and <uses-permission android:name="android.permission.CAMERA"/>
PD2: I am leaving the entire camera function that I used here for some one that may need help with the camera and the FileProvider, additional to the previous code, it is needed that this is added to the Manifest:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="[package]"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"></meta-data>
</provider>
and a XML resource file file_paths.xml with this:
<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<external-path name="RemisionesPMT" path="Android/data/[package]/files/Pictures" />
</paths>
It took me six hours to figure it out.