简体   繁体   English

应用程序在后台运行时停止MediaPlayer服务

[英]Stop MediaPlayer service when app goes in Background

I have a media player service that plays music in the background of my app throughout activities like : 我有一个媒体播放器服务,可在诸如以下活动的整个应用程序中播放音乐:

public class Music extends Service {
MediaPlayer player;

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

public void onCreate() {
    player = MediaPlayer.create(this, R.raw.music);
    player.setLooping(true);
}

public int onStartCommand(Intent intent, int flags, int startId) {
    player.start();
    return Service.START_NOT_STICKY;
}


public void onDestroy() {
    player.stop();
    player.release();
    stopSelf();
    super.onDestroy();
}

The problem is that when the user changes app or goes to home screen of phone(app goes in the background) the music is still playing. 问题在于,当用户更改应用程序或进入电话的主屏幕(应用程序在后台运行)时,音乐仍在播放。

I have tried to stop it in onStop and onDestroy method but this stops the music when I change activities which is something that I don't want(I want the music to keep playing when user navigates through activities). 我试图用onStoponDestroy方法停止它,但是这在我更改活动时停止了音乐,这是我不希望的(我希望音乐在用户浏览活动时继续播放)。

Update 更新资料

I tried with broadcast: 我尝试了广播:

I added 我加了

LocalBroadcastManager.getInstance(this).registerReceiver(StateReceiver, new IntentFilter("status"));

in onCreate of music Service and a method to receive events : 在音乐服务的onCreate和接收事件的方法中:

private BroadcastReceiver StateReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String status = intent.getStringExtra("status");
        if (parseInt(String.valueOf(status)) == 0) {
            player.stop();
        }else{player.start();}

    }
};

And in Application class I did this: 在应用程序类中,我这样做:

public class app_class extends Application implements Application.ActivityLifecycleCallbacks {
private static int resumed;
private static int paused;

private static String currentActivity;

@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
    currentActivity = activity.getClass().getSimpleName();
}
public static String getCurrentActivity() {
    return currentActivity;
}
@Override
public void onActivityStarted(Activity activity) {
}
 @Override
public void onActivityResumed(Activity activity) {
    send_status(1);
}

@Override
public void onActivityPaused(Activity activity) {
    send_status(0);
}  
 private void send_status(int status_counter) {
    Intent intent = new Intent("status");
    intent.putExtra("status", String.valueOf(status_counter));
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
@Override
public void onActivityStopped(Activity activity) {      

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

}
@Override
public void onActivityDestroyed(Activity activity) {

}   

But the music wont resume 但是音乐不会恢复

You need to prepare the player again after stopping it. 停止播放器后,您需要重新准备播放器。 If you want to stop the playback when your app goes in background, and start the media from the beginning when your app comes into foreground. 如果您想在应用程序进入后台时停止播放,并在应用程序进入前台时从头开始播放媒体。 Just modify your BroadcastReceiver code to this: 只需将您的BroadcastReceiver代码修改为此:

private BroadcastReceiver StateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String status = intent.getStringExtra("status");
            if (parseInt(String.valueOf(status)) == 0) {
                player.stop();
            } else {
                player = MediaPlayer.create(this, R.raw.music);
                player.setLooping(true);
                player.start();
            }

        }
    };

However, if you want to pause the playback and resume it from where you left, then make the following changes: In your Application class, in onActivityDestroyed(): 但是,如果要暂停播放并从左侧继续播放,请进行以下更改:在Application类的onActivityDestroyed()中:

@Override
public void onActivityDestroyed(Activity activity) {
    send_status(2);
}

and in the BroadcastReceiver: 并在BroadcastReceiver中:

private BroadcastReceiver StateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String status = intent.getStringExtra("status");
            if (parseInt(String.valueOf(status)) == 0) {
                player.pause();  //When app is in background and not killed, we just want to pause the player and not want to lose the current state.
            } else if (parseInt(String.valueOf(status)) == 1) {
                if (player != null)
                    player.start();  // If the player was created and wasn't stopped, it won't be null, and the playback will be resumed from where we left of.
                else {
                    // If the player was stopped, we need to prepare it once again.
                    player = MediaPlayer.create(this, R.raw.music);
                    player.setLooping(true);
                    player.start();
                }
            } else if(player != null){
                player.stop();
                player.release();
            }

        }
    };

Also, have a look at the MediaPlayer states . 另外,看看MediaPlayer的状态

You could add this in your application class to check whether your app is in the foreground or not. 您可以将其添加到应用程序类中,以检查您的应用程序是否在前台。

public class MyLifecycleHandler implements Application.ActivityLifecycleCallbacks {
    private static int resumed;
    private static int paused;
    private static int started;
    private static int stopped;

    private static String currentActivity;

    public static String getCurrentActivity() {
        return currentActivity;
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        currentActivity = activity.getClass().getSimpleName();
    }

    @Override
    public void onActivityDestroyed(Activity activity) {
    }

    @Override
    public void onActivityResumed(Activity activity) {
        ++resumed;
    }

    @Override
    public void onActivityPaused(Activity activity) {
        ++paused;
        android.util.Log.w("test", "application is in foreground: " + (resumed > paused));

        // send broadcast from here to the service
        sendBroadcast()
    }

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

    @Override
    public void onActivityStarted(Activity activity) {
        ++started;
    }

    @Override
    public void onActivityStopped(Activity activity) {
        ++stopped;
        android.util.Log.w("test", "application is visible: " + (started > stopped));
    }

    public static boolean isApplicationVisible() {
        return started > stopped;
    }

    public static boolean isApplicationInForeground() {
        return resumed > paused;
    }
}

Add this to your application like this : 像这样添加到您的应用程序:

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();

        registerActivityLifecycleCallbacks(new MyLifecycleHandler());
    }
}

On receiving the broadcast in service you can stop mediaplayer. 接收到正在播放的广播后,您可以停止mediaplayer。

Edit 编辑

You need to change your application class to this : 您需要将应用程序类更改为:

public class app_class extends Application implements Application.ActivityLifecycleCallbacks {
    private static int resumed;
    private static int paused;

    private static String currentActivity;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
        currentActivity = activity.getClass().getSimpleName();
    }
    public static String getCurrentActivity() {
        return currentActivity;
    }
    @Override
    public void onActivityStarted(Activity activity) {
    }
    @Override
    public void onActivityResumed(Activity activity) {
        send_status(1);
    }

    @Override
    public void onActivityPaused(Activity activity) {
        send_status(0);
    }
    private void send_status(int status_counter) {
        Intent intent = new Intent("status");
        intent.putExtra("status", String.valueOf(status_counter));
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
    @Override
    public void onActivityStopped(Activity activity) {

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

    }
    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}

Have you implemented onDestroy()? 您实现了onDestroy()吗? If not, I believe that might be the solution - and you stop your Player or whatever you're using to run the service within onDestroy(). 如果没有,我相信这可能是解决方案-然后您停止播放器或在onDestroy()中运行服务所用的任何方式。

A service can be stopped by calling its stopSelf() method, or by calling Context.stopService(). 可以通过调用服务的stopSelf()方法或通过调用Context.stopService()来停止服务。

Besides using the broadcast receiver as RoyalGriffin answered, the problem with the little interruption of the music can be solve by implementing LifecycleObserver interface. 除了使用RoyalGriffin回答的广播接收器之外,音乐的中断很少的问题可以通过实现LifecycleObserver接口来解决。 You can know when the app is in foreground or background, and that way, there is no need of handled the states of every activity. 您可以知道应用程序处于前台还是后台,这样就无需处理每个活动的状态。

Implement Application.ActivityLifecycleCallbacks in your app with his methods @OnLifecycleEvent(Lifecycle.Event.ON_STOP) and @OnLifecycleEvent(Lifecycle.Event.ON_START) 使用他的方法@OnLifecycleEvent(Lifecycle.Event.ON_STOP)@OnLifecycleEvent(Lifecycle.Event.ON_START)在您的应用中实现Application.ActivityLifecycleCallbacks

then add this line to the onCreate() 然后将此行添加到onCreate()

ProcessLifecycleOwner.get().getLifecycle().addObserver(this);

Your app_class would be something like this: 您的app_class将如下所示:

    public class app_class extends Application implements LifecycleObserver, 
    Application.ActivityLifecycleCallbacks{
    private static int resumed;
    private static int paused;

    private static String currentActivity;

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(this);
        ProcessLifecycleOwner.get().getLifecycle().addObserver(this);
    }

   @OnLifecycleEvent(Lifecycle.Event.ON_STOP)
    private void onAppBackgrounded() {
        Log.d(TAG, "App in background");
        send_status(0, this);
    }

    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private void onAppForegrounded() {
        Log.d(TAG, "App in foreground");
        send_status(1, this);
    }

    @Override
    public void onActivityCreated(Activity activity, Bundle 
    savedInstanceState) {
        currentActivity = activity.getClass().getSimpleName();
    }
    public static String getCurrentActivity() {
        return currentActivity;
    }
    @Override
    public void onActivityStarted(Activity activity) {
    }
    @Override
    public void onActivityResumed(Activity activity) {
        //send_status(1);
    }

    @Override
    public void onActivityPaused(Activity activity) {
        //send_status(0);
    }
    private void send_status(int status_counter) {
        Intent intent = new Intent("status");
        intent.putExtra("status", String.valueOf(status_counter));
        LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
    }
    @Override
    public void onActivityStopped(Activity activity) {

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

    }
    @Override
    public void onActivityDestroyed(Activity activity) {

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM