Montoya
Montoya

Reputation: 3049

Android - save photo to path - RESULT_CANCELLED

Since I had bugs on different devices I decided to changed the whole open camera and save picture code. I have used the exact same code in the Android tutorial.

My code:

private static File createImageFile(Activity activity) throws IOException {
    // Create an image file name
    String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());
    String imageFileName = "JPEG_" + timeStamp + "_";
    File storageDir = activity.getExternalFilesDir(Environment.DIRECTORY_PICTURES);
    File image = File.createTempFile(
            imageFileName,  /* prefix */
            ".jpg",         /* suffix */
            storageDir      /* directory */
    );

    // Save a file: path for use with ACTION_VIEW intents
    photoPath = image.getAbsolutePath();
    return image;
}

private static void dispatchTakePictureIntent(Activity activity) {
    Intent takePictureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
    // Ensure that there's a camera activity to handle the intent
    if (takePictureIntent.resolveActivity(activity.getPackageManager()) != null) {
        // Create the File where the photo should go
        File photoFile = null;
        try {
            photoFile = MainActivity.createImageFile(activity);
        } catch (IOException ex) {
            // Error occurred while creating the File
        }
        // Continue only if the File was successfully created
        if (photoFile != null) {
            imageUri = FileProvider.getUriForFile(activity,
                    "com.APPPACKAGE.fileprovider",
                    photoFile);
            takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            activity.startActivityForResult(takePictureIntent, REQUEST_TAKE_PHOTO);
        }
    }
}

On the manifest file:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="18" />

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.APPPACKAGE.fileprovider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths"/>
</provider>

Using this works great on a Android 6 Marshmallow, on Android 4.4 Kitkat it doesn't. On Kitkat my onActivityResult i recieve from the camera result = 0 which is RESULT_CANCELLED.

I've checked if the camera was able to save the photo on the location specified in the file_paths.xml and it didn't. this folder is filled with 0 bytes files.

What can i do to fix it?

Upvotes: 0

Views: 178

Answers (2)

Montoya
Montoya

Reputation: 3049

Thanks to @CommonsWare i added this code and it works:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.LOLLIPOP) {
                takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            }
            else if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.JELLY_BEAN) {
                ClipData clip=
                        ClipData.newUri(activity.getContentResolver(), "A photo", imageUri);

                takePictureIntent.setClipData(clip);
                takePictureIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
            }
            else {
                List<ResolveInfo> resInfoList=
                        activity.getPackageManager()
                                .queryIntentActivities(takePictureIntent, PackageManager.MATCH_DEFAULT_ONLY);

                for (ResolveInfo resolveInfo : resInfoList) {
                    String packageName = resolveInfo.activityInfo.packageName;
                    activity.grantUriPermission(packageName, imageUri,
                            Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
                }
            }

Upvotes: 0

CommonsWare
CommonsWare

Reputation: 1007554

Not all camera apps will support content as a scheme for the EXTRA_OUTPUT Uri. Google's own camera app did not support it until the summer of 2016, for example. And, since we are passing the Uri via an extra, we have no means of limiting ourselves to camera apps that support content.

Your main options are:

  1. Reduce your targetSdkVersion below 24 and stick with Uri.fromFile(), rather than using FileProvider

  2. Use StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().build()); to disable the FileUriExposedException, then stick with Uri.fromFile(), rather than using FileProvider

  3. Scrap your use of ACTION_IMAGE_CAPTURE entirely, switching to the camera APIs directly or via some helper library (e.g., mine)

Tactically, you might get better results if you use setClipData() to force granting of permissions on your Uri.

Upvotes: 1

Related Questions