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.
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();
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With