SOLVED -- Saving an image from Photo Picker in app folder for permanent access

56 views Asked by At

I have a database (SQLite) in which i want to store a path to an image. I am using the PhotoPicker to get the image, I set it with "setImageURI()", this part works (the PhotoPicker is clearly returning the wanted image). The Uri is stored into the ImageViews Tag and accessed later to be put into the database as a string.

When i open the part of the fragment that should show me the image after i saved everything (including Uri) into the database: it works finde. The Uri is getting retrieved and the image can be shown in the ImageView by parsing the string from the database to an Uri, ...

But: the Uri from the Photopicker (the entry in the database is: content://media/picker/0/com.android.providers.media.photopicker/media/1000000033) is temporary. When i re-open the app, the app can no longer access the Uri ("java.lang.SecurityException: Calling uid ( 10190 ) does not have permission to access picker uri").

The question is: how can i still access an Uri after closing the app?

Should I copy the image to a folder the app can always access? (What would be the code, including permissions, to copy and retrieve??) Can I access such an Uri permanently? (What would be the code??) Would there be a better solution?

My code for starting the PhotoPicker (called in a Button.OnClickListener):

private static void pickImage() {
        Intent intent = new Intent(MediaStore.ACTION_PICK_IMAGES);
        resultLauncher.launch(intent);
    }

The code for getting its result:

private void registerResult() {
        resultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), new ActivityResultCallback<ActivityResult>() {
            @Override
            public void onActivityResult(ActivityResult o) {
                try {
                    Uri imageUri = o.getData().getData();
                    imageView.setImageURI(imageUri);
                    imageView.setTag(imageUri);

                } catch (Exception e) {
                    e.printStackTrace();
                    Toast.makeText(getContext(), "Error!", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }

The code getting the Uri from the database:

stringUri = cursor.getString(5);
Uri imageUri = Uri.parse(stringUri);
                alertBuilderPflanzeBild.setImageURI(imageUri);
                alertBuilderPflanzeBild.setTag(imageUri);

The error:

java.lang.SecurityException: Calling uid ( 10190 ) does not have permission to access picker uri: content://media/picker/0/com.android.providers.media.photopicker/media/1000000033

-- MY SOLUTION: I get the image from the imageView in here:

private static String savePic (ImageView imageView, String subfolder, String pictureName) {
        // subfolder: Pflanzen, Rezepte, ..
        BitmapDrawable drawable = (BitmapDrawable) imageView.getDrawable();
        Bitmap bitmap = drawable.getBitmap();
        try {
            File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM)+"/Pictures/[APP_NAME]/"+subfolder+"/",pictureName+".jpg");

            if (!file.exists()) {
                Log.d(TAG, "Folder '" + file.toString() + "' doesn't exist, creating it...");
                boolean rv = Objects.requireNonNull(file.getParentFile()).mkdir();
                Log.d(TAG, "Folder creation " + ( rv ? "success" : "failed"));
            } else {
                Log.d(TAG, "Folder already exists.");
            }

            FileOutputStream out = new FileOutputStream(file);
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, out);
            out.flush();
            out.close();
            return file.getAbsolutePath();

        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

To get the picture from its path I call:

private static Bitmap getPic (String path) {
        File file = new File(path);
        Bitmap bmap=BitmapFactory.decodeFile(file.getAbsolutePath());
        //imageView.setImageBitmap(bmap);
        return bmap;
    }

-- C O N C L U S I O N: At first i load the non-permanent image from its PhotoPicker-Uri into the imageView. I then copy that picture with savePic() into a known folder that belongs to my app. The path (returned by savePic() is put into a database. To load the pic into an imageView i simply call getPic().

0

There are 0 answers