12

MediaStore.MediaColumns.DATA constant was deprecated in API level Q.

Apps may not have filesystem permissions to directly access this path. Instead of trying to open this path directly, apps should use ContentResolver#openFileDescriptor(Uri, String) to gain access. This value will always be NULL for apps targeting Build.VERSION_CODES.Q or higher.

Paranoid
  • 214
  • 2
  • 14
  • 1
    No one knows the solution of this ? ? ? – Paranoid Jul 11 '19 at 08:28
  • I'm confused about what you're asking. [I edited the question](https://stackoverflow.com/revisions/55796224/3) based on what I thought you were asking, but I see you've rejected that edit. Could you explain how what you're asking is different from what I asked in the edit? – Jacob O'Bryant Aug 06 '19 at 04:35
  • 4
    The problem is how to get real_path instead of content URI of file that is present inside our android device in **android 29** – Paranoid Aug 09 '19 at 12:14
  • Is there any solution? – Himanshu Oct 07 '19 at 18:35

2 Answers2

2

This is true we can't get the real path. Just Simple method open stream with contentResolver() and copy the whole content of file into new file and for getting file information we need to call a query() method of a getContentResolver().query() then we can get DISPLAY_NAME of the file and some more info like FILE_SIZE.

Simple code Example for those who upvoted the question:

public class MainFragment extends Fragment {

    private Button openGallery;
    private File selectedFile;
    private Context context;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        context = container.getContext();
        return inflater.inflate(R.layout.fragment_question, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        openGallery = view.findViewById(R.id.openGallery);
        openGallery.setOnClickListener(v->browseFile());
    }


    private void browseFile() {

        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
            openFiles();
        } else {
            requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, 786);
        }
    }

    private void openFiles() {

        deleteFileFromCacheDir();

        Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
        intent.setType("*/*");
        intent.addCategory(Intent.CATEGORY_OPENABLE);

        if (intent.resolveActivity(context.getPackageManager()) != null) {
            startActivityForResult(intent, 786);
        }
    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (requestCode == 786 && resultCode == -1 && data != null) {

            Uri uri = data.getData();
            openStreamAndCopyContent(uri); // Here i am just copy the content of file and paste it into my new file. You can check the type of the file image/video/audio & do it whatever you want

            // Now here is your file

            if (selectedFile != null && selectedFile.exists()){
                // Do it whatever you want Or send it to server 
            } 

        }

    }

    private void openStreamAndCopyContent(Uri uri) {

        try {

            String fileName = "temp" + System.currentTimeMillis() + "." + MimeTypeMap.getSingleton().getExtensionFromMimeType(context.getContentResolver().getType(uri));
            selectedFile = new File(context.getCacheDir().getAbsolutePath() + File.separator + fileName);

            InputStream inputStream = context.getContentResolver().openInputStream(uri);

            if (inputStream != null) {
                Utility.copy(inputStream, selectedFile);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == 786) {
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                openFiles();
            } else if (grantResults[0] == PackageManager.PERMISSION_DENIED && getActivity() != null) {

                if (!ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE)) {

                    new AlertDialog.Builder(context).setTitle(R.string.permission_required).setMessage(R.string.permission_message)
                            .setPositiveButton(R.string.open_settings, (dialog, which) ->
                                    context.startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS,
                                            Uri.parse("package:" + BuildConfig.APPLICATION_ID)))).setNegativeButton(R.string.close, null).show();
                }
            }
        }
    }


    private void deleteFileFromCacheDir() {

        if (selectedFile != null && selectedFile.exists()) {
            if (selectedFile.delete()) {
                selectedFile = null;
            }
        }
    }

    @Override
    public void onDestroyView() {

        deleteFileFromCacheDir();

        super.onDestroyView();
    }



    }
Paranoid
  • 214
  • 2
  • 14
  • Is it possible to get the name of the original file? – Sudhir Singh Khanger Apr 15 '20 at 17:02
  • 1
    @SudhirKhanger yes its pretty simple once you will get the URI in onActivityResult () method just call getContext().getContentResolver().query() method .. in query method pass Uri and the columns array in your case just pass DISPLAY_NAME Column. And you can get the name of that file. For Coding example check how to use query method on google. – Paranoid Apr 15 '20 at 21:23
  • Can you please post the header files that you have used – Amanpreet Kaur Nov 12 '22 at 11:25
  • @AmanpreetKaur What exactly you want to check. I do not have this code now. Tell me what exactly you want to check I will try to help you. – Paranoid Nov 12 '22 at 19:27
  • @Paranoid I have resolved the issue. Thank you for replying. Will definitely post here in case anyone needs – Amanpreet Kaur Nov 14 '22 at 09:20
1

I believe it is not possible, as you simply don't need that path from a programming stand point.

You cannot read/change/delete the file with the real path. You should use a ContentResolver for these operations as stated in your question.

If you just want to show the path to the user, then I would suggest to either give an option to open/share the file with an Intent.createChooser or just show the MediaColumns.RELATIVE_PATH.

cuzi
  • 978
  • 10
  • 21