0

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

ganjaam
  • 1,030
  • 3
  • 17
  • 29
  • Have you set the required permissions? – Thomas Meinhart Jan 24 '22 at 10:43
  • @ThomasMeinhart yes. I haven't included the code here, but I did it properly. – ganjaam Jan 24 '22 at 11:40
  • And you also check and request them before trying to take the picture? – Thomas Meinhart Jan 24 '22 at 11:46
  • @ThomasMeinhart yes. The activity does not even open if required permissions are not given. – ganjaam Jan 24 '22 at 12:30
  • Do you have a physical device for testing or is it an emulator? In our app we had a problem with samsung devices with an external SD-Card inside. – Thomas Meinhart Jan 24 '22 at 13:41
  • @ThomasMeinhart in physical device (Xiaomi Note 7s). However, later I noticed that when the device is unplugged, the app rarely crashes. – ganjaam Jan 25 '22 at 04:53
  • Can you add the permissions you request to the question? – Thomas Meinhart Jan 26 '22 at 05:48
  • Hi @ganjaam did you find a way to fix this issue ?? – Oussama Ridéne Aug 12 '22 at 13:21
  • @OussamaRidéne, unfortunately, no. Also, I stopped investing time in it because later I found out that it was occurring mostly in Samsung Galaxy M11 and emulator during development phase. And this issue occurs sporadically. After the app is built for production, I almost never encountered this issue. Right now, my app is running on 50k+ devices, but I haven't got any report of this issue in firebase console or user feedback. – ganjaam Aug 13 '22 at 05:04
  • @OussamaRidéne when I posted this question, I was initializing the result launcher everytime the user was clicking the button. but later, I modified the code so that the result launcher was initialized only once in `onCreate()` of the activity. After I did that, I encountered this issue once or twice in 4-5months. But I'm not sure if it is the result of this code modification. It is possible for other factors to be involved, I can't say for sure. – ganjaam Aug 13 '22 at 05:14
  • @OussamaRidéne jut to add, other than the previously mentioned changes, I did not make any other significant changes in code related to this issue. I just updated libraries and stuffs. and I didn't encounter this issue that much in Xiaomi phone. – ganjaam Aug 13 '22 at 05:17

0 Answers0