【问题标题】:IntentService stopping immediatelyIntentService 立即停止
【发布时间】:2014-01-28 18:02:43
【问题描述】:

我有我的应用程序设置,其中(非意图)服务将使用 gps/网络侦听器轮询位置。它工作得很好,因为我负责服务何时结束(即在找到新位置或达到超时时调用 stopSelf() )。但是,我最近读到,intentService 可能更适合长时间运行的任务,因为它不是在 ui 线程上运行,而是在它自己的工作线程上运行。问题是,现在它不允许服务在任何时候运行(我假设这是因为服务中没有任何活动发生,而侦听器等待接收位置,因此服务自行结束)。

当它是非意图服务时,我的 onStartCommand() 方法看起来像:

@Override
protected void onStartCommand(Intent intent) {
    grabLocation();
}

由于我已将服务切换为 Intent 服务,因此我取消了此方法(根据文档,它不应该被 intentSerivce 覆盖),现在我的 onHandleIntent 服务如下所示:

@Override
protected void onHandleIntent(Intent intent) {
    grabLocation(); 
}

服务几乎立即结束。服务结束后如何延期?

我使用 startService(Intent) 像其他任何服务一样调用该服务

locationPollingIntent = new Intent(MainActivity.this, LocationService.class);
updateLocationButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            startService(locationPollingIntent);
        }
    });

清单sn-p:

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >

    <service
        android:name="com.rperryng.intellilocation.backgroundServices.LocationService"
        android:label="Location Service" />

    <receiver android:name="com.rperryng.intellilocation.backgroundServices.AutoStart" />

    <activity
        android:name="com.rperryng.intellilocation.activities.MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

【问题讨论】:

  • 如何启动 IntentService?您的清单文件看起来如何?
  • 我已经添加了你提到的代码 @EarlOfEgo 。如果您想知道服务是否已启动,它是,我有来自整个服务的 Logcat 消息(包括 onCreate、onHandleIntent、grabLocation() 和 onDestroy())它只是没有给我的听众任何时间必须在终止服务之前检索位置更新

标签: android intentservice


【解决方案1】:

但是,我最近读到,intentService 可能更适合长时间运行的任务,因为它不是在 ui 线程上运行,而是在它自己的工作线程上运行

仅适用于本质上是“事务性”的事情:数据库 I/O、Web 服务调用、下载小文件等。不适合您这种情况。

我假设这是因为服务中没有主动发生任何事情,而侦听器等待接收位置,因此服务自行结束

更具体地说,一旦onHandleIntent() 返回,如果没有更多命令等待处理,服务将调用stopSelf()

服务结束后我该怎么做才能推迟?

回到你原来的方法,但是通过使用HandlerThread 和使用LooperrequestLocationUpdates() 的风格,在后台线程上将位置传递给你。这样,当你的位置到达时,你就在后台线程上,可以对位置做任何你需要做的事情,然后你可以stopSelf() 离开。

但是,这会变得很棘手,因为您还需要超时,以防您永远无法修复位置。而且,您必须担心让设备保持唤醒状态,因此在您等待修复时它不会进入睡眠状态。我写了a LocationPoller library来处理这些东西,虽然我已经很多年没用过了,所以上面有一层相当厚的灰尘。

您可以考虑使用requestLocationUpdates()PendingIntent 风格或LocationClient API 上的等效版本,作为其中任何一种的替代方案。然后,您可以使用 IntentService 来处理定位修复的结果

【讨论】:

  • 感谢您提供的内容丰富的回复,我最近多次查看您的图书馆。我不担心从睡眠中丢失信息,因为位置不是应用程序的重要组成部分,我也不想添加唤醒锁权限。你觉得使用 handlerthread 仍然是我只需要轮询位置并将其保存到 sharedPreferences 对象中的最佳方法吗?
  • 你指的是这个文档吗? developer.android.com/guide/components/…
  • @Raian1614:“你觉得使用 handlerthread 仍然是我只需要轮询位置并将其保存到 sharedPreferences 对象中的最佳方法吗?” -- 你应该异步执行磁盘 I/O。对于SharedPreferences,如果您的android:minSdkVersion 为9 或更高,您可以使用SharedPreferences.Editor 上的apply() 方法,该方法为您处理后台线程。在这种情况下,您可以跳过HandlerThread 并只接收主应用程序线程上的位置,因为您不需要在该线程上花费太多时间。
  • 谢谢。如果我想稍微扩展我的项目以与该位置进行一些网络连接,是否只将发送网络请求的代码放在处理程序线程中?
  • @Raian1614:Handler 线程的唯一原因是直接在LocationListener 中获得控制权,因为requestLocationUpdates() 需要Looper 用于后台线程,@987654343 @ 是满足该要求的一种简单方法。另一种方法是,如果您的 LocationListener 回调到达主应用程序线程,则在从回调本身派生的线程上执行网络 I/O 或其他“繁重的工作”,在这种情况下,它可以是常规线程,或来自ThreadPoolExecutor 的一个,或其他。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-12-18
  • 2019-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
相关资源
最近更新 更多