Я пытаюсь поделиться файлом MP3 из внутренних файлов моего андроида (корень которого getFilesDir()
) в другое приложение с неявным намерением ACTION_VIEW
.Файл MP3 изначально хранился в папке /raw
моего приложения, но я скопировал его во внутренние файлы моего приложения.
Я подтвердил, что файл существует, используя file.exists()
.Однако когда я использую FileProvider для создания URI контента для файла и использую этот URI контента в качестве данных в неявном намерении, я получаю FileNotFoundException: open failed: ENOTDIR
, когда пытаюсь запустить неявное намерение.
Я попытался изменить полномочия FileProvider, и я изучил спецификации Android для совместного использования медиа-файла с помощью намерений и убедился, что мое неявное намерение соответствует стандартам.
Вот вывод из окна журнала при возникновении ошибки:
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 на «audio / mpeg», который является типом MIME для MP3.
Я также вынул гипс в названиях путей.Похоже, что из-за этого было невозможно правильно записать MP3-файл в getFilesDir () + «meditationPaths», поскольку проверка «file.exists ()» на пути к MP3 вернула бы 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>