2017-07-22 1 views
0

Je n'arrive pas à comprendre pourquoi MediaPlayer joue parfois et parfois ne joue pas le même fichier. Il y a ca. 2000 fichiers audio dans le répertoire. Cela peut arriver à n'importe lequel d'entre eux. À la prochaine exécution de l'application, il peut y avoir d'autres fichiers qui sont affectés. Je n'ai aucune explication à cela.MediaPlayer ne joue pas toujours

Voici le code:

private void play(List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) { 
    Log.d("ENTER lineIndices.size()=", lineIndices.size()); 

    File sdcard = (RUNS_ON_EMULATOR) ? Environment.getExternalStorageDirectory() : new File("/storage/sdcard1"); 

    final List<MediaPlayer> players = new ArrayList<>(); 

    for (Integer index : lineIndices) { 
     Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(index))); 
     Log.d("File URI=%s", uri.toString()); 
     MediaPlayer player = MediaPlayer.create(context, uri); 
     players.add(player); 
    } 

     for (int i = 0; i < players.size() - 1; i++) { 
      players.get(i).setNextMediaPlayer(players.get(i + 1)); 
     } 

    MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() { 
     @Override 
     public void onCompletion(MediaPlayer mediaPlayer) { 
      completionListener.onCompletion(mediaPlayer); 
      for (MediaPlayer player : players) { 
       player.release(); 
      } 
     } 
    }; 

    if (!players.isEmpty()) { 
     players.get(players.size() - 1).setOnCompletionListener(listener); 
     Log.d("Before players.get(0).start();"); 
     players.get(0).start(); 
    } 

    Log.d("EXIT"); 
} 

La sortie du journal indique que le fichier est déterminé et players.get(0).start() est appelé:

com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] ENTER lineIndices.size()= 
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] File URI=file:///storage/sdcard1/tmp/english/vocabulary/000010.wav 
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] Before players.get(0).start(); 
com.android.vocabularytrainer D/VocabularyTrainerModelImpl: [play] EXIT 

J'ai essayé de le résoudre en utilisant une seule MediaPlayer par exemple, non en utilisant la méthode setNextMediaPlayer et en introduisant des appels de méthode setDataSource(), prepare() et reset(). Cela a amélioré un peu la situation, mais il peut toujours arriver qu'un fichier ne soit pas joué. Cependant, cela n'arrive pas si souvent que précédemment.

private void play(final List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) { 
    Log.d("ENTER lineIndices.size()=%d", lineIndices.size()); 

    if (!lineIndices.isEmpty()) { 
     final File sdcard = (RUNS_ON_EMULATOR) ? Environment.getExternalStorageDirectory() : new File("/storage/sdcard1"); 

     final MediaPlayer player = new MediaPlayer(); 
     final Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(lineIndices.get(0)))); 

     try { 
      player.setDataSource(context, uri); 

      MediaPlayer.OnCompletionListener listener = new MediaPlayer.OnCompletionListener() { 
       private int i = 1; 

       @Override 
       public void onCompletion(MediaPlayer mediaPlayer) { 
        if (i < lineIndices.size()) { 
         final Uri uri = Uri.fromFile(new File(sdcard + DEFAULT_FOLDER + getFileName(lineIndices.get(i++)))); 
         try { 
          mediaPlayer.reset(); 
          mediaPlayer.setDataSource(context, uri); 
          mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
           @Override 
           public void onPrepared(MediaPlayer mediaPlayer) { 
            Log.d("%s", uri.toString()); 
            mediaPlayer.start(); 
           } 
          }); 
          mediaPlayer.prepare(); 
          return; 
         } catch (IOException e) { 
          Log.e("Unable to play file", e); 
         } 
        } 

        completionListener.onCompletion(mediaPlayer); 
        mediaPlayer.release(); 
       } 
      }; 

      player.setOnCompletionListener(listener); 

      player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { 
       @Override 
       public void onPrepared(MediaPlayer mediaPlayer) { 
        Log.d("%s", uri.toString()); 
        player.start(); 
       } 
      }); 
      player.prepare(); 

     } catch (IOException e) { 
      Log.e("Unable to play file", e); 
     } 

    } 

    Log.d("EXIT"); 
} 

Répondre

0

Selon mon expérience, cela ressemble à un problème de mémoire insuffisante. Problème se produit au hasard? Problème de mémoire fait. Limitez le nombre de mediaPlayers dans l'application et gérez-les soigneusement (2 ou 3). Ne préparez pas trop les médias. Si je me trompe - MediaPlayer.create() préparera les médias à la création qui consommeront de la mémoire.

MISE À JOUR

je trouve qu'il n'y a pas de référence pour MediaPlayer. Ce qui signifie que MediaPlayer peut être GCed à tout moment. Normalement, mediaPlayer s'arrêtera de jouer quand GCed. Suivre MediaPlayer avec référence.

MediaPlayer mPlayer; // field Variable 
... 
private void play(final List<Integer> lineIndices, final MediaPlayer.OnCompletionListener completionListener) { 
    ... 
    mPlayer = new MediaPlayer(); 
    ... 
+0

Oui. Cela peut arriver à n'importe lequel de ces 2000 fichiers. S'il vous plaît regardez la deuxième version de la méthode dans ma réponse. Je viens de l'ajouter. – ka3ak

+0

Merci pour la réponse, mais je n'ai pas essayé de trouver une solution. J'ai décidé de contourner le problème en utilisant le fichier texte et Google TTS au lieu de milliers de fichiers audio. Mais en ce qui concerne mediaplayer, je pense que certaines de ses fonctionnalités ne sont pas fiables (au moins dans Android 4.2.1). Par exemple. J'ai remarqué que seekTo() ne fonctionne pas bien si le fichier audio dure 2-3 heures. Je suppose que mediaplayer a quelques problèmes avec la lecture de milliers de fichiers qui ne durent que 1 à 2 secondes. Il se peut qu'il ne gère pas bien ce cas d'utilisation. – ka3ak