在后台不会被杀死的长期服务活动

caw*_*caw 12 android android-service android-lifecycle android-service-binding

在Android上,我有一个Activity被叫FirstActivity,它启动一个Service名为MyService在后台做网络的东西.ActivityService相互所有的时间通过调用方法通信.

现在,当用户从导航FirstActivitySecondActivity,后台服务应该不会被杀死或重新创建的,但维持生命,并传递给SecondActivity现在将是一个与服务进行通信.

换句话说,Service只要两个Activitys中的一个正在运行,它就应该运行,并且当用户在两个Activitys 之间导航时它不应该停止.

其中一个Activity将永远在前台,在此期间,服务应该(最佳)永远不会被杀死.我认为这应该不是问题,因为这两个中Activity的一个总是活跃的,因此Android知道服务很重要而不是必须被杀死的东西.

(如果没有办法阻止Android不时地杀死和重新创建服务,我需要一种方法来优雅地恢复服务的完整状态.)

总而言之,它Service应该具有与两个Activity"组合" 相同的寿命.它应该从它们中的第一个开始,并且在它们都被破坏之前停止.

以下代码是否适用于该设置和目标?

public class MyService extends Service {

    public class LocalBinder extends Binder {
        public MyService getService() {
            return MyService.this;
        }
    }

    ...

}

public class FirstActivity extends Activity {

    private MyService mMyService;

    private ServiceConnection mMainServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            MyService mainService = ((LocalBinder) service).getService();
            mMyService = mainService;
            mMyService.setCallback(FirstActivity.this);
        }

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

    @Override
    public void onCreate(Bundle savedInstanceState) {
        ...
        startService(new Intent(FirstActivity.this, MyService.class));
    }

    @Override
    protected void onResume() {
        super.onResume();
        bindService(new Intent(FirstActivity.this, MyService.class), mMainServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mMainServiceConnection != null) {
            unbindService(mMainServiceConnection);
        }

        if (mMyService != null) {
            mMyService.setCallback(null);
        }

        if (!isUserMovingToSecondActivity) {
            stopService(new Intent(FirstActivity.this, MyService.class));
        }
    }

    @Override
    public void onBackPressed() {
        stopService(new Intent(FirstActivity.this, MyService.class));
        super.onBackPressed();
    }

    ...

}

public class SecondActivity extends Activity {

    private MyService mMyService;

    private ServiceConnection mMainServiceConnection = new ServiceConnection() {

        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            MyService mainService = ((LocalBinder) service).getService();
            mMyService = mainService;
            mMyService.setCallback(SecondActivity.this);
        }

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

    @Override
    protected void onResume() {
        super.onResume();
        bindService(new Intent(SecondActivity.this, MyService.class), mMainServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (mMainServiceConnection != null) {
            unbindService(mMainServiceConnection);
        }
    }

    @Override
    protected void onDestroy() {
        ...
        stopService(new Intent(SecondActivity.this, MyService.class));
    }

    ...

}
Run Code Online (Sandbox Code Playgroud)

这是保证在Activity不会被杀死或重新创建的s 背景下提供持久服务的最佳方式吗?

怎么样Context.BIND_AUTO_CREATE?将此标志设置在此处是否正确?怎么样Context.BIND_ADJUST_WITH_ACTIVITYContext.BIND_WAIVE_PRIORITY-我需要这些?

mat*_*ash 7

(非常感谢@ corsair992提供了有用的指示!)


如果活动总是按照这个顺序调用(即FirstActivity开始SecondActivity,而不是相反,那么你应该基本上试图将服务的生命周期"绑定"到FirstActivity生命周期.

一般情况下(见后面的警告),这意味着:

  • 呼叫startService()FirstActivity.onCreate().
  • 呼叫stopService()FirstActivity.onDestroy().
  • 调用bindService()/ unbindService()在两个活动的onStart()/ onStop()方法中(以访问Binder对象,并能够调用它上面的方法).

以这种方式启动的服务将一直处于活动状态,直到stopService()被调用并且每个客户端解除绑定,请参阅管理服务的生命周期:

这两条路径并不完全分开.也就是说,您可以绑定到已使用startService()启动的服务.(...)在这种情况下,stopService()或stopSelf()实际上不会停止服务,直到所有客户端解除绑定.

和:

当最后一个客户端从服务解除绑定时,系统会销毁该服务(除非该服务也是由startService()启动的).

有了这个基本策略,服务将FirstActivity在周围生存(即不会被破坏).然而,一个重要的观点仍然是:在配置发生变化时(如屏幕旋转)未明确处理会造成活性重启本身,该服务将被销毁(因为我们调用stopService()onDestroy()).

为了防止这种情况,您可以isChangingConfigurations()在实际停止服务之前进行检查(因为onDestroy()由于这个原因而发生的回调意味着虽然正在销毁Activity的这个特定实例,但之后将重新创建它.

因此,完整的解决方案将是这样的:

public class FirstActivity extends Activity
{
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startService(new Intent(this, MyService.class));
    }

    private ServiceConnection mServiceConnection = new ServiceConnection() { ... }

    @Override
    protected void onStart() {
        super.onStart();
        bindService(new Intent(this, MyService.class), mServiceConnection, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        unbindService(mServiceConnection);
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        if (!isChangingConfigurations())
            stopService(new Intent(this, MyService.class));

        super.onDestroy();
    }
Run Code Online (Sandbox Code Playgroud)

虽然SecondActivity执行onStart()/ onStop()方法(以同样的方式).


关于您的特定实现的几点说明:

  • 没有必要覆盖onBackPressed(),因为如果活动被破坏,将调用必要的生命周期方法(此外,它可以在不按下后退按钮的情况下完成,例如,如果调用finish()它).
  • 停止服务onDestroy()而不是让onPause()您不必检查isUserMovingToSecondActivity.