【问题标题】:Android playing resource files from internal storage causes MediaPlayer.prepare to give IOExceptionAndroid 从内部存储播放资源文件导致 MediaPlayer.prepare 给出 IOException
【发布时间】:2011-01-28 22:43:35
【问题描述】:

我的应用从为我的应用指定的内部目录 (/data/data/com...) 播放音频资源文件。似乎可以将文件下载到该位置,setDataSource(String path) 不会引发任何异常,但 MediaPlayer.prepare() 会引发 IOException。相同的代码适用于 SD 卡。为什么会这样?

编辑:

假设这是代码;它比我的代码更简单,并且抛出相同的异常:

package com.app.MediaPlayerTest;

public class MediaTest extends Activity {
    MediaPlayer mp;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DownloadFiles();
        MusicPlay();
    }

    public void DownloadFiles() {
        //Downloads Files
    }

    public void MusicPlay()
    {
            try {
                mp.setDataSource("/data/data/com.app.pronounce/winds.mp3");
            } catch (IllegalArgumentException e1) {
                e1.printStackTrace();
            } catch (IllegalStateException e1) {
                e1.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        try {
            mp.prepare();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        mp.setLooping(true);
        mp.start();
    }
}

关于堆栈跟踪:

(mutexes: tll=0 tsl=0 tscl=0 ghl=0 hwl=0 hwll=0)
"main" prio=5 tid=1 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x4001f1a8 self=0xce48
  | sysTid=338 nice=0 sched=0/0 cgrp=bg_non_interactive handle=-1345006528
  | schedstat=( 151460588 425586896 45 )
  at android.os.BinderProxy.transact(Native Method)
  at android.app.ActivityManagerProxy.handleApplicationCrash(ActivityManagerNative.java:2547)
  at com.android.internal.os.RuntimeInit$UncaughtHandler.uncaughtException(RuntimeInit.java:76)
  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:854)
  at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:851)
  at dalvik.system.NativeStart.main(Native Method)

"Binder Thread #2" prio=5 tid=8 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40512b30 self=0x156e90
  | sysTid=346 nice=0 sched=0/0 cgrp=default handle=1570912
  | schedstat=( 4357682 930487 3 )
  at dalvik.system.NativeStart.run(Native Method)

"Binder Thread #1" prio=5 tid=7 NATIVE
  | group="main" sCount=1 dsCount=0 obj=0x40512a68 self=0x17f578
  | sysTid=345 nice=0 sched=0/0 cgrp=bg_non_interactive handle=604904
  | schedstat=( 6939806 13372136 3 )
  at dalvik.system.NativeStart.run(Native Method)

"Compiler" daemon prio=5 tid=6 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x4050eba8 self=0x938c8
  | sysTid=344 nice=0 sched=0/0 cgrp=bg_non_interactive handle=1099136
  | schedstat=( 4770066 33579300 5 )
  at dalvik.system.NativeStart.run(Native Method)

"JDWP" daemon prio=5 tid=5 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x4050eaf8 self=0x10c3c0
  | sysTid=343 nice=0 sched=0/0 cgrp=bg_non_interactive handle=1098624
  | schedstat=( 14899224 33240040 20 )
  at dalvik.system.NativeStart.run(Native Method)

"Signal Catcher" daemon prio=5 tid=4 RUNNABLE
  | group="system" sCount=0 dsCount=0 obj=0x4050ea38 self=0x93570
  | sysTid=342 nice=0 sched=0/0 cgrp=bg_non_interactive handle=588000
  | schedstat=( 24278832 4707632 7 )
  at dalvik.system.NativeStart.run(Native Method)

"GC" daemon prio=5 tid=3 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x4050e990 self=0x8f720
  | sysTid=341 nice=0 sched=0/0 cgrp=bg_non_interactive handle=1099336
  | schedstat=( 791698 556969 3 )
  at dalvik.system.NativeStart.run(Native Method)

"HeapWorker" daemon prio=5 tid=2 VMWAIT
  | group="system" sCount=1 dsCount=0 obj=0x4050e8d8 self=0x10c740
  | sysTid=340 nice=0 sched=0/0 cgrp=bg_non_interactive handle=1357728
  | schedstat=( 211702049 225986921 9 )
  at dalvik.system.NativeStart.run(Native Method)

【问题讨论】:

    标签: android resources media-player ioexception prepare


    【解决方案1】:

    MediaPlayer 要求正在播放的文件具有世界可读的权限。可以在 adb shell 中使用以下命令查看文件的权限:

    ls -al /data/data/com.mypackage/myfile
    

    您可能会看到“-rw------”,这意味着只有所有者(您的应用,而不是 MediaPlayer)拥有读/写权限。

    注意:您的手机必须root才能使用ls命令而不指定文件(在内存中)。

    如果你的手机已经root,你可以在adb shell中添加world-read权限,命令如下:

    chmod o+r /data/data/com.mypackage/myfile
    

    如果您需要以编程方式修改这些权限(需要 root 手机!),您可以在您的应用代码中使用以下命令:

    Runtime.getRuntime().exec("chmod o+r /data/data/com.mypackage/myfile");
    

    或

    Runtime.getRuntime().exec("chmod 777 /data/data/com.mypackage/myfile");
    

    这基本上是一个 linux 命令。有关 chmod 的更多信息,请参阅 https://help.ubuntu.com/community/FilePermissions。

    编辑:找到了另一种简单的方法here(对那些没有根电话的人有用)。由于应用程序拥有该文件,它可以创建一个文件描述符并将其传递给 mediaPlayer.setDataSource():

    FileInputStream fileInputStream = new FileInputStream("/data/data/com.mypackage/myfile");
    mediaPlayer.setDataSource(fileInputStream.getFD());
    

    这种方法完全避免了权限问题。

    【讨论】:

    • 谢谢,我对发生的事情感到非常困惑。创建文件时,我会将其设置为世界可读模式。
    • @WRU4Android 这种方法效果很好,除非您使用 MediaRecorder 创建文件。见stackoverflow.com/questions/3038474/…。
    • 不,我没有使用 MediaRecorder,我只是从网上下载它们。不过谢谢你的提示。
    【解决方案2】:

    我知道这个问题比污垢更古老,但它帮助我解决了我的问题。以下工作正常:

          FileOutputStream outStream= openFileOutput("movie.mp4", MODE_WORLD_READABLE);
    

    世界可读的标志是这里的重要部分。

    【讨论】:

    • 小心这种方法,你让其他应用程序访问你的文件(前提是:1)这是在内部存储中,2)他们知道你的完全合格的包名称,3)他们知道确切的文件名)。
    • 你有什么建议?
    • 我有完全相同的东西,只使用“神秘的伪随机”文件名。我还没有找到任何其他合适的解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-24
    相关资源
    最近更新 更多