Android停止背景音乐

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

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

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

另一个编辑 – 似乎主要的问题是:“为什么按下主页按钮不会调用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覆盖中,这不是我想要的,因为当我离开家庭活动进行其他活动(例如’menu’和’about’)时背景音乐停止,我也不知道在打开新活动时使用暂停和恢复的原因因为我做不希望漂亮的背景音乐“跳过”或被打断。


方案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时,停止背景音乐。 是的,这很简单,但为什么我必须以编程方式执行此操作,实际上这个post的最大问题是:

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

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

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

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

现在,这完全打动了我的想法,我从Android市场下载的每个游戏和每个应用程序都有非常漂亮的背景音乐,当我按BACK或HOME因为我完成了那个可爱的游戏,音乐停止了 ,而不是保持在后台玩。

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

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

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

我错过了什么?

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

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

  

其次,将其添加到您的“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 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是“你在你的APP中切换活动” ”。 我相信我知道为什么会这样,但事实并非如此,因为我称之为“player.stop();” 来自2个场景,这意味着我的应用程序不再被“使用”。 显然比“player.stop();”做更多的工作 如果你需要:)而且很明显你不需要“你在你的应用程序中切换活动”的“其他”,因为没有理由“停止/暂停”背景音乐,这是我需要的,但如果你新活动开始时需要做点什么,好吧,你去吧:)

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

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

编辑-

这部分必须在每个活动的onPause:

 Context context = getApplicationContext(); ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); List 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(); } } 

因此,您将知道用户是否从任何活动中删除了您的应用。 这很好知道:)

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

例:

当媒体播放器正在播放歌曲并且用户回家时,显然用户仍然想要将该歌曲作为其后台任务来收听。 在用户完成收听之后,用户通过进入应用程序并停止(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(); } } } 

一个解释:

我们检查对象不为空的原因是显而易见的。 然而; 当我们进入暂停状态时,我们希望确保媒体播放器正在停止。 但是如果我们要离开并且歌曲几乎完成,那么停止并释放它。

更新2

点击此处链接:

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

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

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

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

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

所以,你需要的东西是:

  • 2接口( ObserverObservable

  • Activity实现Observer ,在Service实现Observable

  • ArrayList

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

但那只是我的观点……

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

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

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

 private static HashMap focus = new HashMap(); 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 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); } 

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

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

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

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

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

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

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

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

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

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

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

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

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