我正在尝试使用getFilesDir()
隐式意图将android内部文件(其根为ACTION_VIEW
)中的MP3文件共享给另一个应用程序。 MP3文件最初存储在应用程序的/raw
文件夹中,但是我将其复制到了应用程序的内部文件中。
我已使用file.exists()
验证文件存在。但是,当我使用FileProvider构造文件的内容URI并将该内容URI用作隐式意图中的数据时,尝试启动隐式意图时会得到FileNotFoundException: open failed: ENOTDIR
。
我尝试更改FileProvider的权限,并且研究了Android's specifications for sharing a media file using intents,并确保我的隐式意图符合标准。
以下是发生错误时日志窗口的输出:
23349-23349/? D/MusicLifecycle: com.google.android.music.ui.playback.AudioPreviewActivity generated event: Activity created
23349-23349/? W/MediaPlayer: Couldn't open content://com.example.selfcareapplication.fileprovider/meditation-files/breathing-meditation.mp3: java.io.FileNotFoundException: open failed: ENOTDIR (Not a directory)
1844-2784/? W/ActivityManager: Permission Denial: opening provider android.support.v4.content.FileProvider from (null) (pid=1694, uid=1013) that is not exported from UID 10099
1694-2151/? E/MediaPlayerService: Couldn't open fd for content://com.example.selfcareapplication.fileprovider/meditation-files/breathing-meditation.mp3
23349-23349/? E/MediaPlayerNative: Unable to create media player
23349-23349/? D/AudioPreviewActivity: Failed to open file: java.io.IOException: setDataSource failed.: status=0x80000000
这是我获取文件,创建FileProvider并启动意图的代码:
Intent openMeditationFileIntent = new Intent(Intent.ACTION_VIEW);
File testFile = new File(this.getFilesDir(), "meditation-files\\breathing-meditation.mp3");
//check if file was written to internal memory. It prints "FILE WAS OUTPUT!"
if(testFile.exists()) {
Log.d(LOG_TAG, "FILE WAS OUTPUT!");
} else {
Log.d(LOG_TAG, "FILE WAS NOT OUTPUT!!!");
}
//create content URI using FileProvider and the testFile
Uri meditationFileContentUri = FileProvider.getUriForFile(this.getApplicationContext(), "com.example.selfcareapplication.fileprovider", testFile);
openMeditationFileIntent.setDataAndType(meditationFileContentUri, "audio/*");
openMeditationFileIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//try to open implicit intent using content URI as its data:
if(openMeditationFileIntent.resolveActivity(getPackageManager()) != null) {
startActivity(openMeditationFileIntent);
} else {
Log.d(LOG_TAG, "Could not resolve activity");
}
这是我的清单:
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.selfcareapplication.fileprovider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
</provider>
这是我的file_paths.xml文件:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="meditation-files" path="meditation-files/"/>
</paths>
编辑:
我能够使它正常工作! 根据@CommonsWare的建议,我将MIME Type更改为““ audio / mpeg”“,这是MP3的MIME类型。
我还删除了路径名中的连字符。这样做似乎会导致无法将MP3文件正确写入“ getFilesDir()+“ meditationPaths”“,因为在MP3路径上检查“ file.exists()”将返回false。将路径中的“ \”更改为“ /”可以解决此问题。
也就是说,当我稍后进行一些进一步的测试时,我发现'\'和'/'都允许MP3正确编写...因此,我不确定我是第一次出什么毛病。我只建议使用“ File.separator”来确保针对程序所运行的环境自动使用正确的分隔符。
这是获取文件,创建FileProvider并启动意图的最终代码:
Intent openMeditationFileIntent = new Intent(Intent.ACTION_VIEW);
File testFile = new File(this.getFilesDir(), "meditationFiles" + Path.separator + "breathingMeditation.mp3");
//check if file was written to internal memory. It prints "FILE WAS OUTPUT!"
if(testFile.exists()) {
Log.d(LOG_TAG, "FILE WAS OUTPUT!");
} else {
Log.d(LOG_TAG, "FILE WAS NOT OUTPUT!!!");
}
//create content URI using FileProvider and the testFile
Uri meditationFileContentUri = FileProvider.getUriForFile(this.getApplicationContext(), "com.example.selfcareapplication.fileprovider", testFile);
openMeditationFileIntent.setDataAndType(meditationFileContentUri, "audio/mpeg");
openMeditationFileIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
//try to open implicit intent using content URI as its data:
if(openMeditationFileIntent.resolveActivity(getPackageManager()) != null) {
startActivity(openMeditationFileIntent);
} else {
Log.d(LOG_TAG, "Could not resolve activity");
}
我还必须更改file-paths.xml文件以反映文件夹名称中的更改:
<paths xmlns:android="http://schemas.android.com/apk/res/android">
<files-path name="meditationFiles" path ="meditationFiles"/>
</paths>