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

Android 在后台长期服务且不会被杀死的活动,android,android-service,android-lifecycle,android-service-binding,Android,Android Service,Android Lifecycle,Android Service Binding,在Android上,我有一个名为FirstActivity的Activity,它启动一个名为MyService的服务,在后台进行网络工作活动和服务始终通过调用方法相互通信。 现在,当用户从FirstActivity导航到SecondActivity时,后台服务不应被终止或重新创建,而应保持活动状态并传递到SecondActivity,该服务现在将与服务通信 换句话说,服务应在两个活动s中的一个正在运行时运行,并且当用户在两个活动s之间导航时,服务不应停止。 其中一个活动s将始终位于前台,在此期间

在Android上,我有一个名为
FirstActivity
Activity
,它启动一个名为
MyService
服务,在后台进行网络工作活动
和服务始终通过调用方法相互通信。

现在,当用户从
FirstActivity
导航到
SecondActivity
时,后台服务不应被终止或重新创建,而应保持活动状态并传递到
SecondActivity
,该服务现在将与服务通信

换句话说,
服务
应在两个
活动
s中的一个正在运行时运行,并且当用户在两个
活动
s之间导航时,服务不应停止。

其中一个
活动
s将始终位于前台,在此期间,该服务(最好)不会被终止。我认为这不应该是一个问题,因为这两个
活动中的一个始终处于活动状态,因此Android知道该服务很重要,而不是必须终止的东西

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

总之,
服务
的寿命应与两个
活动
的“组合”寿命相同。它应该从第一个开始,在两个都被销毁之前停止。

那么下面的代码对于该设置和目标是否正确

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

    ...

}
这是在
活动
s的后台保证长期服务不会被终止或重新创建的最佳方法吗

那么
Context.BIND\u AUTO\u CREATE
呢?在这里设置此标志是否正确?关于
Context.BIND\u ADJUST\u与\u ACTIVITY
Context.BIND\u放弃\u优先级
——我需要这些吗?

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


如果活动总是按该顺序调用(即
FirstActivity
开始
SecondActivity
,而不是相反的顺序,那么基本上,您应该尝试将服务的生命周期与
FirstActivity
的生命周期“绑定”

一般而言(见下文的注意事项),这意味着:

  • FirstActivity.onCreate()
    中调用
    startService()
  • FirstActivity.ondestory()
    中调用
    stopService()
  • 在两个活动的
    onStart()
    /
    onStop()
    方法中调用
    bindService()
    /
    unbindService()
    (以访问Binder对象,并能够对其调用方法)
以这种方式启动的服务将一直处于活动状态,直到调用
stopService()
,并且每个客户端都解除绑定,请参阅:

这两条路径并不是完全分开的。也就是说,您可以绑定到 已使用startService()启动的服务。在这种情况下,stopService()或 stopSelf()在所有客户机停止服务之前不会停止服务 解开束缚

以及:

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

使用此基本策略,只要
FirstActivity
存在,服务就会一直存在(即未销毁)。但是,重要的一点仍然存在:如果未明确处理配置更改(例如屏幕旋转),将导致活动重新启动,服务将被销毁(因为我们正在
ondestory()
中调用
stopService()

为了防止这种情况发生,您可以在实际停止服务之前进行检查(因为由于此原因而发生的
ondestory()
回调意味着尽管活动的此特定实例正在被销毁,但随后将重新创建它)

因此,完整的解决方案如下:

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();
    }
SecondActivity
实现
onStart()
/
onStop()
方法(以相同的方式)


关于您的特定实现,请注意以下几点:

  • 无需重写
    onBackPressed()
    ,因为如果活动被销毁,将调用必要的生命周期方法(另外,可以在不按后退按钮的情况下完成,例如,如果对其调用
    finish()
  • onDestroy()
    中停止服务,而不是在
    onPause()
    中停止服务,这样您就不必检查
    isUserMovingToSecondActivity

您是否尝试过该代码,或者在尝试之前是否询问过?如果您尝试过,是否出现任何错误?它是否表现得不符合您的预期?如果您真的尝试过,然后向我们寻求解决方案,我们将进行更有成效的讨论,并为社区和您自己提供更有用的答案,具体问题是您需要的have@DallaRosa是的,当然可以当然,我已经试过了。这是一个关于如何设计服务类和相应的
活动
类的一般性问题,以使服务尽可能长且不被终止。用户报告称,此服务提供的功能在其中一个
活动
类中不时停止可用。and I(a)发现当系统可能终止此服务时很难调试,以及(b)希望了解一些最佳实践或改进,这些实践或改进应适用于此服务,以实现明确的目标和要求。我可以看到您对
服务的管理中存在许多问题。只有在第一个
活动
被销毁时,您才需要停止它,或者依赖绑定并正确管理它。Ther有一些通用的