在API level Q中,MediaStore.MediaColumns.DATA常量被弃用。
应用程序可能没有文件系统权限直接访问此路径。代替直接尝试打开此路径,应用程序应使用ContentResolver#openFileDescriptor(Uri, String)获取访问权限。对于针对Build.VERSION_CODES.Q或更高版本的应用程序,此值将始终为NULL。
在API level Q中,MediaStore.MediaColumns.DATA常量被弃用。
应用程序可能没有文件系统权限直接访问此路径。代替直接尝试打开此路径,应用程序应使用ContentResolver#openFileDescriptor(Uri, String)获取访问权限。对于针对Build.VERSION_CODES.Q或更高版本的应用程序,此值将始终为NULL。
事实上,我们无法获取真正的路径。只需要使用contentResolver()打开流并将文件的整个内容复制到新文件中即可。要获取文件信息,我们需要调用getContentResolver().query()方法,然后就可以获得文件的DISPLAY_NAME和一些其他信息,例如FILE_SIZE。
以下是对于那些赞同此问题的人的简单代码示例:
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();
}
}
val fileDescriptorPath = fileDescriptor(myUri)
//use path and then delete it
fileDescriptorPath?.delete()
private fun fileDescriptor(uri: Uri?): File? {
if (uri == null) return null
var input: FileInputStream? = null
var output: FileOutputStream? = null
val filePath: String = File(context.cacheDir, "tmp.fileExtension").absolutePath
return try {
val parcelFileDescriptor: ParcelFileDescriptor = context.contentResolver.openFileDescriptor(uri, "r")!!
val fileDescriptor = parcelFileDescriptor.fileDescriptor
input = FileInputStream(fileDescriptor)
output = FileOutputStream(filePath)
var read: Int
val bytes = ByteArray(1024)
while (input.read(bytes).also { read = it } != -1) {
output.write(bytes, 0, read)
}
parcelFileDescriptor.close()
File(filePath)
} catch (ignored: IOException) {
Log.v("pathFileDescriptor", "IOException: ${ignored.message}")
null
} finally {
input?.close()
output?.close()
}
}