web-dev-qa-db-fra.com

Android Arrêter la musique de fond

EDIT - TROUVEZ UNE SOLUTION FACILE 5-10 LIGNES !!! Voir ma propre réponse ci-dessous !!! YAY!!!!!!!!!

J'ai cherché pendant 5 heures, des dizaines de SO messages, aucune réponse, et cela semble être la chose la plus évidente qui soit!)

EDIT- btw, ce n'est PAS une application de lecteur de musique, juste une application pour afficher des photos et du texte, ouvre plusieurs activités comme le menu et environ, afficher différents types d'images, etc. Je veux juste jouer de la musique de fond simple tout en regardant à travers les photos et le texte, pourquoi est-ce si difficile?

un autre EDIT - il semble que la question principale soit vraiment: "POURQUOI LA PRESSION DU BOUTON HOME N'APPELLE PAS onPause ou onStop ???" -puis-je savoir quand arrêter le lecteur multimédia? et comment les jeux que je télécharge sur le marché y parviennent-ils ???

l'activité à domicile commence

ensuite

le lecteur multimédia démarre:

player = MediaPlayer.create(this, R.raw.idil);
player.setLooping(true);
player.setVolume(100,100);
player.start();

Le joueur a déclaré en dehors de onCreate

MediaPlayer player;

Lorsque d'autres activités sont ouvertes, la musique de fond continue sans interruption, ce qui est BON, c'est ce que je veux.

Maintenant, quand j'en ai fini avec mon très application simple (qui montre juste quelques photos et textes dans des activités différentes), je clique plusieurs fois sur RETOUR pour revenir à l'activité d'origine/d'origine, puis une de plus il est temps de "quitter", OU, j'appuie simplement sur home pour "quitter" parce que j'ai terminé avec cette application et je n'ai plus besoin d'entendre cette musique.


OPTION 1

Appelez player.stop(); dans un remplacement onPause, c'est pas ce que je veux car la musique de fond s'arrête lorsque je quitte l'activité à la maison pour d'autres activités comme 'menu' et ' à propos de ', je ne sais pas non plus quoi utiliser pause et reprendre lors de l'ouverture de nouvelles activités car je ne veux pas que la jolie musique de fond saute ou soit interrompue.


OPTION 2

@Override
    protected void onPause() {
        super.onPause();
        if (this.isFinishing()){
            player.stop();
        }
    }

C'est mieux parce que la musique de fond ne s'arrête pas entre les activités et lorsque j'appuie sur RETOUR depuis mon activité à domicile, la musique s'arrête et je peux continuer à profiter de mon Android téléphone amusant en toute tranquillité, mais le problème est que lorsque vous appuyez sur le bouton HOME pour "quitter" mon application, la musique de fond embêtante continue de jouer.


BIZARREMENT

@Override
protected void onStop() {
        super.onStop();
        if (this.isFinishing()){
            player.stop();
        }
    }

Fait la même chose que onPause (et je comprends les différences réelles)

EDIT- ÉGALEMENT, cela ne semble pas avoir d'importance si player.stop (); est au-dessus ou au-dessous de super.onStop (); mais cela affecte quelque chose que je ne peux pas voir, de toute façon, toujours pas de SOLUTION :(

ooooo

ooooo

ÉDITER - UNE AUTRE OPTION - MAIS NE FONCTIONNE PAS

public void onUserLeaveHint() {
    player.stop();
    super.onUserLeaveHint();
}

cela arrête la musique lorsque j'appuie sur ACCUEIL mais il l'arrête également lorsque je commence de nouvelles activités :(

EDIT - UN TRAVAIL TRÈS COMMUN AUTOUR D'AVOIR VU DE MULTIPLES LIEUX, mais semble ridicule à faire:

il faut essentiellement compter le nombre d'activités qui ont été ouvertes et fermées (onResume et onPause serait probablement le meilleur, mais cela ne semble pas pertinent) et lorsque ce nombre atteint 0, arrêtez la musique de fond. OUI c'est assez simple, mais pourquoi dois-je le faire par programme, en fait la PLUS GRANDE QUESTION POUR CELA POST IS:

POURQUOI APPUYER SUR LE BOUTON HOME N'APPELLE PAS onPause ou onStop ???

Le mettre dans onDestroy n'est pas une option car onDestroy n'est appelé que lorsque le système manque de mémoire, ou que vous forcez la fermeture de votre application, et cela est bien documenté.

Surcharger le bouton HOME n'est pas non plus une option car j'ai lu que c'est "pas possible" et j'ai lu que c'est "extrêmement mal vu", de toute façon j'évite cela.

Je ne vois pas la nécessité de créer un SERVICE, et même si je le faisais, quand arrêterais-je le service, il semble que j'aurais le même problème

MAINTENANT ICI IS LA CHOSE qui me souffle complètement, chaque jeu et chaque application que j'ai téléchargée à partir du Android market a une très belle musique de fond, et quand j'appuie sur BACK ou HOME parce que j'ai fini de jouer à ce joli jeu la musique s'arrête, ne continue pas à jouer en arrière-plan.

Je suis très frustré, et je pense que c'est parce que j'ai l'impression de manquer quelque chose très simple, car c'est l'un des problèmes de cycle de vie les plus élémentaires de toute application.

J'ai passé un mois à lire chaque page de developer.Android.com, y compris le guide de développement, les didacticiels, les exemples de projets et la recherche dans la section Référence, ainsi qu'à rechercher ce sujet sur Google pendant 5 heures.

Je ne comprends pas non plus pourquoi les 6 ou 7 SO threads avec le exact même problème, ont pas répondu, toutes les applications téléchargeables) sur le marché arrête de lire sa musique (sauf s'il s'agit d'un lecteur de musique de fond) lorsque vous appuyez sur HOME ou BACK ou autre chose pour "quitter" l'application pour aller faire autre chose sur votre téléphone.

Qu'est-ce que je rate?

26
Mike

Je suis très heureux aujourd'hui et j'ai toujours des cheveux :) J'ai testé ça et ça marche !!!

Ajoutez d'abord ceci à votre manifeste:

<uses-permission Android:name="Android.permission.GET_TASKS"/>

Deuxièmement, ajoutez ceci à votre activité/classe "Accueil/Principal":

  @Override
  protected void onPause() {
    if (this.isFinishing()){ //basically BACK was pressed from this activity
      player.stop();
      Toast.makeText(xYourClassNamex.this, "YOU PRESSED BACK FROM YOUR 'HOME/MAIN' ACTIVITY", Toast.LENGTH_SHORT).show();
    }
    Context context = getApplicationContext();
    ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
    if (!taskInfo.isEmpty()) {
      ComponentName topActivity = taskInfo.get(0).topActivity; 
      if (!topActivity.getPackageName().equals(context.getPackageName())) {
        player.stop();
        Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP", Toast.LENGTH_SHORT).show();
      }
      else {
        Toast.makeText(xYourClassNamex.this, "YOU SWITCHED ACTIVITIES WITHIN YOUR APP", Toast.LENGTH_SHORT).show();
      }
    }
    super.onPause();
  }

Et évidemment, remplacez xYourClassNamex par, eh bien, votre nom de classe :)

Maintenant, évidemment, vous n'avez pas besoin des "Toasts" mais cela vous dira ce qui se passe. Le plus intéressant est que lorsque vous appuyez sur BACK de votre activité 'Home/Main', vous obtenez évidemment 2 toasts, "VOUS AVEZ APPUYÉ SUR VOTRE ACTIVITÉ 'HOME/MAIN'", et le 2ème Toast est "VOUS AVEZ COMMUTÉ LES ACTIVITÉS DANS VOTRE APP ". Je crois que je sais pourquoi cela se produit, mais cela n'a pas d'importance parce que j'appelle "player.stop ();" des 2 scénarios qui signifient que mon application n'est plus "utilisée". Évidemment, faites plus de travail que "player.stop ();" si vous en avez besoin :) Et il est également évident que vous n'avez pas besoin du "else" pour "VOUS AVEZ COMMUTÉ DES ACTIVITÉS DANS VOTRE APP", car il n'y a aucune raison de "stop/pause" la musique de fond, ce dont j'ai besoin, mais si vous AVEZ besoin de faire quelque chose lorsque de nouvelles activités commencent, et bien voilà! :)

J'espère que cela aide quiconque cherche à savoir quand l'utilisateur "quitte/quitte/a terminé" l'application :)

MERCI POUR TOUS LES COMMENTAIRES ET AIDEZ TOUT LE MONDE !!! YAY!

ÉDITER-

Cette partie doit être dans CHAQUE activité onPause:

Context context = getApplicationContext();
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
        List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
        if (!taskInfo.isEmpty()) {
          ComponentName topActivity = taskInfo.get(0).topActivity; 
          if (!topActivity.getPackageName().equals(context.getPackageName())) {
            player.stop();
            Toast.makeText(xYourClassNamex.this, "YOU LEFT YOUR APP", Toast.LENGTH_SHORT).show();
          }
        }

vous saurez donc si l'utilisateur a quitté votre application à partir de TOUTES les activités. C'est bon à savoir :)

22
Mike

Le lecteur multimédia fonctionne de la manière suivante: il s'exécute en tant que service, puis s'arrête MANUELLEMENT lorsque l'utilisateur l'arrête dans l'application elle-même.

Exemple:

Lorsque le lecteur multimédia lit une chanson et que l'utilisateur revient à la maison, il est évident que l'utilisateur souhaite toujours écouter la chanson comme tâche d'arrière-plan. Une fois que l'utilisateur a fini d'écouter, l'utilisateur l'arrête manuellement en allant dans l'application et en l'arrêtant (Aka arrêtant le service qui joue la chanson) ou si la liste de lecture est terminée, alors arrêtez. Facile.

C'est le comportement attendu. Et c'est exactement ainsi que fonctionne l'application Music.

[~ # ~] mise à jour [~ # ~]

@Override
    protected void onPause() {
        super.onPause();
        if (this.isFinishing()){
            player.stop();
        }
    }

Doit être changé en

@Override
    protected void onPause() {
        super.onPause();
        if (mediaPlayer != null){
            mediaPlayser.stop();
            if (isFinishing()){
            mediaPlayer.stop();
            mediaPlayer.release();
            }
        }
    }

Une explication:

La raison pour laquelle nous vérifions que l'objet n'est pas nul est évidente. Pourtant; lorsque nous entrons dans la pause, nous voulons nous assurer que le lecteur multimédia s'arrête. [~ # ~] mais [~ # ~] si nous partons et que la chanson est presque terminée, alors arrêtez-la et relâchez-la.

MISE À JOUR 2

Consultez le lien ici:

https://stackoverflow.com/a/6704844/529691

Cela peut être utilisé pour détecter si votre application a été déplacée hors de la pointe actuelle de la pile d'applications.

2
JoxTraex

comment est-il sur un/s'inscrire en tant qu'auditeur @ le service dans la méthode onStart() et onStop() de vos activités et chaque fois qu'un auditeur est (dés) enregistré, vos vérifications de service s'il en a auditeurs laissés dans son ArrayList<Listener>. si la listOfListeners.size() est 0 alors votre service appelle sa méthode stopSelf() et se tue.

c'est du moins ainsi que je mettrais en œuvre cela ...

donc, les choses dont vous auriez besoin sont:

  • 2 interfaces (Observer, Observable)

  • implémenter Observer dans Activity, Observable dans Service

  • ArrayList<Observer> Dans Service

  • registerObserver(Observer o) et unregisterObserver(Observer o) dans Service

mais c'est juste mon point de vue ...

1
herom

Pourquoi ne faites-vous pas simplement un bouton pour arrêter la musique, c'est tellement plus facile et vous n'avez pas à forcer la fermeture à chaque fois

Button exit =(Button) findViewById(R.id.exit);

    exit.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v)
            {
                // TODO: Implement this method

                startActivity(new Intent("com.justme.worldexplorer.EXIT"));             
                finish();
                Music I'd.stop();}});}

Là vous allez et donc le dos du bouton du matériel clé quitte le doseur si vous appuyez par accident

public boolean onKeyDown(int KeyCode,KeyEvent event){


    return false;
}

Et voilà, il l'a installé dans le manifeste et exécuté si des problèmes me le font savoir

1
the android dude

J'ai rencontré le même problème. Je vais vous dire ma solution. Je remplace onStop, onStart chaque activité et compte mon activité démarrée avec un certain retard et le compte atteint zéro, j'ai mis la musique en pause.

1
lulumeya

Pour ceux qui recherchent toujours une solution dans Lollipop ou tout simplement sans autorisation, j'ai trouvé une autre solution comme dernière ressource. Nous pouvons mesurer le temps passé par l'utilisateur. Si c'était plus de X ms, alors vous pouvez considérer qu'il a quitté l'application et arrêter la musique.

J'utilise donc Application child où je stocke le temps afk et BaseActivity pour remplacer onPause et onResume de toutes mes activités.

0
Vito Valov
private static HashMap<String, Boolean> focus = new HashMap<String, Boolean>();

public static void check(Context context, boolean hasFocus)
{
    handler.removeMessages(0);
    focus.put(((Activity)context).getLocalClassName(), hasFocus);
    handler.sendEmptyMessageDelayed(0, 500);
}

public static void check(String classname, boolean hasFocus)
{
    handler.removeMessages(0);
    focus.put(classname, hasFocus);
    handler.sendEmptyMessageDelayed(0, 500);
}

private static Handler handler = new Handler()
{
    @Override
    public void handleMessage(Message msg)
    {
        Iterator<Boolean> it = focus.values().iterator();
        while(it.hasNext())
        {
            if(it.next())
                return;
        }
        pause();
        super.handleMessage(msg);
    }
};

il s'agit d'une méthode de classe gestionnaire.

chaque activité implémentant comme après le code

@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    MusicManager.check(this, hasFocus);
    super.onWindowFocusChanged(hasFocus);
}

J'utilise ce code avec mon jeu qui est publié et fonctionne très bien.

Quelle partie de ce code est terrible? et où est la meilleure solution? Je veux savoir s'il existe.

Mike, tu m'as répondu que ma réponse est terrible et ne fonctionne pas, qu'est-ce qui ne va pas?

0
lulumeya

J'ai rencontré le même problème avec mon processus de développement.

J'ai résolu cela en utilisant les méthodes onPause et onResume et avec pause () et start () dans le lecteur que j'ai enregistré sur mon conteneur principal, en appelant des fragments au lieu d'activités.

J'ai gardé un drapeau sur un singleton afin de savoir quand la musique a été désactivée par l'utilisateur.

Un autre problème que j'ai trouvé est que mon application (idk si elle fait partie de la Android ou non) exécutait la méthode onResume juste avant de remettre le lecteur en marche, j'ai donc exécuté une boucle while dans afin de recevoir le lecteur non pas comme un pointeur nul, et cela fonctionne car il s'exécute sur un thread différent, permettant ainsi à l'application d'exécuter onResume sans se bloquer et la musique à côté.

Je le trouve meilleur (code plus petit à écrire) et invasif sans permission;).

0
user2438341

Dans chaque activité, liez au service dans onStart () et dissociez-le du service dans onStop (). Lorsque vous démarrez le service, liez-le uniquement et n'appelez pas startService (...).

En appelant startService (), le service continuera de fonctionner jusqu'à ce que stopService () soit appelé, quel que soit le nombre d'activités qui lui sont liées. Si vous n'appelez pas le service de démarrage, le service s'arrêtera automatiquement une fois que toutes les activités auront été libérées.

Ainsi, en liant et en dissociant les méthodes onStart () et onStop () de chaque activité, vous constaterez que le service (musique) continuera jusqu'à ce que vous quittiez votre application avec le bouton d'accueil, la touche retour, le délai d'expiration de l'écran, etc.

0
TomEverin