23

In androidx.activity version 1.2.0-alpha05 API for TakePicture contract has been changed:

The TakePicture contract now returns a boolean indicating success rather than a thumbnail Bitmap as this was very rarely supported by camera apps when writing the image to the provided Uri

While in alpha04 callback received a Bitmap object, now only a Boolean object that describes success is received by the callback.

So now the Uri Parameter of the launch method of the launcher must not be null, but must be the destination where the picture is saved. Did not manage to create an Uri object that is accepted by the launcher and that can be used for my app to read the result picture.

Does anybody have an example for me for a valid Uri object that can be provided to the launcher?

Werner Harnisch
  • 850
  • 1
  • 7
  • 10

2 Answers2

24

I can't find any example on the internet
Here is an example.

File file = new File(getFilesDir(), "picFromCamera");
Uri uri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", file);

ActivityResultLauncher<Uri> mGetContent = registerForActivityResult(
    new ActivityResultContracts.TakePicture(),
    new ActivityResultCallback<Boolean>() {
        @Override
        public void onActivityResult(Boolean result) {
                            
        // do what you need with the uri here ...
    }
});                        
mGetContent.launch(uri);

Note1: You are likely to run into FileUriExposedException , need to expose this uri for the camera app to access

Related: android.os.FileUriExposedException: file:///storage/emulated/0/test.txt exposed beyond app through Intent.getData()

Note2: If you have <uses-permission android:name="android.permission.CAMERA" /> declared in your manifest, you need to have permission before launching, otherwise java.lang.SecurityException: Permission Denial

BabyishTank
  • 1,329
  • 3
  • 18
  • 39
  • Have you tried this? You'll probably get an IllegalStateException with the message: YourFragment is attempting to registerForActivityResult after being created. But perhaps I'm missing something. – Miguel Lasa Feb 04 '21 at 15:39
  • 2
    In fragments, you should register your ActivitiesResultLaunchers in onAttach or onCreate method – ruif3r Feb 05 '21 at 15:39
  • Not a well explained answer, you should have added some more details, for whether to place above two lines of file and uri. – Kashif Ahmad Jul 05 '22 at 13:27
  • Note: if you are doing this from a fragment, use `requireActivity()` instead of `this`. – Code-Apprentice Nov 01 '22 at 05:11
  • What is `my.package.provider`? Do I need to create a Provider for this and declare it in my AndroidManifest.xml? – Code-Apprentice Nov 01 '22 at 05:17
  • Also from a fragment, use `requireActivity().getApplicationContext().getPackageName()`. Or alternatively, `requireActivity().getPackageName()`. Or `BuildConfig.APPLICATION_ID`. – Code-Apprentice Nov 01 '22 at 05:37
1

thanks @babyishTank for good answer, after adding following changes works for me

    val directory = File(context.filesDir, "camera_images")
    if(!directory.exists()){
        directory.mkdirs()
    }
    val file = File(directory,"${Calendar.getInstance().timeInMillis}.png")
Uri uri = FileProvider.getUriForFile(this, getApplicationContext().getPackageName() + ".provider", file);

ActivityResultLauncher<Uri> mGetContent = registerForActivityResult(
    new ActivityResultContracts.TakePicture(),
    new ActivityResultCallback<Boolean>() {
        @Override
        public void onActivityResult(Boolean result) {
                            
        // do what you need with the uri here ...
    }
});                        
mGetContent.launch(uri);

and in filepaths.xml add following code

<files-path
    name="images"
    path="camera_images/"/>
Mohd Qasim
  • 896
  • 9
  • 20