在具有Android 10(Q)和targetSdkVersion = 29的ExoPlayer上播放歌曲的正确方法是什么?

时间:2019-11-25 17:01:52

标签: android exoplayer exoplayer2.x android-10.0

随着Android 10(Q)的最新更改,尝试在应用程序上播放用户设备上的歌曲(定位为sdk版本 29 ,并运行Android 10 ),使用ExoPlayer在控制台上打印以下日志,但失败(歌曲未播放):

E/libprocessgroup: Error encountered killing process cgroup uid 99420 pid 20294: Permission denied
    com.google.android.exoplayer2.upstream.FileDataSource$FileDataSourceException: java.io.FileNotFoundException: /storage/emulated/0/Music/Nirvana/[1989] - Bleach/01 - Blew.mp3: open failed: EACCES (Permission denied)
        at com.google.android.exoplayer2.upstream.FileDataSource.open(FileDataSource.java:73)
        at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:257)
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:83)
        at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:939)
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:394)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
        at java.lang.Thread.run(Thread.java:919)
     Caused by: java.io.FileNotFoundException: /storage/emulated/0/Music/Nirvana/[1989] - Bleach/01 - Blew.mp3: open failed: EACCES (Permission denied)
        at libcore.io.IoBridge.open(IoBridge.java:496)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:289)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:152)
        at com.google.android.exoplayer2.upstream.FileDataSource.open(FileDataSource.java:65)
        at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:257) 
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:83) 
        at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:939) 
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:394) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:919) 
     Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied)
        at libcore.io.Linux.open(Native Method)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at libcore.io.BlockGuardOs.open(BlockGuardOs.java:252)
        at libcore.io.ForwardingOs.open(ForwardingOs.java:167)
        at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7255)
        at libcore.io.IoBridge.open(IoBridge.java:482)
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:289) 
        at java.io.RandomAccessFile.<init>(RandomAccessFile.java:152) 
        at com.google.android.exoplayer2.upstream.FileDataSource.open(FileDataSource.java:65) 
        at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:257) 
        at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:83) 
        at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:939) 
        at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:394) 
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
        at java.lang.Thread.run(Thread.java:919) 

我在Internet上找到的解决该问题的一种方法是在清单的<application>标签上添加以下属性:

android:requestLegacyExternalStorage="true"

该解决方案的问题在于它似乎是临时的,可能很快就会弃用。


在这些规范下处理这些更改的正确方法是什么?

2 个答案:

答案 0 :(得分:1)

请参见https://stackoverflow.com/a/59037794/2373819

但请查看Exoplayer源代码。

https://github.com/google/ExoPlayer/blob/release-v2/library/core/src/main/java/com/google/android/exoplayer2/upstream/FileDataSource.java

file = new RandomAccessFile(dataSpec.uri.getPath(), "r");

在API 29及更高版本中,公共文件中无法访问文件路径。

您应该在ExoPlayer中引发一个错误,以使用Java fileDescriptor中的contentresolver来代替Java

答案 1 :(得分:0)

经过进一步的试用,我能够使用Media的Uri使用ExoPlayer播放歌曲。

// id col = `MediaStore.Audio.Media._ID`
val id = cursor.getLong(idColIndex)
val uri = ContentUris.withAppendedId(
    MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
    id
)

...

val songSource = ExtractorMediaSource.Factory(dataSourceFactory)
    .createMediaSource(uri)

它成功播放了这首歌,没有引发任何异常。