2011-01-28 10 views
10

La mia app riproduce file di risorse audio dalla directory interna designata per la mia app (/ data/data/com ...). Sembra scaricare i file in quella posizione, ok, setDataSource (percorso String) non genera eccezioni, ma MediaPlayer.prepare() genera IOException. Lo stesso codice funziona sulla scheda SD. Perché sta succedendo?L'esecuzione di file di risorse Android dalla memoria interna fa sì che MediaPlayer.prepare fornisca IOException

EDIT:

Supponiamo che questo è il codice; è più semplice di quanto il mio codice e getta la stessa eccezione:

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

Per quanto riguarda l'analisi dello stack:

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

risposta

23

MediaPlayer richiede che il file in riproduzione dispone di autorizzazioni leggibile in tutto il mondo. È possibile visualizzare i permessi del file con il seguente comando in adb shell:

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

Probabilmente vedrete "-rw ------", il che significa che solo il proprietario (la vostra applicazione, non MediaPlayer) ha permessi di lettura/scrittura.

Nota: il telefono deve essere rootato per poter utilizzare il comando ls senza specificare il file (nella memoria interna).

Se il telefono è radicata, è possibile aggiungere le autorizzazioni di mondo-lettura in adb shell con il seguente comando:

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

Se è necessario modificare queste autorizzazioni a livello di codice (! Richiede telefono radicata), è possibile utilizzare il seguente comando nel codice dell'app:

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

o

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

W che è fondamentalmente un comando linux. Vedi https://help.ubuntu.com/community/FilePermissions per ulteriori informazioni su chmod.

MODIFICA: trovato un altro approccio semplice here (utile per quelli senza telefoni rooted). Dal momento che l'applicazione possiede il file, si può creare un descrittore di file e passare che a mediaPlayer.setDataSource():

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

Questo approccio consente di evitare completamente il problema di autorizzazione.

+0

Grazie, ero davvero confuso su quello che stava succedendo. Lo imposterò in modalità leggibile dal mondo quando creerò il file. – AnimatedRNG

+0

@ WRU4Android Questo approccio funziona alla grande, a meno che non si stiano creando i file con MediaRecorder. Vedi http://stackoverflow.com/questions/3038474/can-a-videoview-play-a-video-stored-on-internal-storage/5475436#5475436. – gtkandroid

+0

No, non sto usando MediaRecorder, sto solo scaricandoli da online. Ma grazie per il suggerimento. – AnimatedRNG

3

So che questa domanda è più vecchia della sporcizia, ma mi ha aiutato a eliminare il mio problema. Di seguito funziona bene:

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

La bandiera leggibile in tutto il mondo è la parte importante qui.

+0

Fai attenzione a questo approccio, stai permettendo ad altre app di accedere al tuo file (a condizione che: 1) questo sia nella memoria interna, 2) Conoscano il tuo nome di pacchetto completo, 3) Conosce il nome esatto del file). –

+0

Cosa suggeriresti? – MattD

+0

Ho esattamente la stessa cosa, usando solo un nome di file "criptico-pseudo-casuale". Non ho trovato nessuna altra soluzione decente. –

Problemi correlati