【问题标题】:Stop MediaPlayer service when app goes in Background当应用程序进入后台时停止 MediaPlayer 服务
【发布时间】:2018-06-13 13:03:10
【问题描述】:

我有一个媒体播放器服务,可以在我的应用程序的后台播放音乐,例如:

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();
}

问题是当用户更改应用程序或进入手机主屏幕(应用程序进入后台)时,音乐仍在播放。

我试图在 onStoponDestroy 方法中停止它,但是当我更改我不想要的活动时,这会停止音乐(我希望在用户浏览活动时继续播放音乐) .

更新

我尝试过广播:

我加了

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();}

    }
};

在应用程序类中我这样做了:

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) {

}   

但音乐不会继续播放

【问题讨论】:

    标签: java android service android-mediaplayer


    【解决方案1】:

    您需要在停止播放器后再次对其进行准备。如果您想在您的应用程序进入后台时停止播放,并在您的应用程序进入前台时从头开始播放媒体。只需将您的 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();
                }
    
            }
        };
    

    但是,如果您想暂停播放并从您离开的地方继续播放,请进行以下更改: 在您的 Application 类中,在 onActivityDestroyed() 中:

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

    在广播接收器中:

    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

    【讨论】:

    • 它只适用于一个不太重要的问题,但如果您知道任何修复方法,我们将不胜感激。当我浏览活动时,音乐会立即暂停和恢复,导致音乐瞬间失真。无论如何,我将标记为已纠正,因为我已经尝试找到一个星期的解决方案......所以非常感谢你
    【解决方案2】:

    您可以在您的应用程序类中添加它来检查您的应用程序是否在前台。

    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());
        }
    }
    

    在服务中接收到广播后,您可以停止媒体播放器。

    编辑

    您需要将您的应用程序类更改为:

    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) {
    
        }
    }
    

    【讨论】:

    • 您能否再解释一下“在接收服务中的广播时,您可以停止媒体播放器。”
    • 您可以从 MyLifecycleHandler 发送广播并在您的服务类中接收其广播。你可以在这里看到这个实现:stackoverflow.com/a/8875292/7384780
    • 我想不通。它不会工作(音乐不会停止),但应用程序不会崩溃。
    • 您需要在应用程序的 oncreate 中通过registerActivityLifecycleCallbacks(this) 注册ActivityLifecycleCallbacks。您是否能够在服务中接收广播?
    【解决方案3】:

    你实现了 onDestroy() 吗?如果没有,我相信这可能是解决方案 - 你停止你的 Player 或任何你用来在 onDestroy() 中运行服务的东西。

    可以通过调用它的 stopSelf() 方法来停止服务,或者通过 调用 Context.stopService()。

    【讨论】:

      【解决方案4】:

      除了使用RoyalGriffin回答的广播接收器外,通过实现LifecycleObserver接口可以解决音乐中断少的问题。您可以知道应用程序处于前台还是后台,这样就无需处理每个活动的状态。

      用他的方法在你的应用中实现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) {
      
          }
      }
      

      【讨论】:

        【解决方案5】:

        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 (app)

        implementation "androidx.lifecycle:lifecycle-runtime:2.1.0"
        implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"
        annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.1.0"
        

        【讨论】:

          猜你喜欢
          • 2014-12-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多