首页 文章

Android停止背景音乐

提问于
浏览
26

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

我搜索了5个小时,数十个SO帖子,没有答案,这似乎是最简单明显的怪异事!

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

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

家庭活动开始

然后

媒体播放器开始:

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

玩家在onCreate之外宣布

MediaPlayer player;

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

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


选项1

onPause 覆盖中调用 player.stop(); ,这是 not 我想要的是因为当我离开家庭活动进行其他活动(如'menu'和'about')时背景音乐停止,我也不知道在打开新活动时使用暂停和恢复是什么因为我不想要漂亮的背景音乐'skip'或被打断 .


方案2

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

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


奇怪

@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市场下载的游戏和 every 应用程序有非常漂亮的背景音乐,当我按BACK或HOME因为我完成了那个可爱的游戏 the music stops ,而不是继续玩的背景 .

我非常沮丧,我觉得这是因为我觉得我很遗憾 very 简单,因为这是任何应用程序最基本的生命周期问题之一 .

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

我也不明白为什么那个带有 exact 同一问题的6或7个SO线程已经被回答了,当你按HOME或BACK或者其他什么时,市场上的每个可下载应用程序都停止播放它的音乐(除非它是一个背景音乐播放器)到"exit"该应用程序将在您的手机上执行其他操作 .

我错过了什么?

9 回答

  • 2

    我今天很开心,还有头发:)我已经测试了这个它的工作原理!!!

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

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

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

    @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();”做更多的工作如果你需要:)而且显而易见你不需要“你在你的应用程序中切换活动”的“其他”,因为没有理由“停止/暂停”背景音乐,这是我需要的,但如果你新活动开始时需要做点什么,好吧,你去吧:)

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

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

    编辑-

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

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

    例:

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

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

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

    一个解释:

    我们检查对象不为空的原因是显而易见的 . 然而;当我们进入暂停状态时,我们希望确保媒体播放器正在停止 . BUT 如果我们要离开并且歌曲差不多完成了,那就停下来然后释放它 .

    UPDATE 2

    点击此处链接:

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

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

  • 1

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

  • 0

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

    至少那是我如何实现这个...

    所以,你需要的东西是:

    • 2接口( ObserverObservable

    • Activity 中实施 Observer ,在 ServiceObservable

    • ArrayList<Observer> in Service

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

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

  • 22

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

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

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

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

    迈克,你回答我,我的回答很可怕而且没有用,这有什么不对?

  • 0

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

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

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

  • 0

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

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

  • 0

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

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

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

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

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

相关问题