Android Stop Фоновая музыка - PullRequest
       3

Android Stop Фоновая музыка

26 голосов
/ 05 февраля 2012

РЕДАКТИРОВАТЬ - НАЙТИ ЛЕГКОЕ 5-10 ЛИНЕЙНОЕ РЕШЕНИЕ !!! Смотрите МОЙ СОБСТВЕННЫЙ ОТВЕТ НИЖЕ !!! YAY !!!!!!!!!

Я искал 5 часов, десятки SO сообщений, ответов нет, и это кажется самой простой очевидной чертовой вещью !!!

РЕДАКТИРОВАТЬ - кстати, это НЕ приложение музыкального плеера, а просто приложение для просмотра фотографий и текста, открывает несколько действий, таких как меню и около, просматривать различные типы изображений и т. Д. Я просто хочу играть в простую фоновую музыку, глядя на через фото и текст, почему это так сложно?

еще один РЕДАКТИРОВАТЬ - кажется, главный вопрос на самом деле: "ПОЧЕМУ НАЖМИТЕ НА КНОПКУ ДОМА НЕ ВЫЗЫВАТЬ onPause или onStop ???" -Так я могу знать, когда остановить медиаплеер? и как игры, которые я загружаю на маркете, достигают этого ???

начинается домашняя деятельность

1011 * тогда *

запускается медиаплеер:

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

Игрок объявлен вне onCreate

MediaPlayer player;

Когда открываются другие действия, фоновая музыка продолжает непрерывно, что ХОРОШО, это то, что я хочу.

Теперь, когда я закончу с моим очень простым приложением (которое просто показывает некоторые фотографии и тексты в различных действиях), я либо нажимаю НАЗАД несколько раз, чтобы перейти к домашнему / исходному заданию, а затем еще раз, чтобы «выйти», ИЛИ, я просто нажимаю домой, чтобы «выйти», потому что я СДЕЛАН с этим приложением, и мне больше не нужно слушать эту музыку.


ВАРИАНТ 1

Позвоните player.stop(); в onPause переопределении, это , а не , что я хочу, потому что фоновая музыка останавливается, когда я покидаю домашнюю деятельность для других действий, таких как «меню» и «о», я также Не делайте пауз и возобновлений при открытии новых действий, потому что я не хочу, чтобы красивая фоновая музыка «пропускала» или прерывалась.


ВАРИАНТ 2

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

Это лучше, потому что фоновая музыка не останавливается между действиями, и когда я нажимаю НАЗАД из моего домашнего занятия, музыка останавливается, и я могу продолжать наслаждаться своим забавным телефоном для Android в тишине и покое, но проблема в том, что при нажатии кнопки HOME для «выхода» из моего приложения продолжает играть противная фоновая музыка.


1043 * Как ни странно *

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

Действует так же, как onPause (и я понимаю реальные различия)

РЕДАКТИРОВАТЬ - ТАКЖЕ это не имеет значения, если player.stop (); выше или ниже super.onStop (); но это влияет на то, что я не вижу, в любом случае, все еще нет РЕШЕНИЯ: (

* * Ооооо тысяче сорок-девять

ооооо

РЕДАКТИРОВАТЬ - ДРУГОЙ ВАРИАНТ - НО НЕ РАБОТАЕТ

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

это останавливает музыку, когда я нажимаю HOME, но также останавливает ее, когда я начинаю новые действия: (

РЕДАКТИРОВАТЬ - ОЧЕНЬ ОБЩАЯ РАБОТА Вокруг IV ВИДЕМОГО МНОЖЕСТВА, но, кажется, нелепо делать:

необходимо вести подсчет количества действий, которые были открыты и закрыты (лучше всего было бы использовать onResume и onPause, но это не имеет значения), и когда этот счет достигнет 0, остановите фоновую музыку. Да, это довольно просто, но почему я должен это делать программно, на самом деле САМЫЙ БОЛЬШОЙ ВОПРОС ДЛЯ ЭТОГО ПОЧТЫ:

ПОЧЕМУ НАЖМИТЕ КНОПКУ ДОМА НЕ ВЫЗЫВАТЬ onPause или onStop ???

Поместить его в onDestroy не вариант, потому что onDestroy вызывается только тогда, когда в системе недостаточно памяти или вы принудительно закрываете свое приложение, и это хорошо задокументировано.

Переопределение кнопки HOME также невозможно, поскольку я прочитал, что это «невозможно», и я прочитал, что это «крайне недовольно», в любом случае я избегаю этого.

Я не вижу необходимости создавать SERVICE, и даже если бы я это сделал, когда бы я остановил службу, похоже, у меня возникла бы та же проблема

СЕЙЧАС ЗДЕСЬ это то, что полностью поражает меня, каждая игра и каждое приложение, которое я скачал с Android Market, имеет очень красивую фоновую музыку, и когда я нажимаю BACK или ГЛАВНАЯ, потому что я закончил играть в эту прекрасную игру , музыка перестает , не продолжая играть в фоновом режиме.

Я очень расстроен, и я чувствую, что это потому, что я чувствую, что упускаю что-то очень простое, потому что это одна из самых основных проблем жизненного цикла любого приложения.

Я потратил месяц на чтение каждой страницы developer.android.com, включая руководство по разработке, учебные пособия, примеры проектов и исследование справочного раздела, а также просмотр этой темы в Google в течение 5 часов.

Я также не понимаю, почему 6 или 7 потоков SO с точной такой же проблемой, если не получен ответ, каждое загружаемое приложение на рынке перестает воспроизводить свою музыку ( если это не проигрыватель фоновой музыки), когда вы нажимаете ДОМОЙ или НАЗАД или что-то еще, чтобы «выйти» из приложения, чтобы пойти и сделать что-то еще на своем телефоне.

Чего мне не хватает?

Ответы [ 9 ]

22 голосов
/ 06 февраля 2012

Я очень счастлив сегодня, и все еще есть волосы :) Я проверил это, и это работает !!!

Сначала добавьте это в свой манифест:

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

Во-вторых, добавьте это в свою «Домашнюю / Основную» деятельность / класс:

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

И, очевидно, замените xYourClassNamex на, ну, в общем, ваше имя класса:)

Теперь, очевидно, вам не нужны «Тосты», но они скажут вам, что происходит. Самое интересное, что когда вы нажимаете НАЗАД из своего «Домашнего / Основного» действия, вы, очевидно, получаете 2 тоста: «ВЫ НАЖИМАЛИ НАЗАД ИЗ ВАШЕЙ« ДОМОЙ / ОСНОВНОЙ »ДЕЯТЕЛЬНОСТИ», а 2-й тост - «ВЫ ПОДКЛЮЧИЛИ ДЕЯТЕЛЬНОСТЬ В СВОЕМ ПРИЛОЖЕНИИ ». Мне кажется, я знаю, почему это происходит, но это не имеет значения, потому что я вызываю "player.stop ();" из двух сценариев, которые означают, что мое приложение больше не используется. Очевидно, делать больше работы, чем "player.stop ();" если вам нужно :) И также очевидно, что вам не нужно "else" для "ВЫ ПЕРЕКЛЮЧЕННОЙ ДЕЯТЕЛЬНОСТИ В СВОЕМ ПРИЛОЖЕНИИ", потому что нет причины "останавливать / приостанавливать" фоновую музыку, что мне и нужно, но если вы НЕОБХОДИМО делать что-то, когда начинаются новые действия, ну вот, пожалуйста:)

Надеюсь, что это поможет любому, кто хочет знать, когда пользователь "уходит / выходит / завершает работу" с приложением:)

СПАСИБО ЗА ВСЕ ОТЗЫВЫ И ПОМОЩЬ ВСЕМ !!! YAY!

Edit-

Эта часть должна быть в КАЖДОЙ активности 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();
          }
        }

так что вы будете знать, если пользователь оставил ваше приложение от ЛЮБОГО из действий. это хорошо знать:)

2 голосов
/ 05 февраля 2012

Работа медиаплеера заключается в том, что он работает как служба, а затем останавливается ВРУЧНУЮ, когда пользователь останавливает его в самом приложении.

Пример:

Когда медиаплеер воспроизводит песню и пользователь нажимает кнопку «Домой», очевидно, что пользователь все еще хочет прослушать песню в качестве фоновой задачи. После того, как пользователь завершил прослушивание, он вручную останавливает его, зайдя в приложение и остановив его (Aka останавливая службу, которая воспроизводит песню), или, если список воспроизведения завершен, затем остановите. Простой.

Это ожидаемое поведение. И именно так работает приложение Music.

UPDATE

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

Необходимо изменить на

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

Объяснение:

Причина, по которой мы проверяем, чтобы объект не был нулевым, очевидна. Тем не мение; когда мы входим в паузу, мы хотим убедиться, что медиаплеер останавливается. НО если мы уходим и песня почти закончена, тогда остановите ее и отпустите.

ОБНОВЛЕНИЕ 2

Проверьте ссылку здесь:

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

Это можно использовать для определения того, было ли ваше приложение перемещено из текущей вершины стека приложений.

1 голос
/ 10 июля 2012

Почему бы вам просто не сделать кнопку, чтобы остановить музыку, это намного проще, и вам не нужно каждый раз принудительно закрывать

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

Вот и все, и ключевая аппаратная кнопка возвращается назадоставь, если нажмешь случайно

public boolean onKeyDown(int KeyCode,KeyEvent event){


    return false;
}

И все, настрои его в манифесте и запусти, если возникнут проблемы, дай мне знать

1 голос
/ 05 февраля 2012

как насчет отмены / регистрации в качестве прослушивателя @ службы в onStart() и onStop() методе вашей деятельности, и каждый раз, когда прослушиватель (не) регистрирует вашу службу, проверяет, остались ли какие-либо прослушиватели в его ArrayList<Listener>. если listOfListeners.size() равно 0, то ваша служба вызывает свой метод stopSelf() и убивает себя.

по крайней мере, так я бы это реализовал ...

Итак, вам понадобятся следующие вещи:

  • 2 интерфейса (Observer, Observable)

  • агрегат Observer дюйм Activity, Observable дюйм Service

  • ArrayList<Observer> in Service

  • registerObserver(Observer o) и unregisterObserver(Observer o) in Service

но это только моя точка зрения ...

1 голос
/ 05 февраля 2012

Я столкнулся с той же проблемой.Я расскажу вам свое решение.Я переопределил onStop, onStart каждое действие и посчитал мою начатую деятельность с некоторой задержкой и счетчик достиг нуля, я приостановил музыку.

0 голосов
/ 14 января 2017

Я столкнулся с той же проблемой в процессе разработки.

Я решил это, используя onPause и onResume и методы pause () и start () в проигрывателе, которые я сохранил в своем основном контейнере, вызывая фрагменты вместо действий.

Я держал флаг на синглтоне, чтобы знать, когда музыка была отключена пользователем.

Другая проблема, которую я обнаружил, заключается в том, что мое приложение (IDK, если оно является частью сборки Android) запускало метод onResume непосредственно перед тем, как он снова включил проигрыватель, поэтому я запустил цикл while, чтобы не получить проигрыватель. как нулевой указатель, и он работает, потому что работает в другом потоке, что позволяет приложению запускать onResume без сбоев и музыки вместе с ним.

Я считаю, что это лучше (меньший код для записи) и без разрешения инвазивных;).

0 голосов
/ 25 июля 2015

Для тех, кто все еще ищет решение в виде леденца на палочке или просто без использования разрешения, я предложил другое решение в качестве последнего ресурса.Мы можем измерить время, когда пользователь был afk.Если это было больше, чем X мс, то вы можете считать, что он покинул приложение и остановил музыку.

Поэтому я использую дочерний элемент приложения, в котором храню время afk и BaseActivity для переопределения onPause и onResume всех моих действий.

0 голосов
/ 27 января 2014

В каждом действии привязывайте к сервису в onStart () и отменяйте привязку к сервису в onStop ().Когда запускаете службу, только привязывайтесь к ней и не вызывайте startService (...).

При вызове startService () служба будет продолжать работать до вызова stopService (), независимо от количества действийсвязаны с этим.Если вы не вызовете службу запуска, то служба автоматически остановится, как только все действия от нее отсоединятся.

Таким образом, связывая и отменяя привязку к методам onStart () и onStop () каждого действия, вы обнаружите, чтослужба (музыка) будет продолжаться до тех пор, пока вы не покинете свое приложение с помощью кнопки «Домой», клавиши «Назад», тайм-аута экрана и т. д.

0 голосов
/ 05 февраля 2012
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);
    }
};

это методы класса менеджера.

каждое действие реализуется как после кода

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

Я использую этот код в моей игре, которая опубликована и отлично работает.

Какая часть этого кода ужасна? а где лучшее решение? Я хочу знать, если существует.

Майк, ты ответил мне, мой ответ ужасен и не работает, что с этим не так?

...