确定服务实例是否正在运行并将其终止

时间:2016-01-16 00:23:17

标签: java android

我有一个Android服务,让我们说“Service.java”

我启动一个实例并将一个唯一的id传递给我启动的每个服务实例(这样我就没有同时运行同一个uid的两个服务):

Intent intent = new Intent(this, Service.class);
intent.putExtra("KEY", uid);
startService(intent);

假设我在“Service.java”中为此uid设置了一个变量:

private String uid;
@Override
public int onStartCommand(Intent intent, int flags, final int startId) {
    super.onStartCommand(intent, flags, startId);

    if(intent != null) {
        Bundle infoBundle = intent.getExtras();
        this.uid = infoBundle.getString("KEY");
    }

    ...
}

public String getUid() { return this.uid; }

有没有办法以某种方式检查“Service.java”的实例是否正在使用给定的uid运行并将其杀死?

我有一个键/值对列表,我希望在一天中的特定时间启动此服务的实例,但如果用户“禁用”某个时间段(键/值对),我想要服务停下来。

背景故事:

我有一个应用程序在给定时间之前30分钟启动服务以轮询数据源以进行更改。数据馈送不再可用后,该服务将自行终止。

如果用户“不喜欢/禁用”这个时段(键/值对 - uid),我不希望服务在接下来的30分钟内运行,所以我想在它“不受欢迎”时立即将其杀死/禁止“

我可能会以错误的方式解决这个问题。

无论哪种方式,非常感谢输入,谢谢!

2 个答案:

答案 0 :(得分:1)

我更多地将其视为:您的服务需要知道数据模型何时发生变化。在这种情况下,数据模型是“键/值对列表”,每个都具有启用/禁用状态。

假设存储在数据库SharedPreferences或具有单例缓存的文件中以便快速访问,那么这里有三种选择让服务知道数据模型的变化:

  1. 使用事件总线或其他一些侦听器模式,因此如果服务存在,它会发现有关更改并可以采取一些适当的步骤。如果您的服务在单独的进程中运行,则事件总线必须是系统级广播(与LocalBroadcastManager相反,后者是进程内事件总线)。

  2. 使用ContentProvider在数据模型前面并使用ContentObserver通知更改(这就像用别克拍苍蝇一样,但是,嘿,这是一个选项)。

  3. 更改数据模型时调用startService(),并使用一些信息(例如,自定义操作字符串)让服务知道这是“检查您的数据模型”事件。这种方法的缺点是,如果服务尚未启动,则启动服务,但可能服务会意识到如果没有任何事情要做,只是立即停止服务。

  4. 就个人而言,我会选择#1选项。

    但是,要回到您的文字问题,根据需要从服务中提取数据的唯一好方法是使用绑定模式,您的客户端通过bindService()连接到服务并且服务发布一个Binder形式的API。这与您当前的方法并不相互排斥。但是,这种方法的缺点类似于上面的#3:如果服务尚未运行,尝试绑定到它的行为将创建服务的实例。

    没有什么可以阻止你采取“哦,服务是一个单身,所以我将通过一些static字段某处跟踪其状态”方法。我甚至偶尔也会为废话应用程序做过这件事,虽然它让我感到不安。它也仅适用于与应用程序其余部分相同的过程中的服务;如果您的服务是在一个单独的过程中,这种方法不起作用。

答案 1 :(得分:0)

根据文件,

  

请求启动给定的应用程序服务。意图可以   要么包含特定服务的完整类名   启动的实现,或通过操作的抽象定义   和其他领域的服务开始。如果是这项服务   尚未运行,它将被实例化并启动(创建一个   如果需要,它的过程);如果它正在运行,那么它仍然在运行。

但是如果你使用的是startService();

您应该指定何时停止服务中的服务,

并且您应该知道该服务将在主线程上运行(哪个阻塞主线程),除非您在服务中启动新线程,或者使用IntentService,它使用工作线程轮流处理每个Intent ,当它用完时停止运转。

您可以拥有一个线程池实现。并且有一个作业队列,在你把任何东西放到队列之前,你可以在那里检查它。

您可以将这些作业设置为可运行,并为每项作业提供UUid。你可以删除它们,用你随心所欲地打断它们。

这是一个cool example,复杂,但工作正常:)