Android停止背景音乐

时间:2012-02-05 10:49:09

标签: android background media-player

编辑 - 找到一个简单的5-10线解决方案!看下面我自己的答案! YAY !!!!!!!!!

我已经搜索了5个小时,数十个SO帖子,没有答案,这看起来像是最简单明显的怪异事情!!!

编辑顺便说一句,这不是一个音乐播放器应用程序,只是一个应用程序来查看图片和文本,打开多个活动,如菜单和关于,查看差异类型的图片等。我只是想播放一些简单的背景音乐,同时寻找通过图片和文字,为什么这么难?

另一个编辑 - 似乎主要问题是: “为什么按下按钮不会打开onPause或onStop ???” - 我可以知道何时停止媒体播放器?我在市场上下载的游戏如何完成这个???

家庭活动开始

然后

媒体播放器启动:

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

在onCreate

之外宣布的玩家
MediaPlayer player;

当其他活动被打开时,背景音乐会不间断地继续,这很好,这就是我想要的。

现在,当我完成了我的非常简单应用程序(只显示差异活动中的一些图片和文本)时,我要么多次单击BACK以进入主页/原始活动,并且然后又一次“退出”,或者,我只是按回家“退出”,因为我已经完成了这个应用程序,我不再需要听到那些音乐了。


选项1

player.stop();覆盖中拨打onPause,这是我想要的,因为当我离开家庭活动以进行“菜单”和“其他活动”时,背景音乐会停止关于',我也不知道在打开新活动时使用什么暂停和恢复,因为我不希望漂亮的背景音乐'跳过'或被打断。


选项2

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

这是更好的,因为背景音乐不会在活动之间停止,当我从我的家庭活动按BACK时,音乐停止,我可以继续享受我的安卓乐趣,安静,但是问题是,当按下HOME按钮“退出”我的应用程序时,那讨厌的背景音乐一直在播放。


奇怪

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

与onPause相同(我确实理解实际的差异)

编辑 - 这似乎并不重要,如果player.stop();高于或低于super.onStop();但它影响了我无法看到的东西,无论哪种方式,仍然没有解决方案:(

OOOOO

OOOOO

编辑 - 另一个选项 - 但不工作

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

当我按HOME时停止播放音乐,但是当我开始新活动时它也会停止播放:(

编辑 - 我看到多个地方非常常见的工作,但似乎很荒谬:

essentialy保持已经打开和关闭的活动数量的计数(onResume和onPause最好,但这点不相关),当该计数达到0时,停止背景音乐。是的,这很简单,但为什么我必须以编程方式执行此操作,实际上这个帖子的最大问题是:

为什么按下主页按钮不打开onPause或onStop ???

将它放入onDestroy不是一个选项,因为onDestroy只在系统内存不足时调用,或者你强制关闭你的应用程序,并且记录良好。

覆盖HOME按钮也是没有选择的,因为我读过它“不可能”而且我读过它“非常不满意”,无论哪种方式我都避免这样做。

我认为没有必要创建SERVICE,即使我这样做了,我何时会停止服务,似乎我会遇到同样的问题

现在,这完全打击了我的想法,每个游戏以及我从Android市场下载的每个应用程序都有非常漂亮的背景音乐,当我按下回来或回家,因为我玩完了那个可爱的游戏音乐停止,而不是继续在后台播放。

我非常沮丧,我觉得这是因为我觉得我错过了一些非常简单的东西,因为这是任何应用程序最基本的生命周期问题之一。

我花了一个月的时间阅读developer.android.com的每一页,包括开发指南,教程,示例项目和研究参考部分,以及谷歌这个主题5个小时。

我也不明白为什么6个或7个具有完全相同问题的SO线程,已被回答,市场上的每个可下载应用程序都停止播放音乐(除非它是背景音乐播放器)当您按HOME或BACK或任何“退出”应用程序以在手机上执行其他操作时。

我错过了什么?

9 个答案:

答案 0 :(得分:22)

今天我很开心,还有头发:) 我已经测试了这个并且它可以工作!!!

首先,将此添加到您的清单中:

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

其次,将其添加到“Home / Main”活动/班级:

  @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:)

现在显然你不需要“Toasts”,但它会告诉你发生了什么。 非常有趣的是当你从'Home / Main'活动中按BACK时,你显然会得到2个Toast,“你从你的'主页/主要'活动中回来了”,而第二个Toast是“你在你的应用程序中切换的活动” ”。我相信我知道为什么会这样,但事实并非如此,因为我称之为“player.stop();”来自2个场景,这意味着我的应用程序不再被“使用”。显然比“player.stop();”做更多的工作如果你需要:)而且显而易见你不需要“你在你的应用程序中切换活动”的“其他”,因为没有理由“停止/暂停”背景音乐,这是我需要的,但如果你当新的活动开始时,你需要做些什么吗,好的就在这里:)

希望这可以帮助任何想知道用户何时“离开/退出/完成”应用程序的人:)

感谢所有评论的帖子,并帮助每个人! YAY!

编辑 -

这部分必须在每个活动的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();
          }
        }

这样您就可以知道用户是否从任何活动中删除了您的应用。这很好知道:)

答案 1 :(得分:2)

媒体播放器的工作方式是它作为服务运行,然后当用户在应用程序本身停止它时手动停止。

示例:

当媒体播放器正在播放歌曲并且用户回家时,显然用户仍然希望将该歌曲作为其后台任务来收听。在用户完成收听之后,用户通过进入应用程序并停止(Aka停止正在播放歌曲的服务)或者播放列表完成后手动停止它,然后停止。简单。

这是预期的行为。这正是音乐应用程序的工作原理。

<强>更新

@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

这可用于检测您的应用程序是否已移出应用程序堆栈的当前提示。

答案 2 :(得分:1)

我遇到了同样的问题。我会告诉你我的解决方案。 我重写onStop,onStart每个活动并计算我的开始活动有一些延迟,计数达到零,我暂停了音乐。

答案 3 :(得分:1)

如何在您的活动的onStart()onStop()方法中取消/注册为监听器@服务,并且每次监听器(未)注册时,您的服务都会检查是否有一些监听器留在ArrayList<Listener>。如果listOfListeners.size()0,那么您的服务会调用其stopSelf()方法并自行终止。

至少我会如何实现这个......

所以,你需要的是:

  • 2个接口(ObserverObservable

  • ObserverActivity

  • Observable实施ServiceArrayList<Observer>

  • ServiceregisterObserver(Observer o)

  • unregisterObserver(Observer o)Service

但这只是我的观点......

答案 4 :(得分:1)

为什么不用一个按钮来停止音乐这么容易,你不必每次都强行关闭

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

这就是它在清单中设置并运行,如果有任何问题让我知道

答案 5 :(得分:0)

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

我在我的游戏中使用此代码,该游戏已发布并且运行良好。

这段代码的哪一部分很糟糕?哪里有更好的解决方案?我想知道是否存在。

迈克,你回答我的回答是可怕的,不行,这有什么不对?

答案 6 :(得分:0)

在每个活动中,绑定到onStart()中的服务,并从onStop()中的服务解除绑定。启动服务时,只绑定它,不要调用startService(...)。

通过调用startService(),服务将继续运行,直到调用stopService(),无论绑定到它的活动数量是多少。如果您不调用启动服务,则一旦所有活动都未绑定,该服务将自动停止。

因此,通过对每个活动的onStart()和onStop()方法进行绑定和解除绑定,您会发现服务(音乐)将继续,直到您使用主页按钮,后退键,屏幕超时等离开应用程序。 / p>

答案 7 :(得分:0)

对于那些仍在寻找棒棒糖解决方案或者没有使用权限的人,我想出了另一个解决方案作为最后的资源。我们可以衡量用户的健康时间。如果它超过X毫秒,那么你可以考虑他离开应用程序并停止音乐。

所以我正在使用Application子存储时间afk和BaseActivity来覆盖我所有活动的onPause和onResume。

答案 8 :(得分:0)

我的开发过程遇到了同样的问题。

我通过在我的主容器中保存的播放器中使用onPause和onResume以及pause()和start()方法来解决这个问题,调用片段而不是活动。

我在单身人士上留了一面旗帜,以便知道用户何时关闭了音乐。

我发现的另一个问题是我的应用程序(idk,如果它是android构建的一部分)是在他重新启动播放器之前运行onResume方法,所以我运行了一个while循环以便不接收播放器作为一个空指针,它的工作原理是因为它在不同的线程上运行,因此使应用程序能够运行onResume而不会崩溃并且音乐与它并行。

我发现它更好(编写更小的代码)和非许可侵入;)。