My objective: The user will click a floating action button which will open a camera. User will then take a picture with it. If the image is okay then the captured image will be loaded to another activity.
Problem: After the user captures image and proceeds to the next step, the activity/process responsible for this crashes.
Log:
com.roots.edulive E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.roots.edulive, PID: 12232
java.lang.RuntimeException: Unable to resume activity {com.roots.edulive/com.roots.edulive.ViewActivity.DoubtHistoryActivity}: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=276995085, result=-1, data=null} to activity {com.roots.edulive/com.roots.edulive.ViewActivity.DoubtHistoryActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getPath()' on a null object reference
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4279)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4311)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=276995085, result=-1, data=null} to activity {com.roots.edulive/com.roots.edulive.ViewActivity.DoubtHistoryActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getPath()' on a null object reference
at android.app.ActivityThread.deliverResults(ActivityThread.java:4960)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4266)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4311)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.getPath()' on a null object reference
------------------------------------------------------------------------------------------------------------------------------------
at com.roots.edulive.ViewActivity.DoubtHistoryActivity$4.onActivityResult(DoubtHistoryActivity.java:178)
at com.roots.edulive.ViewActivity.DoubtHistoryActivity$4.onActivityResult(DoubtHistoryActivity.java:173)
------------------------------------------------------------------------------------------------------------------------------------
at androidx.activity.result.ActivityResultRegistry.doDispatch(ActivityResultRegistry.java:377)
at androidx.activity.result.ActivityResultRegistry.dispatchResult(ActivityResultRegistry.java:336)
at androidx.activity.ComponentActivity.onActivityResult(ComponentActivity.java:624)
at androidx.fragment.app.FragmentActivity.onActivityResult(FragmentActivity.java:164)
at android.app.Activity.dispatchActivityResult(Activity.java:8249)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4953)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4266)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4311)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2047)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:224)
at android.app.ActivityThread.main(ActivityThread.java:7590)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
Here's how I tried to implement this feature:
I used an ActivityResultLauncher<Uri>
that will get the image from the camera and initialized it in the following way -
cameraActivityResultLauncher = registerForActivityResult(new ActivityResultContracts.TakePicture(), new ActivityResultCallback<Boolean>() {
@Override
public void onActivityResult(Boolean result) {
if (result) {
// Toast.makeText(getContext(), "Image saved in: " + photoURI.getPath(), Toast.LENGTH_SHORT).show();
Log.d(TAG, "onActivityResult: " + "Image saved in: " + cameraPhotoUri.getPath());
Intent editImageIntent = new Intent(DoubtHistoryActivity.this, EditImageActivity.class);
editImageIntent.putExtra("FILE_PATH", cameraPhotoUri.toString())
.putExtra(EditImageActivity.FROM_CAMERA, true)
.putExtra("CourseTitle", courseName)
.putExtra("CourseId", courseId)
.putExtra("SubscriptionId", subscriptionId);
Log.d(TAG, "onActivityResult: DoubtSolve courseID: " + courseId);
startActivity(editImageIntent);
// finish();
}
}
});
Note: the Exceptions are occurring at line Log.d(TAG, "onActivityResult: " + "Image saved in: " + cameraPhotoUri.getPath());
which is line 178 mentioned in the log (I've used ------- in log to highlight this part)
The value of cameraPhotoUri
might get lost when the activity is paused. So I saved its value in the following way:
@Override
public void onSaveInstanceState(@NonNull Bundle outState, @NonNull PersistableBundle outPersistentState) {
String photoPath = "";
if (cameraPhotoUri != null) {
photoPath = cameraPhotoUri.toString();
}
Log.d(TAG, "onSaveInstanceState: photoPath: " + photoPath);
outState.putString("photoPath", photoPath);
super.onSaveInstanceState(outState, outPersistentState);
}
@Override
public void onRestoreInstanceState(@Nullable Bundle savedInstanceState, @Nullable PersistableBundle persistentState) {
Log.d(TAG, "onRestoreInstanceState: the code came here");
if (savedInstanceState != null) {
if (savedInstanceState.containsKey("photoPath")) {
cameraPhotoUri = Uri.parse(savedInstanceState.getString("photoPath"));
}
}
super.onRestoreInstanceState(savedInstanceState, persistentState);
}
Note: I tried calling super
at the beginning of the function too. It still had the same issue.
Finally in the onClick() of the button responsible for launching the camera, I called the following method:
private void dispatchTakePictureIntent() {
Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
Log.d(TAG, "dispatchTakePictureIntent: inside dispatchTakePictureIntent");
// Ensure that there's a camera activity to handle the intent
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
// Create the File where the photo should go
File photoFile = null;
try {
photoFile = MyFileUtils.createImageFile(this);
currentPhotoPath = photoFile.getAbsolutePath();
Log.d(TAG, "dispatchTakePictureIntent: currentPhotoPath: " + currentPhotoPath);
} catch (IOException ex) {
// Error occurred while creating the File
Log.d(TAG, "dispatchTakePictureIntent: the following error occurred");
ex.printStackTrace();
}
// Continue only if the File was successfully created
if (photoFile != null) {
cameraPhotoUri = FileProvider.getUriForFile(
getBaseContext(),
"com.roots.edulive.fileprovider",
photoFile
);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, cameraPhotoUri);
Log.d(TAG, "dispatchTakePictureIntent: photo URI = " + cameraPhotoUri);
cameraActivityResultLauncher.launch(cameraPhotoUri);
} else {
Log.e(TAG, "dispatchTakePictureIntent: Photo FILE is NULL!!!!");
}
}
}
What baffles me the most is the fact that this very same code worked perfectly yesterday!
NOTE 1: This code worked after I've cleared app data. I'm confused how is app data related to this issue!? And what should be done to handle it?
NOTE 2: It's not working after I've cleared app data again. Sometimes it works, sometimes it don't. I am confused what's causing this problem