2012-04-10 3 views
9

Sto scrivendo un'applicazione di allarme Android che utilizza un servizio per riprodurre il tono di allarme. Attualmente, sono in grado di riprodurre l'audio, ma viene riprodotto in una forma che può essere disattivata abbassando il volume del dispositivo. Pertanto, sto cercando di aggiungere una chiamata a setAudioStreamType(AudioManager.STREAM_ALARM); per impedirlo.(Android MediaPlayer) Come dovrei chiamare setAudioStreamType() se MediaPlayer.create() chiama implicitamente prepare()?

ho il seguente per la mia onStartCommand() funzione per il servizio:

MediaPlayer mMP;  
@Override 
    public int onStartCommand(Intent intent, int flags, int startId) 
    { 
     try 
     { 
      mMP = MediaPlayer.create(this, R.raw.alarm); 
      mMP.setAudioStreamType(AudioManager.STREAM_ALARM); 
      mMP.setLooping(true); 
      //mMP.prepare(); commented out since prepare() is called in create 
     } 
     catch (Exception e) 
     { 
      e.printStackTrace(); 
     } 
     if (mMP != null) mMP.start(); 

     return START_STICKY; 
    } 

Il mio problema è che con la chiamata a setAudioStreamType(), il MediaPlayer non riproduce l'audio. Se commento questa battuta, l'audio suona.

Con la linea a, ottengo il seguente errore di runtime (s):

04-10 19: 32: 03,115: E/MediaPlayer (3411): setAudioStream chiamato stato 8

04-10 19: 32: 03,115: E/MediaPlayer (3411): errore (-38, 0)

04-10 19: 32: 03,115: E/MediaPlayer (3411): inizio chiamato nello stato 0

04-10 19: 32: 03.115: E/MediaPlayer (3411): errore (-38, 0)

04-10 19: 32: 03,115: E/MediaPlayer (3411): Errore (-38,0)

04-10 19: 32: 03,115: E/MediaPlayer (3411): Errore (- 38,0)

Alcune ricerche (non riesco a trovare il link ora) mi ha detto che setAudioStreamType() non può essere chiamato dopo prepare() è stato chiamato, e che create() chiama implicitamente prepare().

In ogni caso, come dovrei setAudioStreamType() senza un tale errore?

risposta

12

È possibile chiamare mp.reset() e quindi impostare il tipo di flusso, l'origine dati e quindi preparare. In alternativa, basta usare il costruttore predefinito e gestire da solo l'inizializzazione.

EDIT:

Resources res = getResources(); 
AssetFileDescriptor afd = res.openRawResourceFd(R.raw.alarm); 

mp.reset(); 
mp.setAudioStreamType(AudioManager.STREAM_ALARM); 
mp.setLooping(true); 
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength()); 
mp.prepare(); 
mp.start(); 
+0

Sembra che si sta suggerendo qualcosa in questo senso (a partire dopo la chiamata a 'create()'): 'reset();' 'setAudioStreamType();' 'setLooping();' 'prepare();' Sono corretto? In tal caso, ricevo il seguente errore nella chiamata per la preparazione: '04-10 20: 06: 25.515: E/MediaPlayer (845): avvio chiamato nello stato 1' ' 04-10 20: 06: 25.515: E/MediaPlayer (845): errore (-38, 0) ' – finiteloop

+0

Sembra che tu stia ricevendo l'errore sulla chiamata a' start() 'in realtà, non' prepare() '. Puoi aggiungere il tuo codice aggiornato alla domanda? – kcoppock

+0

Hai ragione, quel particolare errore è sorto dopo la chiamata per iniziare, c'è anche un errore nella chiamata per preparare che mi sono perso nel log quando stavo postando il mio commento. '04-10 21: 42: 11.896: E/MediaPlayer (593): prepareAsync chiamato nello stato 1'. – finiteloop

2

risposta accettata stava gettando un IllegalStateException. Questo è il lavoro

MediaPlayer mediaPlayer = new MediaPlayer(); 

try { 
    mediaPlayer.setDataSource(
      this, 
      getCustomToneUri() 
); 

    mediaPlayer.setAudioStreamType(AudioManager.STREAM_NOTIFICATION); 

    mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
    @Override 
    public void onPrepared(MediaPlayer mp) { 
     mp.start(); 
    } 
    }); 

    mediaPlayer.prepareAsync(); 
} catch (IOException e) { 
    e.printStackTrace(); 
}