安卓媒体播放器在后台播放,但应用程序被关闭时不会停止播放

20

我是Android新手,所以我有一个问题。在Android中,我想要在我的音乐播放器启动时播放背景音乐,并且即使活动从一个更改到另一个,它也能继续播放。我已经尝试了这段代码:

MediaPlayer music = MediaPlayer.create(MainActivity.this, R.drawable.bgscore);
music.start();

然而,当用户关闭应用程序时,声音应该停止,但实际上它没有停止。我该怎么做才能实现这一点?


1
使用服务播放您的音乐。检查此链接是否有可下载的示例:https://thenewcircle.com/s/post/60/servicesdemo_using_android_services - Raghunandan
同意 - 无法保证在活动不可见时声音会继续播放 - 系统负载和内存短缺时可能会销毁您的活动。此外,当其他应用程序的活动可见时,您的应用程序可能正在运行 - 这就是音乐播放器的预期工作方式,但这是否符合您的期望? - marko
@shahbaz pothiawala,你找到正确的解决方案了吗?我是这样做的。我编写了一个绑定服务。在应用程序类中处理服务的启动和停止。在每个活动中,我在onStart()中启动服务,并在onPause()中停止服务。 - Prashanth Debbadwar
在服务中创建媒体播放器...工作完成! - Dhaval Parmar
太好了。在我的情况下,当我关闭我的应用程序时,我的下载服务会停止(类似于您的媒体播放)。您是如何设法使您的服务在应用程序被杀死时仍然能够工作的? - Neon Warge
10个回答

9
创建一个单独的类来处理多个条件。
import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;

public class MusicManager {
    static final int MUSIC_PREVIOUS = -1;
    private static final String TAG = "MusicManager";
    static MediaPlayer mp;
    private static int currentMusic = -1;
    private static int previousMusic = -1;


    public static void start(Context context, int music) {
        start(context, music, false);
    }

    public static void start(Context context, int music, boolean force) {
        if (!force && currentMusic > -1) {
// already playing some music and not forced to change
            return;
        }

        if (music == MUSIC_PREVIOUS) {
            Log.d(TAG, "Using previous music [" + previousMusic + "]");
            music = previousMusic;
        }
        if (currentMusic == music) {
// already playing this music
            return;
        }
        if (currentMusic != -1) {
            previousMusic = currentMusic;
            Log.d(TAG, "Previous music was [" + previousMusic + "]");
// playing some other music, pause it and change
            pause();
        }
        currentMusic = music;
        Log.d(TAG, "Current music is now [" + currentMusic + "]");
        if (mp != null) {
            if (!mp.isPlaying()) {
                mp.start();
            }
        } else {
            mp = MediaPlayer.create(context, R.raw.backGroundMusic); //Ur BackGround Music
        }

        if (mp == null) {
            Log.e(TAG, "player was not created successfully");
        } else {
            try {
                mp.setLooping(true);
                mp.start();
            } catch (Exception e) {
                Log.e(TAG, e.getMessage(), e);
            }
        }
    }

    public static void pause() {
        if (mp != null) {
            if (mp.isPlaying()) {
                mp.pause();
            }
        }

// previousMusic should always be something valid
        if (currentMusic != -1) {
            {
                previousMusic = currentMusic;
                Log.d(TAG, "Previous music was [" + previousMusic + "]");
            }
            currentMusic = -1;
            Log.d(TAG, "Current music is now [" + currentMusic + "]");
        }
    }

    public static void release() {
        Log.d(TAG, "Releasing media players");
        try {
            if (mp != null) {
                if (mp.isPlaying()) {
                    mp.stop();
                }
                mp.release();
            }
        } catch (Exception e) {
            Log.e(TAG, e.getMessage(), e);
        }

        if (currentMusic != -1) {
            previousMusic = currentMusic;
            Log.d(TAG, "Previous music was [" + previousMusic + "]");
        }
        currentMusic = -1;
        Log.d(TAG, "Current music is now [" + currentMusic + "]");
    }
}

然后在您的 MainActivity 中定义一个全局布尔变量,并在 onCreate() 方法中的 setContentView(....) 之前将其设置为 true,例如:

    boolean continueBGMusic;
    ....
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        continueBGMusic=true;
    setContentView(R.layout.activity_main);
    .....
    }

那么,将onPause()更新为:

    public void onPause()
        {
            super.onPause();
            if(!continueBGMusic)
                MusicManager.pause();
    }

onResume()翻译为

    public void onResume()
        {
            super.onResume();

                continueBGMusic=false;
                MusicManager.start(this,R.raw.backGroundMusic);
    }

将您的三个活动都更新为布尔变量和两种方法。


@Bhava:我按照你上面发布的一切设置好了,但是音乐没有播放。我在途中错过了什么吗? - Fisnik B.

4
如果您的活动不是很多,您可以通过在需要播放音乐的活动中添加布尔标志来管理此任务。当您停止一个活动时,这些标志将告诉您其他活动是否需要您的MediaPlayer。
因此,在您的主要活动中:
public class MainActivity extends Activity {

    static MediaPlayer introPlayer;
    static boolean sActive;

    @Override
    protected void onResume() {

    // starting the player if it is not playing
        if (!introPlayer.isPlaying()) {
            introPlayer.start();
            introPlayer.setLooping(true);
        }

        // true when activity is active
        sActive = true;
        super.onResume();
    }

    @Override
    protected void onPause() {

        sActive = false;
        super.onPause();
    }

    @Override
    protected void onStop() {

        // before stoping mediaplayer checking whether it is not used by other          activities

        if (introPlayer.isPlaying()
                && !(Activity2.sActive || Activity3.sActive)) {
            introPlayer.pause();
        }

        super.onStop();

    }
}

其他活动:

public class Activity2 extends Activity {

    static boolean sActive;

    @Override
    protected void onPause() {
        sActive = false;

        super.onPause();
    }

    @Override
    protected void onStop() {

        // pausing the player in case of exiting from the app
        if (MainActivity.introPlayer.isPlaying() && !(MainActivity.sActive || Activity3.sActive)) {
            MainActivity.introPlayer.pause();
        }

        super.onStop();
    }

    @Override
    protected void onResume() {
        sActive = true;

        if (!MainActivity.introPlayer.isPlaying()) {
            MainActivity.introPlayer.start();
            MainActivity.introPlayer.setLooping(true);
        }

        super.onResume();
        }
}

And

public class Activity3 extends Activity {

    static boolean sActive;

    @Override
    protected void onPause() {
        sActive = false;

        super.onPause();
    }

    @Override
    protected void onStop() {

        // pausing the player in case of exiting from the app
        if (MainActivity.introPlayer.isPlaying() && !(MainActivity.sActive || Activity2.sActive)) {
            MainActivity.introPlayer.pause();
        }

        super.onStop();
    }

    @Override
    protected void onResume() {
        sActive = true;

        if (!MainActivity.introPlayer.isPlaying()) {
            MainActivity.introPlayer.start();
            MainActivity.introPlayer.setLooping(true);
        }

        super.onResume();
        }
}

2

试试这个

@Override
public boolean onKeyDown(int keyCode, KeyEvent event)  {
    if (keyCode == KeyEvent.KEYCODE_BACK ) {
        music.stop();
        return true;
    }

    return super.onKeyDown(keyCode, event);
}

如果您有任何单独的按钮操作来关闭应用程序,则可以调用music.stop()。

1
如果用户按下主页按钮结束应用程序,或者应用程序被电话呼叫或其他事情中断,该怎么办? - Shahbaz Pothiawala
2
这里有一个巨大的假设,即用户使用返回按钮导航离开应用程序,并且该应用程序只有一个活动。但这两个条件都不是确定的。 - marko
@Marko - 我真的接受你所说的,但我无法考虑到Shahbaz需要的所有逻辑,但这是停止音乐的方法..... - Siva K
@shahbazpothiawala - 你也可以在OnPause和onDestriy方法中尝试调用music.stop()。 - Siva K
2
Siva,如果我想要像你提供的临时解决方案一样的临时解决方案,我就不会在堆栈溢出中问这个问题。那是一个明显但不正确的答案。在发布问题之前已经考虑过所有这些临时解决方案。我想要的只是一个适用于任何情况的合适的解决方案。 - Shahbaz Pothiawala
显示剩余3条评论

0

要开始播放音乐,您需要找出我们的应用程序何时启动。我们可以通过扩展Application类来实现。应用程序对象在任何活动之前实例化,并在Android操作系统终止我们的应用程序之前保留。

这使得它非常适合仅在此对象内控制播放。当我们创建一个扩展Application的新类时,我们必须将其注册到我们的清单中。

我们已经确定了应用程序何时被创建,但是当我们的应用程序从前台转到后台时,如何停止音乐呢?Android没有开箱即用的方法来确定这一点。为了解决这个问题,我遵循了这篇非常好的文章,其中部分解决方案代码也来自那里。

应用程序代码:

package com.example.stackmusic; 

import android.app.Activity;
import android.app.Application;
import android.media.MediaPlayer;
import android.os.Bundle;


public class PlayMusicApp extends Application {


private MediaPlayer music;
@Override
public void onCreate() {
    super.onCreate();
    registerActivityLifecycleCallbacks(new MyLifecycleHandler());

    music = MediaPlayer.create(this, R.raw.some_music);
}

/**
 * All activities created in our application will call these methods on their respective
 * lifecycle methods.
 */
class MyLifecycleHandler implements ActivityLifecycleCallbacks {

    private int resumed;
    private int stopped;

    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    }

    public void onActivityDestroyed(Activity activity) {
    }

    public void onActivityResumed(Activity activity) {
        // this is the first activity created
        if(resumed == 0) {
            music.start();
        }
        ++resumed;
    }

    public void onActivityPaused(Activity activity) {
    }

    public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
    }

    public void onActivityStarted(Activity activity) {
    }

    public void onActivityStopped(Activity activity) {
        ++stopped;
        android.util.Log.w("test", "application is being backgrounded: " + (resumed == stopped));
        // we are stopping the last visible activity
        if(resumed == stopped) {
            music.stop();
        }
    }
  }
}

在清单中注册:

<application
    android:name=".PlayMusicApp"

你不想在UI线程中播放音乐。最好创建一个服务来在后台线程中播放音乐,而不是在应用程序对象中管理媒体播放器。


0

要停止歌曲,您可以在Destroy上执行music.stop()。这意味着当您的应用程序关闭或被终止时,音乐会停止。

@Override
protected void onDestroy() {
    music.stop();
    super.onDestroy();
}

0
我是通过以下方式完成的:

初始化

    MediaPlayer player;
    Music music;

在OnCreate中

    music = new Music();
    music.execute("abc");

当你想要停止音乐时,通常在onDestroy方法中实现

        music.cancel(true);
        if(player.isPlaying()){
        player.stop();
        player.release();
        }

创建音乐类
  public class Music extends AsyncTask<String, Integer, Void>
{

    @Override
    protected Void doInBackground(String... params) {

        if(running)
        {
        player = MediaPlayer.create(getApplicationContext(), R.raw.bg_music1); 
        player.setVolume(100,100); 
        player.setLooping(true); 
        player.start(); 
        }
        else
        {
            player.stop();
            player.release();
        }
        return null;
    }

    @Override
    protected void onCancelled() {
        // TODO Auto-generated method stub
        super.onCancelled();
        running = false;
    }
}

另一种方法是使用服务


0

每当您离开应用程序时,只需调用music.stop()即可。如果您的应用程序仅包含一个活动,则可以在启动器活动的onStop()方法中执行此操作。

我建议您使用SoundPool来有效地播放声音。使用它,您可以播放许多并发声音。我还制作了一个SoundPool的演示项目。您可以在这里找到它

当您使用MediaPlayer对象时,您将不得不自己管理所有事情。我在我的第一个游戏中也使用了它。但是现在对于我的新游戏,我正在使用SoundPool。它在API 1中添加,仍然很流行。


我的应用程序不仅包含一个活动,也没有许多声音同时播放。只有一首背景音乐贯穿整个应用程序,其中包括三个不同的活动! - Shahbaz Pothiawala
好的,当您离开应用程序时,请停止它。 - Jatin Malwal

0

看看ActivityLifecycleCallbacks并追踪活动的开始和停止,以了解何时您的应用程序处于“停止”状态。这将在调用onActivityStopped时发生,并且在短时间内没有跟随调用onActivityStarted。


-1

非常简单,当您想要关闭MediaPlayer音量时,请尝试使用setVolume(int leftVolume,int RightVolume)进行设置。

因此,每当您想要停止MediaPlayer的音量时,请使用

music.setVolume(0,0);

你甚至可以使用 music.pause(); 暂停或停止你的 MediaPlayer。

并且使用 music.stop(); 停止 MediaPlayer。


-1
最简单的解决方案是进入您的Android设置>应用程序>(您的音乐播放器的名称),然后点击“强制停止”。确认操作,音乐应该停止。它可能无法与所有音乐播放器一起使用,但值得一试。
如果您必须有代码,您是否尝试过分配music.pause()?此命令将停止音乐。

为什么回答中有问题? - Enamul Hassan
我并不是在质疑,只是在提出一个解决方案。如果这个方案看起来太像质疑了,我可以按要求重新表述。 - user5487924

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接