当前位置: 首页 > 知识库问答 >
问题:

启动和绑定的服务何时被销毁?

西门建安
2023-03-14

我在浏览android中的服务文档时,发现了两个相互矛盾的地方:

在服务文档中,它是在管理服务生命周期中指定的

这两条道路并不是完全分开的。也就是说,您可以绑定到已使用startService()启动的服务。例如,可以通过调用startService()来启动背景音乐服务,目的是识别要播放的音乐。稍后,可能当用户想要对播放器进行某种控制或获取有关当前歌曲的信息时,活动可以通过调用bindService()绑定到服务。在这种情况下,stopService()或stopSelf()实际上不会停止服务,直到所有客户端解除绑定。

但是在关于绑定服务的文档中,在管理绑定服务的生命周期时

但是,如果选择实现onStartCommand()回调方法,则必须显式停止服务,因为该服务现在被视为已启动。在这种情况下,服务会一直运行,直到服务停止自己,并停止自己,或另一个组件调用停止服务(),而不管它是否绑定到任何客户端。

可能是我,但我认为这些说法相互矛盾。谁能澄清一下。。。

共有3个答案

能远
2023-03-14

是的,它起作用了。我想完成一个示例代码:

我必须用活动启动的服务制作一个应用程序,活动必须调用服务中的一些方法,即使活动被终止,服务也必须在后台运行,当活动重新启动时,如果它正在运行,就不必重新启动服务。我希望它能帮助你,你可以看看它是如何与日志一起工作的。这就是代码:

 public class MyActivity extends Activity{

    private MyService myService;
    private boolean mIsBound = false;

    private ServiceConnection mConnection = new ServiceConnection() {

        public void onServiceConnected(ComponentName className, IBinder binder) {
            MyService.MyBinder b = (MyService.MyBinder) binder;
            myService = b.getService();
            mIsBound = true
            //Do something
            // Here you can call : myService.aFonctionInMyService();

        }
        public void onServiceDisconnected(ComponentName className) {
            // Do something
            mIsBound = false;
        }
    }



    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);

        //Checked if my service is running
        if (!isMyServiceRunning()) {
            //if not, I start it.
            startService(new Intent(this,MyService.class));
        }
    }

    private boolean isMyServiceRunning() {
        ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
        for (RunningServiceInfo service : manager
                .getRunningServices(Integer.MAX_VALUE)) {
            if (MyService.class.getName().equals(
                    service.service.getClassName())) {
                return true;
            }
        }
        return false;
    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        doBindService();
    }




    //Connection to the Service
    private void doBindService() {
        bindService(new Intent(this,MyService.class), mConnection,
                Context.BIND_AUTO_CREATE);
    }

    // Disconnection from the service
    private void doUnbindService() {
        if (mIsBound) {
            // Detach our existing connection.
            unbindService(mConnection);
        }
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        doUnbindService();
        super.onPause();
    }

}


public class MyService extends Service{


    public static String Tag = "MyService";
    private final IBinder mBinder = new MyBinder();

    @Override
    public void onCreate() {
        // TODO Auto-generated method stub      
        super.onCreate();
        Log.d(Tag, "onCreate()");

    }

    public class MyBinder extends Binder {
        public LocationService getService() {
            return LocationService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(Tag, "onBind()");
        return mBinder;
    }

    @Override
    public boolean onUnbind(Intent intent) {
        // TODO Auto-generated method stub
        Log.d(Tag, "onUnBind()");
        return super.onUnbind(intent);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO Auto-generated method stub
        Log.d(Tag,"onStartCommand()");

        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub

        Log.d(Tag, "onDestroy");
        super.onDestroy();
    }

    public void aFonctionInMyService(){
        //Do Something
    }

}
唐弘和
2023-03-14

实际上,这两段文字是相辅相成的(尽管它们的措辞可能会误导读者),而且两段文字都与文档中的图像一致。我们来看看:

这两条道路并不是完全分开的。也就是说,您可以绑定到已使用startService()启动的服务。例如,可以通过调用startService()来启动背景音乐服务,目的是识别要播放的音乐。稍后,可能当用户想要对播放器进行某种控制或获取有关当前歌曲的信息时,活动可以通过调用bindService()绑定到服务。在这种情况下,stopService()或stopSelf()实际上不会停止服务,直到所有客户端解除绑定。

其精髓是:如果启动一个服务,然后将一个客户端绑定到它,然后尝试停止它,那么在所有客户端解除绑定之前,服务不会停止(销毁)。第二段并不矛盾,它完善了这一说法。

但是,如果选择实现onStartCommand()回调方法,则必须显式停止服务,因为该服务现在被视为已启动。在这种情况下,服务会一直运行,直到服务停止自己,并停止自己,或另一个组件调用停止服务(),而不管它是否绑定到任何客户端。

这意味着:已启动并绑定的服务即使没有客户端绑定到它,也会运行,直到它被明确停止。诚然,在这个问题上,措辞可能会更清晰一些。然而,文档中给出的生命周期图显示了这一点(我确信我已经在“现实生活”中观察到了这一点,尽管我目前还没有直接的例子):

邵星河
2023-03-14

同意留档可以更清晰。他们想说的是:

  • 如果您调用starService(),那么服务将继续运行,除非并直到您在服务中调用了Stop Serivce()(或Stop Self())
  • 如果您调用bindService(),那么服务将继续运行,除非并且直到您调用unbindService()
  • 因此,如果同时调用starService()和bindService(),则该服务将继续运行,直到同时调用停止服务和unbindService()。两者本身都不会停止服务。

创建了一个非常简单的活动和服务,并运行了以下启动/停止/绑定/取消绑定序列。我观察到这些电话给出了以下结果。

解开

bindService() caused:
    onCreate()
    onBind()
unbindService() caused:
    onUnbind()
    onDestroy()

开始绑定解除绑定停止

startService() caused:
    onCreate()
    onStartCommand()
bindService() caused:
    onBind()
unbindService() caused:
    onUnbind()
stopService() caused:
    onDestroy()

开始绑定停止解除绑定

startService() caused:
    onCreate()
    onStartCommand()
bindService() caused:
    onBind()
stopService() caused:
    -- nothing
unbindService() caused:
    onUnbind()
    onDestroy()

绑定开始停止解除绑定

bindService() caused:
    onCreate()
    onBind()
startService() caused:
    onStartCommand()
stopService() caused:
    -- nothing -- still running
unbindService() caused:
    onUnbind()
    onDestroy()

绑定开始解除绑定停止

bindService() caused:
    onCreate()
    onBind()
startService() caused:
    onStartCommand()
unbindService() caused:
    onUnbind()
stopService() caused:
    onDestroy()

如您所见,在每种同时调用bind和start的情况下,服务都会一直运行,直到同时调用unbind和stop。解除绑定/停止的顺序并不重要。

下面是在我的简单测试应用程序中从单独的按钮调用的示例代码:

public void onBindBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
}

public void onUnbindBtnClick(View view) {
    if (serviceIsBound) {
        unbindService(serviceConnection);
        serviceIsBound = false;
    }
}

public void onStartBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    startService(intent);
}

public void onStopBtnClick(View view) {
    Intent intent = new Intent(MainActivity.this, ExampleService.class);
    exampleService.stopService(intent);
}
 类似资料:
  • 我想创建一个即使应用程序被杀死也在运行的服务,所以我创建了一个未绑定的服务,这样它就不会绑定到活动生命周期。但是每次我通过长按和滑动杀死应用程序时,服务也会被杀死。请帮帮我。谢谢 服务 我从这样的活动中称之为 startService(new Intent(my service . class . getname())); 服务运行正常,直到应用程序在后台或前台,但当我长按并扫描应用程序时,服务也

  • 问题内容: 从我在Stack Exchange和其他地方看到的所有内容中,我已经正确设置了所有内容,可以在启动Android OS时启动IntentService。不幸的是,它没有在启动时启动,并且我没有收到任何错误。也许专家可以帮忙… 表现: 用于启动的BroadcastReceiver: 更新:我尝试了下面的几乎所有建议,并;在处理程序中添加了日志记录,但从未记录过任何内容。因此,它甚至还没有

  • 我很久以前做了一些自定义systemd服务,都有相同的配置(当然ExecStart除外) 这种配置已经运行了很多年,从18.04版LTS开始,我已经启动并运行了ubuntu,但是现在看起来有些systemd服务根本没有启动,配置如下(myapp.service): 服务已启用: 如果在重新启动后执行“systemctl status myapp”: 如果我在重新启动后执行“Journal alct

  • 我有能力安装jetty,我只是下载了jetty7 zip并提取了服务器。 我需要在3台linux机器上设置这个。在一台机器中,服务器启动得很好,没有问题。 但是在另外两个中,当服务器启动时,它会显示以下错误。

  • 问题内容: 当设备在android上启动时,我一直在尝试启动服务,但无法正常工作。我已经看了许多在线链接,但是这些代码都不起作用。我忘记了什么吗? 广播接收器 问题答案: 作为附加信息:BOOT_COMPLETE在挂载外部存储之前发送到应用程序。因此,如果将应用程序安装到外部存储,它将不会收到BOOT_COMPLETE广播消息。

  • 在我的应用程序中,我有一个在后台(和前台)运行。 在这个中,有一个,当它完成时,我想在某个中启动应用程序并在中自动执行一些操作,即使我的应用程序被杀死或关闭,我也希望它能正常工作。 我看到了一些答案,这是其中之一,但它对我不起作用。我找到了一个更好的解决方案,并将其作为答案发布在下面,但仍然只有在应用程序关闭但未完全关闭时才有效。 如何从后台启动,即使应用程序已关闭或关闭?