在 Android 中跨活动播放 BG 音乐

发布于 08-18 02:30 字数 312 浏览 15 评论 0原文

你好!第一次在 stackoverflow 上提问。令人兴奋!哈哈。

我们正在开发一个 Android 游戏,我们为我们的介绍播放一些背景音乐(我们有一个介绍活动),但我们希望它继续播放到下一个活动,并且也许能够停止或播放从应用程序内的任何位置再次播放音乐。

我们目前正在做的是在 Intro Activity 中使用 MediaPlayer 播放 bgm。但是,一旦用户离开该 Activity,我们就会停止播放音乐。我们必须使用类似服务之类的东西吗?或者 MediaPlayer/SoundPool 就足够了?如果有人知道答案,我们很乐意与我们分享。谢谢!

Hello! First time to ask a question here at stackoverflow. Exciting! Haha.

We're developing an Android game and we play some background music for our intro (we have an Intro Activity) but we want it to continue playing to the next Activity, and perhaps be able to stop or play the music again from anywhere within the application.

What we're doing at the moment is play the bgm using MediaPlayer at our Intro Activity. However, we stop the music as soon as the user leaves that Activity. Do we have to use something like Services for this? Or is MediaPlayer/SoundPool enough? If anyone knows the answer, we'd gladly appreciate your sharing it with us. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

无名指的心愿2024-08-25 02:30:15

您还可以创建一个使用媒体播放器播放音乐的服务,如下所示。

Intent svc=new Intent(this, BackgroundSoundService.class);
startService(svc); //OR stopService(svc); 

public class BackgroundSoundService extends Service {
    private static final String TAG = null;
    MediaPlayer player;
    public IBinder onBind(Intent arg0) {

        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();


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

    }
    public int onStartCommand(Intent intent, int flags, int startId) {


        player.start();

        return 1;
    }

    public void onStart(Intent intent, int startId) {
        // TODO



    }
    public IBinder onUnBind(Intent arg0) {
        // TODO Auto-generated method stub

        return null;
    }

    public void onStop() {

    }
    public void onPause() {

    }
    @Override
    public void onDestroy() {

        player.stop();
        player.release();
    }

    @Override
    public void onLowMemory() {

    }
}

You can also create a service which play music using mediaplayer as below.

Intent svc=new Intent(this, BackgroundSoundService.class);
startService(svc); //OR stopService(svc); 

public class BackgroundSoundService extends Service {
    private static final String TAG = null;
    MediaPlayer player;
    public IBinder onBind(Intent arg0) {

        return null;
    }
    @Override
    public void onCreate() {
        super.onCreate();


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

    }
    public int onStartCommand(Intent intent, int flags, int startId) {


        player.start();

        return 1;
    }

    public void onStart(Intent intent, int startId) {
        // TODO



    }
    public IBinder onUnBind(Intent arg0) {
        // TODO Auto-generated method stub

        return null;
    }

    public void onStop() {

    }
    public void onPause() {

    }
    @Override
    public void onDestroy() {

        player.stop();
        player.release();
    }

    @Override
    public void onLowMemory() {

    }
}
随波逐流2024-08-25 02:30:15

使用 SoundPools 或 MediaPlayers 创建静态 SoundManager。

创建一个名为 keepMusicGoing 的静态标志。

创建第一个活动时开始播放音乐。

切换活动时,将 keepMusicGoing 设置为 true。

在活动的 onStop 事件中检查 keepMusicGoing 是否为 true,如果是,则保持音乐打开,然后将 keepMusicGoing 设置为 false。

如果他们按下主页按钮,则 keepMusicGoing 标志将为 false,因此当活动失去焦点时音乐将停止。

给我发电子邮件,我可以向您发送我编写的几个 SoundManager,其中一个使用 MediaPlayers,另一个使用 SoundPools

Chad

Create a static SoundManager using either SoundPools or MediaPlayers.

Create a static flag called keepMusicGoing.

Start the music when the first activty is created.

When switching actvities set keepMusicGoing to true.

On the onStop event of your activities check if keepMusicGoing is true,if so leave the music on, then set keepMusicGoing to false.

If they press the home button the keepMusicGoing flag will be false so the music will stop when the activity loses focus.

Email me and I can send you a couple SoundManagers that I wrote one uses MediaPlayers and the other SoundPools

Chad

酒几许2024-08-25 02:30:15

如果我正确理解你的情况,那么我已经遇到过几次同样的问题了。我正在使用不同的线程在我的应用程序中播放音乐。此实现传递了对上下文的静态引用,我知道该上下文在播放音乐时将处于活动状态。

public class AudioPlayer extends Thread {
private Context c;
private Thread blinker;
private File file;

public AudioPlayer (Context c, File file) {
    this.c = c;
    this.file = file;
}

public void go () {
    blinker = this;
    if(!blinker.isAlive()) {
        blinker.start();
    }
}

public void end () {
    Thread waiter = blinker;
    blinker = null;
    if (waiter != null)
        waiter.interrupt ();
}

public void run () {
    MediaPlayer ap = MediaPlayer.create(c, Uri.fromFile(file));
    int duration = ap.getDuration();
    long startTime = System.currentTimeMillis();
    ap.start();
    try {
        Thread thisThread = Thread.currentThread();
        while (this.blinker == thisThread && System.currentTimeMillis() - startTime < duration) {           
            Thread.sleep (500);  // interval between checks (in ms)
        }
        ap.stop ();
        ap.release ();
        ap = null;
    } catch (InterruptedException e) {
        Log.d("AUDIO-PLAYER", "INTERRUPTED EXCEPTION");
        ap.stop ();
        ap.release();
        ap = null;
    }
    }
}

If I understand your situation correctly, then I have confronted the same problem a few times. I am using a different thread to play music in my applications. This implementation passes a static reference to a Context that I know will be alive for the time that the music will be playing.

public class AudioPlayer extends Thread {
private Context c;
private Thread blinker;
private File file;

public AudioPlayer (Context c, File file) {
    this.c = c;
    this.file = file;
}

public void go () {
    blinker = this;
    if(!blinker.isAlive()) {
        blinker.start();
    }
}

public void end () {
    Thread waiter = blinker;
    blinker = null;
    if (waiter != null)
        waiter.interrupt ();
}

public void run () {
    MediaPlayer ap = MediaPlayer.create(c, Uri.fromFile(file));
    int duration = ap.getDuration();
    long startTime = System.currentTimeMillis();
    ap.start();
    try {
        Thread thisThread = Thread.currentThread();
        while (this.blinker == thisThread && System.currentTimeMillis() - startTime < duration) {           
            Thread.sleep (500);  // interval between checks (in ms)
        }
        ap.stop ();
        ap.release ();
        ap = null;
    } catch (InterruptedException e) {
        Log.d("AUDIO-PLAYER", "INTERRUPTED EXCEPTION");
        ap.stop ();
        ap.release();
        ap = null;
    }
    }
}
ゝ杯具2024-08-25 02:30:15

首先,我使用了 Chad 提供的保留“keepMusicPlaying”标志的方法。我认为仅使用活动的 onStart 和 onStop 方法更优雅。

创建一个自己的类“SoundManager”,并从所有活动 onStart 和 onStop 中调用其中的一些 onStart 和 onStop 类(或使用基活动类)。使用 startCounter 跟踪 onStart 和 onStop(startCounter++ in onstart 和 startCounter-- in onstop)。因为新活动的开始是在旧活动的 onStop 之前调用的,所以您始终知道 onStart 是第一次调用(startCounter == 1)还是从另一个活动开始(startCounter == 2)。与 onStope 相同(startCounter == 0 表示应用程序已关闭,startCounter == 1 表示它只是旧活动的停止,但有一个新活动)。

通过这种方式,您可以将所有内容封装到 SoundManager 中,而不必在应用程序内启动的每个活动上调用一些 keepMusicPlaying 方法/标志。

    public void OnStart()
    {
        startCounter++;
        if (startCounter == 1)
        {
            //start music here
        }

    public void OnStop()
    {
        startCounter--;
        if (startCounter == 0)
        {
            // stop music here
        }
    }

First i used the method where to keep a "keepMusicPlaying" flag provided by Chad. I think its more elegant to just use the onStart and onStop methods of your activitys.

Create an own class "SoundManager" and call some onStart and onStop classes in it from all your activitys onStart and onStop (or use a base activity class). Keep track of the onStart and onStop with a startCounter(startCounter++ in onstart and startCounter-- in onstop). Because the start of a new activity is called before the onStop of the old activity you always know if the onStart is called for the first Time (startCounter == 1) or started from another of your activitys (startCounter == 2). Same with the onStope(startCounter == 0 means the App was closed, startCounter == 1 means its just the stop from an old activity but there is a new).

This way you encapsulate everything into your SoundManager instead of having to call some keepMusicPlaying method/flag on every activity start inside your app.

    public void OnStart()
    {
        startCounter++;
        if (startCounter == 1)
        {
            //start music here
        }

    public void OnStop()
    {
        startCounter--;
        if (startCounter == 0)
        {
            // stop music here
        }
    }
娇纵2024-08-25 02:30:15

您可以尝试使用 AsyncPlayer 但您应该保留对类以停止播放声音。

您可以使用 Uri uri = Uri.parse("android.resource://com.stackoverlof.android/raw/
beep.mp3");

希望这会有所帮助。

You can try using the AsyncPlayer but you should keep a reference to the class in order to stop the sound from playing.

You can create a Uri to a local resource using Uri uri = Uri.parse("android.resource://com.stackoverlof.android/raw/
beep.mp3");
.

Hope this helps.

九命猫2024-08-25 02:30:15

通过结合 Chad 和 Kedu 的答案并添加我自己的风格,我创建了这个可行的解决方案:

// Parent Activity which every Activity extends
public class ParentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Music.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Music.onStop();
    }
}
// Controller class for handling background music
public abstract class Music {

    private static MediaPlayer mediaPlayer;
    private static int startCounter = 0;

    public static void onStart() {
        startCounter++;
        if (startCounter == 1) {
            mediaPlayer = MediaPlayer.create(InitializeActivity.getContext(), R.raw.background_music);
            mediaPlayer.setLooping(true);
            mediaPlayer.setVolume(1f, 1f);
            mediaPlayer.start();
        }
    }

    public static void onStop() {
        startCounter--;
        if (startCounter == 0) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }
}

就是这样,超级简单!

By combining Chad's and Kedu's answers and adding my own flavor, I created this working solution:

// Parent Activity which every Activity extends
public class ParentActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onStart() {
        super.onStart();
        Music.onStart();
    }

    @Override
    protected void onStop() {
        super.onStop();
        Music.onStop();
    }
}
// Controller class for handling background music
public abstract class Music {

    private static MediaPlayer mediaPlayer;
    private static int startCounter = 0;

    public static void onStart() {
        startCounter++;
        if (startCounter == 1) {
            mediaPlayer = MediaPlayer.create(InitializeActivity.getContext(), R.raw.background_music);
            mediaPlayer.setLooping(true);
            mediaPlayer.setVolume(1f, 1f);
            mediaPlayer.start();
        }
    }

    public static void onStop() {
        startCounter--;
        if (startCounter == 0) {
            mediaPlayer.stop();
            mediaPlayer.release();
        }
    }
}

And that's it, super simple!

新人笑2024-08-25 02:30:15

创建一个带有一个静态 MediaPlayer 的类
所以每次调用它时实例都是相同的(因为它是静态的)

create a class with one static MediaPlayer
so the instance will be the same every time you call it ( because it is static)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文