编辑 - 找到一个简单的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时,停止背景音乐。是的,这很简单,但为什么我必须以编程方式执行此操作,实际上这个帖子的最大问题是:
将它放入onDestroy不是一个选项,因为onDestroy只在系统内存不足时调用,或者你强制关闭你的应用程序,并且记录良好。
覆盖HOME按钮也是没有选择的,因为我读过它“不可能”而且我读过它“非常不满意”,无论哪种方式我都避免这样做。
我认为没有必要创建SERVICE,即使我这样做了,我何时会停止服务,似乎我会遇到同样的问题
现在,这完全打击了我的想法,每个游戏以及我从Android市场下载的每个应用程序都有非常漂亮的背景音乐,当我按下回来或回家,因为我玩完了那个可爱的游戏音乐停止,而不是继续在后台播放。
我非常沮丧,我觉得这是因为我觉得我错过了一些非常简单的东西,因为这是任何应用程序最基本的生命周期问题之一。
我花了一个月的时间阅读developer.android.com的每一页,包括开发指南,教程,示例项目和研究参考部分,以及谷歌这个主题5个小时。
我也不明白为什么6个或7个具有完全相同问题的SO线程,不已被回答,市场上的每个可下载应用程序都停止播放音乐(除非它是背景音乐播放器)当您按HOME或BACK或任何“退出”应用程序以在手机上执行其他操作时。
我错过了什么?
答案 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个接口(Observer
,Observable
)
在Observer
,Activity
Observable
实施Service
在ArrayList<Observer>
中 Service
在registerObserver(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而不会崩溃并且音乐与它并行。
我发现它更好(编写更小的代码)和非许可侵入;)。