2011-01-28 11 views
10

Mi aplicación reproduce archivos de recursos de audio del directorio interno designado para mi aplicación (/ data/data/com ...). Parece que descargar los archivos a esa ubicación está bien, setDataSource (String path) no arroja ninguna excepción, pero MediaPlayer.prepare() arroja IOException. El mismo código funciona en la tarjeta SD. ¿Por qué está pasando esto?Los archivos de recursos de reproducción Android del almacenamiento interno provocan que MediaPlayer.prepare dé IOException

EDIT:

Vamos a suponer que este es el código; Es más sencillo de mi código y que arroja la misma excepción:

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(); 
    } 
} 

En cuanto al seguimiento de la pila:

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

Respuesta

23

MediaPlayer requiere que el archivo que se está reproduciendo tiene permisos que sean legibles. Puede ver los permisos del archivo con el siguiente comando en adb shell:

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

es probable que vea "rw ------", lo que significa que sólo el propietario (su aplicación, no MediaPlayer) tiene permisos de lectura/escritura.

Nota: Su teléfono debe estar rooteado para poder utilizar el comando ls sin especificar el archivo (en la memoria interna).

Si el teléfono tiene sus raíces, puede agregar permisos de lectura mundial en adb shell con el comando siguiente:

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

Si necesita modificar estos permisos mediante programación (! Requiere teléfono raíces), puede utilizar el comando siguiente en el código de aplicación:

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

o

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

W que es básicamente un comando de Linux. Consulte https://help.ubuntu.com/community/FilePermissions para obtener más información sobre chmod.

EDIT: Encontrado otro enfoque simple here (útil para aquellos sin teléfonos rooteados). Dado que la aplicación posee el archivo, se puede crear un descriptor de archivo y pasar a que mediaPlayer.setDataSource():

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

Este enfoque evita el problema de permisos por completo.

+0

Gracias, estaba realmente confundido por lo que estaba pasando. Lo estableceré en modo legible a nivel mundial cuando creo el archivo. – AnimatedRNG

+0

@ WRU4Android Ese enfoque funciona muy bien, a menos que esté creando sus archivos con MediaRecorder. Ver http://stackoverflow.com/questions/3038474/can-a-videoview-play-a-video-stored-on-internal-storage/5475436#5475436. – gtkandroid

+0

No, no estoy usando MediaRecorder, solo los estoy descargando en línea. Pero gracias por el consejo. – AnimatedRNG

3

Sé que esta pregunta es anterior a la suciedad, pero me ayudó a resolver mi problema. Lo siguiente funciona bien:

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

La bandera de lectura mundial es la parte importante aquí.

+0

Tenga cuidado con este enfoque, está permitiendo que otras aplicaciones accedan a su archivo (siempre que: 1) esté en el almacenamiento interno, 2) Conozcan su nombre de paquete totalmente calificado, 3) Conozcan el nombre exacto del archivo). –

+0

¿Qué sugerirías? – MattD

+0

Tengo exactamente lo mismo, solo usando un nombre de archivo "cryptic-pseudo-random". No he encontrado ninguna otra solución decente. –

Cuestiones relacionadas