在多个activites Android的COM prehensive failproof音乐服务多个、音乐、activites、COM

2023-09-04 08:59:43 作者:微笑、不失礼

我知道这个问题已经被问过很多次,似乎成为若干问题的堆集,但我觉得这是相关的,重要的是许多开发商;我需要创建一个背景音乐服务可以在多个活动上运行我的Andr​​oid游戏结束时,应用程序被终止,并暂停所有的下列情况:

在某活动,有它自己的音乐开始。 (继续当此活动结束,这恰好是一个 AndEngine 的活动。) 在主屏幕是pssed $ P $和应用程序的中背景,或者应用程序被终止。恢复时,应用程序返回到前台。需要使用onUserLeaveHint(). Another有用的链接。 在手机接收呼叫并中断应用程序。恢复时呼叫已被处理。需要使用 TelephonyManager 类似于this. 在屏幕被锁定。 (简历屏幕已解除锁定后)需要使用ACTION_USER_$p$pSENT,这似乎be very problematic. 基本上每当该应用不被示出或当从#1的特殊活动正在显示给用户的音乐的暂停。

以上是我所需要的所有的信息,我已拼凑起来的。 我现在的code基本上类似于this.

我觉得奇怪的是 AndEngine 管理​​有没有这些问题,他们的音乐,也许看在源$ C ​​$ C会帮助别人寻找一个答案。我使用从谷歌code 中的最后一个功能GLES1版本。

我已经创造一个良好的音乐服务采取一起来看看下面的链接,以及

停止后台服务音乐 http://www.$c$cproject.com/Articles/258176/Adding-Background-Music-to-Android-App Android的背景音乐服务 Playing BG音乐在整个活动中的Andr​​oid http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion

我想解服务来:

尽量少用 BroadcastReceivers 和Android清单添加/权限,如果可能的话 包含和错误检查自

其他注意事项

在目前所有需要背景音乐的所有活动扩展一个共同的特殊的类。 在音乐需要循环,但只运行一个单一的轨道。

感谢大家的时间提前!祝您好运!

编辑 - 这里是code片段,随意提高或忽略:

媒体播放器包装的

 进口android.content.Shared preferences;
进口android.media.MediaPlayer;
。进口的Andr​​oid preference preferenceManager。
进口android.util.Log;

公共类CarefulMediaPlayer {
    最终的共享preferences SP;
    最后MediaPlayer的熔点;
    私人布尔IsPlaying模块= FALSE;

    公共CarefulMediaPlayer(最终MediaPlayer的熔点,最终MusicService毫秒){
        SP = preferenceManager.getDefaultShared preferences(ms.getApplicationContext());
        this.mp = MP;
    }

    公共无效启动(){
        如果(sp.getBoolean(com.embed.candy.music,真)及&安培;!IsPlaying模块){
            mp.start();
            IsPlaying模块= TRUE;
        }
    }

    公共无效暂停(){
        如果(IsPlaying模块){
            mp.pause();
            IsPlaying模块= FALSE;
        }
    }

    公共无效停止(){
        IsPlaying模块= FALSE;
        尝试 {
            mp.stop();
            mp.release();
        }赶上(最终例外五){}
    }
}
 

音乐服务的

 进口android.app.Service;
进口android.content.Intent;
进口android.media.MediaPlayer;
进口android.os.IBinder;

公共类MusicService延伸服务{
    静态CarefulMediaPlayer MPLAYER = NULL;

    @覆盖
    公众的IBinder onBind(最终意图为arg0){
        返回null;
    }

    @覆盖
    公共无效的onCreate(){
        super.onCreate();
        最后的MediaPlayer MP = MediaPlayer.create(这一点,R.raw.title_music);
        mp.setLooping(真正的);
        MPLAYER =新CarefulMediaPlayer(MP,这一点);
    }

    @覆盖
    公众诠释onStartCommand(最终意图的意图,最终诠释标志,最终诠释startId){
        mPlayer.start();
        返回1;
    }

    @覆盖
    公共无效ONSTART(最终意图的意图,最终诠释startId){

    }

    公众的IBinder onUnBind(最终意图为arg0){
        返回null;
    }

    公共静态无效的onStop(){
        mPlayer.stop();
    }

    公共静态无效的onPause(){
        如果(MPLAYER!= NULL){
            mPlayer.pause();
        }
    }

    公共静态无效onResume(){
        如果(MPLAYER!= NULL){
            mPlayer.start();
        }
    }

    @覆盖
    公共无效的onDestroy(){
        mPlayer.stop();
        MPLAYER = NULL;
    }

    @覆盖
    公共无效onLowMemory(){

    }
}
 

改进基本活动类的

 进口android.app.Activity;
进口android.content.Intent;
进口android.os.PowerManager;
进口android.telephony.TelephonyManager;
进口android.view.KeyEvent;
进口android.view.LayoutInflater;
进口android.view.View;
进口android.view.ViewGroup;
进口android.view.ViewGroup.LayoutParams;
进口android.widget.ImageView;

公共抽象类BetterActivity延伸活动{

    私人布尔isHome = TRUE;

    @覆盖
    保护无效onResume(){
        System.gc()的;
        super.onResume();
        MusicService.onResume();
        isHome = TRUE;
    }

    @覆盖
    保护无效的onPause(){
        如果(((TelephonyManager)getSystemService(TELEPHONY_SERVICE)).getCallState()==TelephonyManager.CALL_STATE_RINGING
                || !((电源管理器)getSystemService(POWER_SERVICE))。isScreenOn()){
            MusicService.onPause();
        }
        super.onPause();
        System.gc()的;
    }

    @覆盖
    公共布尔的onkeydown(最终诠释键code,最终的KeyEvent科){
        开关(钥匙code){
        案例KeyEvent.KEY code_BACK:
            isHome = FALSE;
        默认:
            返回super.onKeyDown(键code,克);
        }
    }

    @覆盖
    公共无效startActivity(最终意图我){
        isHome = FALSE;
        super.startActivity(ⅰ);
    }

    @覆盖
    保护无效onUserLeaveHint(){
        如果(isHome){
            MusicService.onPause();
        }
        super.onUserLeaveHint();
    }

}
 
Android behaviour pre Android 10

解决方案

首先这里是一些code。下面我给大家一个交代。

 公共类MusicService延伸服务{

    //服务粘结剂
    私人最终的IBinder mBinder =新LocalBinder();

    //音乐播放器controling游戏音乐
    私有静态CarefulMediaPlayer MPLAYER = NULL;

    @覆盖
    公共无效的onCreate(){
        //下载音乐文件并创建播放器
        的MediaPlayer媒体播放器= MediaPlayer.create(这一点,R.raw.title_music);
        mediaPlayer.setLooping(真正的);
        MPLAYER =新CarefulMediaPlayer(媒体播放器,这一点);
    }

    @覆盖
    公共无效的onDestroy(){
        super.onDestroy();
    }

    // =========================
    //播放器方法
    // =========================
    公共无效musicStart(){
        mPlayer.start();
    }

    公共无效musicStop(){
        mPlayer.stop();
    }

    公共无效musicPause(){
        mPlayer.pause();
    }

    / **
     *为客户访问类。因为我们知道这种服务始终运行在
     *相同的过程,它的客户,我们不需要处理IPC。
     * /
    公共类LocalBinder扩展粘合剂{
        MusicService的getService(){
            返回MusicService.this;
        }
    }

    @覆盖
    公众的IBinder onBind(意向为arg0){
        返回mBinder;
    }

}
 

活动:

 公共类StartupActivity延伸活动{

//界服务
私有静态MusicService mBoundService;

// whetere服务界与否
私人布尔mIsBound;

@覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    的setContentView(R.layout.activity_startup);
    doBindService();

    //如何处理该服务:
    //调用以下方法时
    //要与你互动
    // 音乐播放器
    // ===================================

    //调用这个例如在的onPause(),您的活动
    。StartupActivity.getService()musicPause();

    //调用这个例如中的onStop(),您的活动
    StartupActivity.getService()musicStop()。

    //调用这个例如在onResume(),您的活动
    。StartupActivity.getService()musicStart();
}

@覆盖
公共无效的onDestroy(){
    super.onDestroy();
    doUnbindService();
}

私人最终ServiceConnection mServiceConnection =新ServiceConnection(){

    @覆盖
    公共无效onServiceConnected(组件名的className,服务的IBinder){
        setService(((MusicService.LocalBinder)服务).getService());
    }

    @覆盖
    公共无效onServiceDisconnected(组件名的className){
        setService(空);
    }
};

私人无效doBindService(){
    意向书的服务=新的意图(getBaseContext(),MusicService.class);
    //启动服务,并绑定它
    startService(服务);
    bindService(新意图(这一点,MusicService.class),mServiceConnection,Context.BIND_AUTO_CREATE);
    mIsBound = TRUE;
}

私人无效doUnbindService(){
    如果(mIsBound){
        //取下现有的连接。
        unbindService(mServiceConnection);
        mIsBound = FALSE;
    }
}

公共静态MusicService的getService(){
    返回mBoundService;
}

私有静态无效setService(MusicService mBoundService){
    StartupActivity.mBoundService = mBoundService;
}
}
 

首先你得到它运行在后台的服务。为你做这项服务将创建MediaPlayer对象。随着localBinder您可以在活动(IES)和访问它像一个正常的Java对象绑定的服务。 该活动我已经张贴bindes服务。在它的onCreate()方法,你可以找到一种方法,如何与你的媒体播放器进行交互。 您可以将任何活动绑定到你的服务。

另一种解决方案:

 公共类CarefulMediaPlayer {
最终的共享preferences SP;
最后MediaPlayer的熔点;
私人布尔IsPlaying模块= FALSE;
私有静态CarefulMediaPlayer实例;

公共CarefulMediaPlayer(最终MediaPlayer的熔点,最终MusicService毫秒){
    SP = preferenceManager.getDefaultShared preferences(ms.getApplicationContext());
    this.mp = MP;
    例如=这一点;
}

公共静态CarefulMediaPlayer的getInstance(){
    返回实例;
}

公共无效启动(){
    如果(sp.getBoolean(com.embed.candy.music,真)及&安培;!IsPlaying模块){
        mp.start();
        IsPlaying模块= TRUE;
    }
}

公共无效暂停(){
    如果(IsPlaying模块){
        mp.pause();
        IsPlaying模块= FALSE;
    }
}

公共无效停止(){
    IsPlaying模块= FALSE;
    尝试 {
        mp.stop();
        mp.release();
    }赶上(最终例外五){}
}
}
 

然后你可以暂停,播放,并通过调用CarefulMediaPlayer.getInstance()停止音乐播放();

I know this question has been asked many times before and might seem to be a conglomeration of several questions, but I feel that it is relevant and important to many developers; I need to create a background music Service that can run across multiple activities for my Android game that ends when the application is terminated and pauses in all of the following circumstances:

A certain Activity that has its own music is started. (Resume when this Activity finishes. This happens to be an AndEngine activity.) The home screen is pressed and the app is backgrounded, or the application is terminated. Resumes when the app returns to the foreground. Requires use of onUserLeaveHint(). Another helpful link. The phone receives a call and interrupts the app. Resumes when the call has been dealt with. Requires use of TelephonyManager similar to this. The screen is locked. (Resumes after screen has been unlocked.) Requires use of ACTION_USER_PRESENT, which seems to be very problematic. Basically the music pauses whenever the app is not being shown or when the special activity from #1 is being shown to the user.

Above is all of what I need and the information I have pieced together. My current code basically resembles this.

I find it curious that AndEngine manages to have none of these issues with their music, so maybe looking in the source code would help someone looking for an answer. I'm using the last functional GLES1 version from Google Code.

I have taken a look at the following links as well on creating a good music Service:

Stopping Background Service Music http://www.codeproject.com/Articles/258176/Adding-Background-Music-to-Android-App Android background music service Playing BG Music Across Activities in Android http://www.rbgrn.net/content/307-light-racer-20-days-61-64-completion

I would like the solution Service to:

Minimize the use of BroadcastReceivers and Android Manifest additions/permissions if possible Self contained and error checking

Other Notes

Currently all the activities that require the background music all extend a common special class. The music needs to loop but only runs a single track.

Thanks to everyone ahead of time! Best of luck!

Edit - Here are code snippets, feel free to improve or ignore:

Media Player Wrapper

import android.content.SharedPreferences;
import android.media.MediaPlayer;
import android.preference.PreferenceManager;
import android.util.Log;

public class CarefulMediaPlayer {
    final SharedPreferences sp;
    final MediaPlayer mp;
    private boolean isPlaying = false;

    public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
        sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
        this.mp = mp;
    }

    public void start() {
        if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) {
            mp.start();
            isPlaying = true;
        }
    }

    public void pause() {
        if (isPlaying) {
            mp.pause();
            isPlaying = false;
        }
    }

    public void stop() {
        isPlaying = false;
        try {
            mp.stop();
            mp.release();
        } catch (final Exception e) {}
    }
}

Music Service

import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.os.IBinder;

public class MusicService extends Service {
    static CarefulMediaPlayer mPlayer = null;

    @Override
    public IBinder onBind(final Intent arg0) {
        return null;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        final MediaPlayer mp = MediaPlayer.create(this, R.raw.title_music);
        mp.setLooping(true);
        mPlayer = new CarefulMediaPlayer(mp,this);
    }

    @Override
    public int onStartCommand(final Intent intent, final int flags, final int startId) {
        mPlayer.start();
        return 1;
    }

    @Override
    public void onStart(final Intent intent, final int startId) {

    }

    public IBinder onUnBind(final Intent arg0) {
        return null;
    }

    public static void onStop() {
        mPlayer.stop();
    }

    public static void onPause() {
        if (mPlayer!=null) {
            mPlayer.pause();
        }
    }

    public static void onResume() {
        if (mPlayer!=null) {
            mPlayer.start();
        }
    }

    @Override
    public void onDestroy() {
        mPlayer.stop();
        mPlayer = null;
    }

    @Override
    public void onLowMemory() {

    }
}

Improved Base Activity Class

import android.app.Activity;
import android.content.Intent;
import android.os.PowerManager;
import android.telephony.TelephonyManager;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;

public abstract class BetterActivity extends Activity {

    private boolean isHome = true;

    @Override
    protected void onResume() {
        System.gc();
        super.onResume();
        MusicService.onResume();
        isHome = true;
    }

    @Override
    protected void onPause() {
        if (((TelephonyManager)getSystemService(TELEPHONY_SERVICE)).getCallState()==TelephonyManager.CALL_STATE_RINGING
                || !((PowerManager)getSystemService(POWER_SERVICE)).isScreenOn()) {
            MusicService.onPause();
        }
        super.onPause();
        System.gc();
    }

    @Override
    public boolean onKeyDown (final int keyCode, final KeyEvent ke) {
        switch (keyCode) {
        case KeyEvent.KEYCODE_BACK:
            isHome = false;
        default:
            return super.onKeyDown(keyCode, ke);
        }
    }

    @Override
    public void startActivity(final Intent i) {
        isHome = false;
        super.startActivity(i);
    }

    @Override
    protected void onUserLeaveHint() {
        if (isHome) {
            MusicService.onPause();
        }
        super.onUserLeaveHint();
    }

}

解决方案

First here is some code. Below I'll give you an explanation.

public class MusicService extends Service {

    // service binder
    private final IBinder mBinder = new LocalBinder();

    // music player controling game music
    private static CarefulMediaPlayer mPlayer = null;

    @Override
    public void onCreate() {
        // load music file and create player
        MediaPlayer mediaPlayer = MediaPlayer.create(this, R.raw.title_music);
        mediaPlayer.setLooping(true);
        mPlayer = new CarefulMediaPlayer(mediaPlayer, this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    // =========================
    // Player methods
    // =========================
    public void musicStart() {
        mPlayer.start();
    }

    public void musicStop() {
        mPlayer.stop();
    }

    public void musicPause() {
        mPlayer.pause();
    }

    /**
     * Class for clients to access. Because we know this service always runs in
     * the same process as its clients, we don't need to deal with IPC.
     */
    public class LocalBinder extends Binder {
        MusicService getService() {
            return MusicService.this;
        }
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return mBinder;
    }

}

Activity:

public class StartupActivity extends Activity {

// bounded service
private static MusicService mBoundService;

// whetere service is bounded or not
private boolean mIsBound;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_startup);
    doBindService();

    // HOW TO WORK WITH THE SERVICE:
    // call the following methods whenever
    // you want to interact with you 
    // music player
    // ===================================

    // call this e.g. in onPause() of your Activities
    StartupActivity.getService().musicPause();

    // call this e.g. in onStop() of your Activities
    StartupActivity.getService().musicStop();

    // call this e.g. in onResume() of your Activities
    StartupActivity.getService().musicStart();
}

@Override
public void onDestroy() {
    super.onDestroy();
    doUnbindService();
}

private final ServiceConnection mServiceConnection = new ServiceConnection() {

    @Override
    public void onServiceConnected(ComponentName className, IBinder service) {
        setService(((MusicService.LocalBinder) service).getService());
    }

    @Override
    public void onServiceDisconnected(ComponentName className) {
        setService(null);
    }
};

private void doBindService() {
    Intent service = new Intent(getBaseContext(), MusicService.class);
    // start service and bound it
    startService(service);
    bindService(new Intent(this, MusicService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
    mIsBound = true;
}

private void doUnbindService() {
    if (mIsBound) {
        // Detach existing connection.
        unbindService(mServiceConnection);
        mIsBound = false;
    }
}

public static MusicService getService() {
    return mBoundService;
}

private static void setService(MusicService mBoundService) {
    StartupActivity.mBoundService = mBoundService;
}
}

First of all you got a Service which runs in background. This service creates the mediaPlayer object as you did. With the localBinder you can bind the Service in your Activity(ies) and access it like a normal Java-Object. The Activity I've posted bindes the Service. In it's onCreate() method you can find a way how to interact with your mediaPlayer. You can bind any Activity to your Service.

Another Solution:

public class CarefulMediaPlayer {
final SharedPreferences sp;
final MediaPlayer mp;
private boolean isPlaying = false;
private static CarefulMediaPlayer instance;

public CarefulMediaPlayer(final MediaPlayer mp, final MusicService ms) {
    sp = PreferenceManager.getDefaultSharedPreferences(ms.getApplicationContext());
    this.mp = mp;
    instance = this;
}

public static CarefulMediaPlayer getInstance() {
    return instance;
}

public void start() {
    if (sp.getBoolean("com.embed.candy.music", true) && !isPlaying) {
        mp.start();
        isPlaying = true;
    }
}

public void pause() {
    if (isPlaying) {
        mp.pause();
        isPlaying = false;
    }
}

public void stop() {
    isPlaying = false;
    try {
        mp.stop();
        mp.release();
    } catch (final Exception e) {}
}
}

Then you can pause, play and stop the music by calling CarefulMediaPlayer.getInstance().play();

 
精彩推荐
图片推荐