当应用进入后台时停止 MediaPlayer 服务
Stop MediaPlayer service when app goes in Background
我有一个媒体播放器服务,可以在我的应用程序后台播放音乐,例如:
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();
}
问题是,当用户更改应用程序或转到 phone 的主屏幕(应用程序进入后台)时,音乐仍在播放。
我试图用 onStop
和 onDestroy
方法停止它,但是当我改变活动时这会停止音乐,这是我不想要的(我希望音乐继续播放当用户浏览活动时)。
更新
我试过广播:
我加了
LocalBroadcastManager.getInstance(this).registerReceiver(StateReceiver, new IntentFilter("status"));
在音乐服务的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();}
}
};
在应用程序中 class 我这样做了:
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) {
}
但是音乐不会恢复
你实现了onDestroy()了吗?如果没有,我相信这可能是解决方案 - 你停止播放器或任何你正在使用的 运行 onDestroy() 中的服务。
A service can be stopped by calling its stopSelf() method, or by
calling Context.stopService().
您可以将此添加到您的应用程序中 class 以检查您的应用程序是否在前台。
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;
}
}
像这样将其添加到您的应用程序中:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
}
}
在服务中收到广播后,您可以停止媒体播放器。
编辑
您需要将应用程序 class 更改为:
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) {
}
}
播放器停止后需要重新准备。如果您想在您的应用程序进入后台时停止播放,并在您的应用程序进入前台时从头开始播放媒体。只需将您的 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();
}
}
};
但是,如果您想暂停播放并从您离开的地方继续播放,请进行以下更改:
在您的应用程序 class 中,在 onActivityDestroyed():
@Override
public void onActivityDestroyed(Activity activity) {
send_status(2);
}
并在 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();
}
}
};
此外,请查看 MediaPlayer states。
除了像RoyalGriffin回答的那样使用broadcast receiver之外,音乐中断很少的问题可以通过实现LifecycleObserver
接口来解决。您可以知道应用程序何时处于前台或后台,这样就不需要处理每个 activity.
的状态
使用他的方法在您的应用中实现 Application.ActivityLifecycleCallbacks
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
和 @OnLifecycleEvent(Lifecycle.Event.ON_START)
然后将此行添加到 onCreate()
ProcessLifecycleOwner.get().getLifecycle().addObserver(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) {
}
}
可以使用 LifecycleObserver 减少样板文件:
class App : Application(), LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppInBackground() {
sendStatus(0)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppInForeground() {
sendStatus(1)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onAppDestroyed() {
sendStatus(2)
}
private fun sendStatus(statusCounter: Int) {
val intent = Intent("status")
intent.putExtra("status", statusCounter)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
}
添加到 build.gradle(应用程序)
implementation "androidx.lifecycle:lifecycle-runtime:2.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.1.0"
我有一个媒体播放器服务,可以在我的应用程序后台播放音乐,例如:
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();
}
问题是,当用户更改应用程序或转到 phone 的主屏幕(应用程序进入后台)时,音乐仍在播放。
我试图用 onStop
和 onDestroy
方法停止它,但是当我改变活动时这会停止音乐,这是我不想要的(我希望音乐继续播放当用户浏览活动时)。
更新
我试过广播:
我加了
LocalBroadcastManager.getInstance(this).registerReceiver(StateReceiver, new IntentFilter("status"));
在音乐服务的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();}
}
};
在应用程序中 class 我这样做了:
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) {
}
但是音乐不会恢复
你实现了onDestroy()了吗?如果没有,我相信这可能是解决方案 - 你停止播放器或任何你正在使用的 运行 onDestroy() 中的服务。
A service can be stopped by calling its stopSelf() method, or by calling Context.stopService().
您可以将此添加到您的应用程序中 class 以检查您的应用程序是否在前台。
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;
}
}
像这样将其添加到您的应用程序中:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
registerActivityLifecycleCallbacks(new MyLifecycleHandler());
}
}
在服务中收到广播后,您可以停止媒体播放器。
编辑
您需要将应用程序 class 更改为:
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) {
}
}
播放器停止后需要重新准备。如果您想在您的应用程序进入后台时停止播放,并在您的应用程序进入前台时从头开始播放媒体。只需将您的 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();
}
}
};
但是,如果您想暂停播放并从您离开的地方继续播放,请进行以下更改: 在您的应用程序 class 中,在 onActivityDestroyed():
@Override
public void onActivityDestroyed(Activity activity) {
send_status(2);
}
并在 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();
}
}
};
此外,请查看 MediaPlayer states。
除了像RoyalGriffin回答的那样使用broadcast receiver之外,音乐中断很少的问题可以通过实现LifecycleObserver
接口来解决。您可以知道应用程序何时处于前台或后台,这样就不需要处理每个 activity.
使用他的方法在您的应用中实现 Application.ActivityLifecycleCallbacks
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
和 @OnLifecycleEvent(Lifecycle.Event.ON_START)
然后将此行添加到 onCreate()
ProcessLifecycleOwner.get().getLifecycle().addObserver(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) {
}
}
可以使用 LifecycleObserver 减少样板文件:
class App : Application(), LifecycleObserver {
@OnLifecycleEvent(Lifecycle.Event.ON_STOP)
fun onAppInBackground() {
sendStatus(0)
}
@OnLifecycleEvent(Lifecycle.Event.ON_START)
fun onAppInForeground() {
sendStatus(1)
}
@OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
fun onAppDestroyed() {
sendStatus(2)
}
private fun sendStatus(statusCounter: Int) {
val intent = Intent("status")
intent.putExtra("status", statusCounter)
LocalBroadcastManager.getInstance(this).sendBroadcast(intent)
}
override fun onCreate() {
super.onCreate()
ProcessLifecycleOwner.get().lifecycle.addObserver(this)
}
}
添加到 build.gradle(应用程序)
implementation "androidx.lifecycle:lifecycle-runtime:2.1.0"
implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.1.0"