尝试使用 FileProvider 共享 MP3 文件时出现 FileNotFoundException

Getting FileNotFoundException When Trying to Share MP3 File Using FileProvider

我正在尝试使用 FileProvider 共享存储在我的应用程序内部存储的原始文件夹中的 MP3 文件,并让用户使用他们选择的音频收听应用程序打开共享的 MP3 文件。

但是,根据我编写的代码,当我尝试执行带有作为数据附加的内容 URI 的意图时,我得到了 FileNotFoundException。这会导致有关 FileProvider 系统的所有其他内容失败。

我创建了一个 MediaPlayer 并让它毫无问题地打开了我想要共享的 MP3 文件,因此我知道该文件存在并且我的应用程序能够访问它。

调试时,我注意到内容 URI 的路径似乎摆脱了 /files/ 目录,即使它在我使用 getUriFromFile 的文件中:

冥想文件:/data/user/0/com.example.selfcareapplication/files/raw/breathing_meditation.mp3

meditationFileContentUri: content://com.example.selfcareapplication.fileprovider/raw/breathing_meditation.mp3

这是我的清单文件中的代码:

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

这是我尝试使用 FileProvider 的代码:

        Intent openMeditationFileIntent = new Intent(Intent.ACTION_VIEW);
        File meditationPath = new File(this.getFilesDir(), "raw");
        File meditationFile = new File(meditationPath, "breathing_meditation.mp3");

        Uri meditationFileContentUri = FileProvider.getUriForFile(this.getApplicationContext(), "com.example.selfcareapplication.fileprovider", meditationFile);
        openMeditationFileIntent.setData(meditationFileContentUri);
        openMeditationFileIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

        if(openMeditationFileIntent.resolveActivity(getPackageManager()) != null) {
            startActivity(openMeditationFileIntent);
        } else {
            Log.d(LOG_TAG, "Could not resolve activity");
        }

这是我尝试启动附带内容 URI 的意图时得到的日志:

2019-04-06 11:45:35.709 4972-4972/? D/MusicLifecycle: com.google.android.music.ui.playback.AudioPreviewActivity generated event: Activity created
2019-04-06 11:45:35.752 4972-4972/? W/MediaPlayer: Couldn't open content://com.example.selfcareapplication.fileprovider/raw/breathing_meditation.mp3: java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
2019-04-06 11:45:35.761 1844-2504/? W/ActivityManager: Permission Denial: opening provider android.support.v4.content.FileProvider from (null) (pid=1694, uid=1013) that is not exported from UID 10092
2019-04-06 11:45:35.766 1694-1776/? E/MediaPlayerService: Couldn't open fd for content://com.example.selfcareapplication.fileprovider/raw/breathing_meditation.mp3
2019-04-06 11:45:35.766 4972-4972/? E/MediaPlayerNative: Unable to create media player
2019-04-06 11:45:35.768 4972-4972/? D/AudioPreviewActivity: Failed to open file: java.io.IOException: setDataSource failed.: status=0x80000000
2019-04-06 11:45:35.810 1584-1626/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 376832
2019-04-06 11:45:35.818 1584-1626/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 376832
2019-04-06 11:45:35.820 1584-1626/? D/gralloc_ranchu: gralloc_alloc: Creating ashmem region of size 376832
2019-04-06 11:45:35.847 4972-4999/? D/EGL_emulation: eglMakeCurrent: 0xea7c5e60: ver 2 0 (tinfo 0xea7b1a10)
2019-04-06 11:45:35.901 4972-4972/? D/MusicLifecycle: com.google.android.music.ui.MusicUrlHandlerActivity generated event: Activity stopped
2019-04-06 11:45:35.931 4972-4972/? D/MusicLifecycle: com.google.android.music.ui.MusicUrlHandlerActivity generated event: Activity destroyed
2019-04-06 11:45:35.939 1684-2170/? D/gralloc_ranchu: gralloc_unregister_buffer: exiting HostConnection (is buffer-handling thread)
2019-04-06 11:45:35.941 1684-2170/? D/gralloc_ranchu: gralloc_unregister_buffer: exiting HostConnection (is buffer-handling thread)
2019-04-06 11:45:35.943 1684-2170/? D/gralloc_ranchu: gralloc_unregister_buffer: exiting HostConnection (is buffer-handling thread)
2019-04-06 11:45:35.944 1684-2170/? D/gralloc_ranchu: gralloc_unregister_buffer: exiting HostConnection (is buffer-handling thread)
2019-04-06 11:45:35.968 1844-3656/? I/MediaFocusControl: abandonAudioFocus() from uid/pid 10069/4972 clientId=android.media.AudioManager@32b5d4dcom.google.android.music.ui.playback.AudioPreviewActivity@6726002
2019-04-06 11:45:35.969 4972-4972/? D/MusicLifecycle: com.google.android.music.ui.playback.AudioPreviewActivity generated event: Activity destroyed
2019-04-06 11:45:36.091 1844-2247/? I/GnssLocationProvider: WakeLock acquired by sendMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@9a951f4)
2019-04-06 11:45:36.092 1844-1857/? I/GnssLocationProvider: WakeLock released by handleMessage(REPORT_SV_STATUS, 0, com.android.server.location.GnssLocationProvider$SvStatusInfo@9a951f4)
2019-04-06 11:45:36.175 4775-4775/? E/GoogleTagManager: Invalid macro: _gtm.loadEventEnabled
2019-04-06 11:45:36.319 1844-1857/? E/memtrack: Couldn't load memtrack module
2019-04-06 11:45:36.319 1844-1857/? W/android.os.Debug: failed to get memory consumption info: -1
2019-04-06 11:45:36.419 4775-5006/? E/GoogleTagManager: Invalid macro: _gtm.loadEventEnabled
2019-04-06 11:45:36.487 4775-4829/? I/MediaStoreImporter: Update: incremental Success: true Added music: 0 Updated music: 0 Deleted music: 0 Created playlists: 0 Updated playlists: 0 Deleted playlists: 0 Inserted playlist items: 0 Deleted playlist items: 0 Removed orphaned playlist items: 0 Total item count: 0
2019-04-06 11:45:36.491 4775-4775/? D/MusicLifecycle: com.google.android.music.download.EncapsulatedBroadcastReceiver generated event: Broadcast received with context com.google.android.music.ui.PhoneMusicApplication@a0c548d and intent Intent { act=com.google.android.music.IMPORT_COMPLETE flg=0x10 }
2019-04-06 11:45:36.609 4775-5008/? E/GoogleTagManager: Invalid macro: _gtm.loadEventEnabled
2019-04-06 11:45:36.637 4775-5000/? E/GoogleTagManager: Unsupported Value Escaping: 3
2019-04-06 11:45:36.752 1844-1955/? E/TaskPersister: File error accessing recents directory (directory doesn't exist?).
2019-04-06 11:45:36.684 4775-5000/? E/GoogleTagManager: Unsupported Value Escaping: 3

I created /raw directory in /res and copied the .mp3 file there

那是在你的开发机器上。

What exactly is the difference between creating a raw/ directory and creating a raw resource if you don't mind my asking?

不同之处在于 getFilesDir() 指的是 Android 设备上的位置。您创建的 raw/ 目录位于您的开发机器上。

Doesn't moving a file into the /res/raw folder turn it into a raw resource that you can reference with R.raw?

是的。但是,这不是您的代码正在做的事情。您的代码正在尝试使用 File 引用它。原始资源是您开发机器上的文件。它们不是设备上的文件。

您需要将原始资源(getResources().openRawResource() 等)复制到一个文件,然后您可以使用 FileProvider.

共享该文件