【发布时间】:2012-07-05 14:59:27
【问题描述】:
我的应用程序通过 Web 服务调用将数据与远程数据库同步。我在 IntentService 中进行这些调用,以便它们可以在后台运行(我称之为 SyncService)。
启动我的 IntentService 的代码如下所示:
Intent intent = new Intent();
intent.setClass(appContext, SyncService.class);
// place additional values in intent
intent.putExtra("data_type", SyncService.ITEM_TRACKING);
intent.putExtra("user_id", intUserId);
// call SyncService
appContext.startService(intent);
这通常看起来很棒。但是,我的一位朋友也是我的应用程序的用户,他经常告诉我他的数据没有同步并显示在我们的网站上。当我在附近时,他的设备恰好显示了这些症状。我将他的设备插入我的电脑,这是我发现的:
- 启动 SyncService 的代码(即:上面的代码)被命中。
- 我的 IntentService 的 onHandleIntent 方法中有一个断点,它从不被命中。
- 我检查了他设备的运行服务列表,SyncService 在那里并且正在运行。有趣的是,它已经运行了大约 20 分钟。我的印象是,当 IntentService 完全无法处理时,IntentService 会自行杀死。
- 我强行停止了 SyncService(而不是应用程序),突然之间,onHandleIntent 开始反复受到攻击。就像所有 Intent 都在设备上的某个地方排队,然后刚刚被抛出 SyncService。
有人对可能出现的问题有任何想法吗?你认为这是我的应用程序的问题吗?用安卓?
我再次向 Android 发送一条消息,说“启动这个 IntentService 或将消息发送到已经运行的 IntentService。”那个时候,我无法控制。消息永远不会到达 IntentService。一旦我强制退出应用程序,消息就会发送到 IntentService 并完成它的工作。
更新:我认为这段代码很好,但我会把它放上来,因为你们很多人可能想看它。
进入 IntentService 的每个 Intent 都有一个 Extra 表示对我进行的调用的“类型”(即:我是调用 this Web 服务还是 that网络服务等)。当 Intent 进入 IntentService 时,我会检查“类型”,如果队列中已经有该类型的 Intent,我会在其中添加一个名为“skip”的 Extra,因此,当它到达时,我不会t 执行搜索(基本上 IntentService 可以构建很多 Intent,并且在 20 秒前调用 this webservice 时调用 this web service 是没有意义的)。它基本上可以保护应用免于向网站发送垃圾邮件。
请务必注意,无论如何都不会命中此代码(一旦问题开始出现)。 onStartCommand 在应用程序被杀死之前不会被调用
@Override
public int onStartCommand (Intent intent, int flags, int startId) {
// here be dragons
// overriding this method and adding your own code is dangerous. i've wrapped
// my code in a try/catch because it is essential that the super method be called
// every time this method is entered. any errors in my code should not prevent this
// or the app will explode.
try {
if (flags == 0 && intent != null && intent.hasExtra("data_type")) {
Integer intDataType = intent.getExtras().getInt("data_type");
if (!mCurrentTypes.containsKey(intDataType)
|| !mCurrentTypes.get(intDataType)) {
mCurrentTypes.put(intDataType, true); // put this type in the list and move on
}
else {
intent.putExtra("skip", true); // mark this Intent to be skipped
}
}
}
catch (Exception e) {
// Log.e("Error onStartCommand", "error: " + e);
}
return super.onStartCommand(intent, flags, startId);
}
private void processIntent(Intent intent) {
// do stuff if no "skip" Extra
mCurrentTypes.put(intDataType, false);
}
【问题讨论】:
-
您是否在清单文件中注册了您的服务?
-
是的。同样,该服务通常有效。我的朋友是唯一提到这个问题的人。而且大多数时候它对他来说效果很好,但偶尔会……拥堵?
-
您的 IntentService 中似乎有一段代码导致应用程序长时间停留。由于 IntentService 一个接一个地排队按顺序运行,这就解释了为什么在杀死当前的 IntentService 后你会一遍又一遍地点击 onHandleIntent。如果您可以发布您的 IntentService 代码,我们或许能够确定它为什么会卡在那里。
-
嗯...我的 IntentService 代码非常大(我有很多很多不同的 Web 服务)。有没有一种方法可以在 Intent 被处理然后完成时发布日志,并从他的手机中检索该日志以进行分析?
-
您的网络服务调用是否设置了超时?你在你的服务上创建任何线程吗?您是否有足够的时间调用您的服务以完成之前的执行?看起来有些东西正在阻止服务完成它的执行,并且其余已启动的服务都在排队。
标签: android service intentservice