Android:从内容URI获取文件URI?

在我的应用程序中,用户将select应用程序然后处理的audio文件。 问题是,为了使应用程序做我想要做的audio文件,我需要的URI在文件格式。 当我使用Android的本地音乐播放器浏览应用程序中的audio文件时,URI是内容URI,如下所示:

content://media/external/audio/media/710 

但是,使用stream行的文件pipe理器应用程序Astro,我得到以下内容:

 file:///sdcard/media/audio/ringtones/GetupGetOut.mp3 

后者更方便我使用,但我希望应用程序具有用户select的audio文件的function,而不pipe他们用于浏览其collections的程序。 所以我的问题是,有没有办法将content:// style URI转换成file:// URI? 否则,你会推荐什么来解决这个问题? 这里是调用select器的代码,供参考:

 Intent ringIntent = new Intent(); ringIntent.setType("audio/mp3"); ringIntent.setAction(Intent.ACTION_GET_CONTENT); ringIntent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(Intent.createChooser(ringIntent, "Select Ringtone"), SELECT_RINGTONE); 

我使用内容URI执行以下操作:

 m_ringerPath = m_ringtoneUri.getPath(); File file = new File(m_ringerPath); 

然后用这个文件做一些FileInputStream的东西。

只需使用getContentResolver().openInputStream(uri)从URI获取InputStream

http://developer.android.com/reference/android/content/ContentResolver.html#openInputStream(android.net.Uri);

您可以使用Content Resolver从content:// URI获得一个file://path:

 String filePath = null; Uri _uri = data.getData(); Log.d("","URI = "+ _uri); if (_uri != null && "content".equals(_uri.getScheme())) { Cursor cursor = this.getContentResolver().query(_uri, new String[] { android.provider.MediaStore.Images.ImageColumns.DATA }, null, null, null); cursor.moveToFirst(); filePath = cursor.getString(0); cursor.close(); } else { filePath = _uri.getPath(); } Log.d("","Chosen path = "+ filePath); 

尝试通过调用ContentResolver.query()来处理具有content://scheme的URI不是一个好的解决scheme。 在运行4.2.2的HTC Desire上,您可以获得NULL作为查询结果。

为什么不使用ContentResolver呢? https://stackoverflow.com/a/29141800/3205334

如果你有一个内容Uri的content://com.externalstorage...你可以使用这个方法获得Android 19或以上的文件夹或文件的绝对path。

 public static String getPath(final Context context, final Uri uri) { System.out.println("%%%%%%%%%%%%%%%"); final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT; // DocumentProvider if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) { System.out.println("getPath() uri: " + uri.toString()); System.out.println("getPath() uri authority: " + uri.getAuthority()); System.out.println("getPath() uri path: " + uri.getPath()); // ExternalStorageProvider if ("com.android.externalstorage.documents".equals(uri.getAuthority())) { final String docId = DocumentsContract.getDocumentId(uri); final String[] split = docId.split(":"); final String type = split[0]; System.out.println("getPath() docId: " + docId + ", split: " + split.length + ", type: " + type); System.out.println("%%%%%%%%%%%%%%%"); // This is for checking Main Memory if ("primary".equalsIgnoreCase(type)) { if (split.length > 1) { return Environment.getExternalStorageDirectory() + "/" + split[1] + "/"; } else { return Environment.getExternalStorageDirectory() + "/"; } // This is for checking SD Card } else { return "storage" + "/" + docId.replace(":", "/"); } } } return null; } 

你可以检查一下Uri的每个部分是使用println的。 列出了我的SD卡和设备主内存的返回值。 如果文件在内存上,您可以访问和删除,但是我无法使用此方法从SD卡中删除文件 ,只能使用此绝对path读取或打开图像。 如果您find使用此方法删除的解决scheme,请分享。 SD卡

 getPath() uri: content://com.android.externalstorage.documents/tree/612E-B7BF%3A/document/612E-B7BF%3A getPath() uri authority: com.android.externalstorage.documents getPath() uri path: /tree/612E-B7BF:/document/612E-B7BF: getPath() docId: 612E-B7BF:, split: 1, type: 612E-B7BF 

主要记忆

 getPath() uri: content://com.android.externalstorage.documents/tree/primary%3A/document/primary%3A getPath() uri authority: com.android.externalstorage.documents getPath() uri path: /tree/primary:/document/primary: getPath() docId: primary:, split: 1, type: primary 

如果你想获得path使用后得到Uri file:///

 DocumentFile documentFile = DocumentFile.fromFile(new File(path)); documentFile.getUri() // will return a Uri with file Uri 

您应该使用getContentResolver().openInputStream(uri)从URI获取InputStream 。 因为它非常容易理解。 更多openInputStream(android.net.Uri)