Получение FileNotFoundException при попытке поделиться MP3 через неявное намерение с использованием FileProvider

1

Я пытаюсь поделиться файлом MP3 из моих внутренних файлов Android (корневым getFilesDir() которого является getFilesDir()) в другое приложение с неявным намерением ACTION_VIEW. Файл MP3 изначально хранился в папке app /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>
Теги:
filenotfoundexception
android-fileprovider

1 ответ

0

посмотрите это свойство: android:exported="false" экспортируемого в файловом провайдере установлено значение false, вы должны установить для него значение true чтобы другие приложения могли использовать вашего провайдера:

<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>

Ещё вопросы

Сообщество Overcoder
Наверх
Меню