gpt4 book ai didi

android - IntentService 在 Android 4.2 (Jelly Bean) 上有问题吗?

转载 作者:行者123 更新时间:2023-11-29 02:40:40 25 4
gpt4 key购买 nike

我正在编写一个需要每分钟与远程服务器同步的应用程序。无法使用推送通知,因为应用程序仅供内部使用,不会在 Google Play 上发布。我发现我可以使用 AlarmManager 和 IntentService 来达到我的目标。因此,我安排每分钟传递一次挂起的 Intent ,并在 IntentService 中处理它以执行网络 I/O。这听起来很简单,但我遇到了以下问题:应用程序在一段时间后(我想大约 100 分钟)失败并出现以下错误。

05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: WARNING: The Looper class instance count has over a limit(100). There should be some leakage of Looper or HandlerThread.
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: Looper class instance count = 101
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: Current Thread Name: IntentService[BackgroundService]

我创建了一个非常简单的示例来更仔细地检查问题。所以它看起来像:

Activity :

public class MainActivity extends AppCompatActivity {
private AlarmManager alarmManager;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
PendingIntent pi = PendingIntent.getService(getBaseContext(), 0, BackgroundService.getIntent(getBaseContext()), PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, 0, 500, pi);
}
}

服务:

public class BackgroundService extends IntentService {
private final static String TAG = BackgroundService.class.getSimpleName();
private final static String ACTION_START = "ru.infotecs.intentservice.action.START";
private static volatile int counter = 0;

public BackgroundService() {
super(TAG);
counter = 0;
}

public static Intent getIntent(Context context) {
Intent intent = new Intent(context, BackgroundService.class);
intent.setAction(ACTION_START);
return intent;
}

@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (ACTION_START.equals(action)) {
counter++;
Log.d(TAG, ACTION_START + " - "+ counter);
}
}
}
}

如您所见,我将时间间隔从 1 分钟减少到 500 毫秒,以更快地重现问题。所以现在大约需要几分钟,但无论如何结果是一样的:

05-27 06:52:04.348 32176-32717/ru.infotecs.intentservice D/BackgroundService: ru.infotecs.intentservice.action.START - 1
05-27 06:52:04.846 32176-32720/ru.infotecs.intentservice D/BackgroundService: ru.infotecs.intentservice.action.START - 1
05-27 06:52:05.349 32176-32726/ru.infotecs.intentservice D/BackgroundService: ru.infotecs.intentservice.action.START - 1
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: WARNING: The Looper class instance count has over a limit(100). There should be some leakage of Looper or HandlerThread.
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: Looper class instance count = 101
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice E/Looper: Current Thread Name: IntentService[BackgroundService]
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice I/System.out: java.lang.ThreadGroup[name=main,maxPriority=10]
05-27 06:52:05.845 32176-32732/ru.infotecs.intentservice I/System.out: Thread[main,5,main]
05-27 06:52:05.846 32176-32732/ru.infotecs.intentservice I/System.out: Thread[Thread-5,5,main]
05-27 06:52:05.847 32176-32732/ru.infotecs.intentservice I/System.out: Thread[Binder_1,5,main]
05-27 06:52:05.847 32176-32732/ru.infotecs.intentservice I/System.out: Thread[Binder_2,5,main]
05-27 06:52:05.847 32176-32732/ru.infotecs.intentservice I/System.out: Thread[IntentService[BackgroundService],5,main]
05-27 06:52:05.848 32176-32732/ru.infotecs.intentservice W/System.err: java.lang.Throwable: stack dump
05-27 06:52:05.848 32176-32732/ru.infotecs.intentservice W/System.err: at java.lang.Thread.dumpStack(Thread.java:489)
05-27 06:52:05.848 32176-32732/ru.infotecs.intentservice W/System.err: at android.os.Looper.prepare(Looper.java:105)
05-27 06:52:05.849 32176-32732/ru.infotecs.intentservice W/System.err: at android.os.Looper.prepare(Looper.java:86)
05-27 06:52:05.849 32176-32732/ru.infotecs.intentservice W/System.err: at android.os.HandlerThread.run(HandlerThread.java:53)
05-27 06:52:05.850 32176-32732/ru.infotecs.intentservice D/BackgroundService: ru.infotecs.intentservice.action.START - 1

我想知道这种微不足道的应用程序是如何导致错误的。我稍微检查了 IntentService 实现,发现服务在 Intent 处理后自动停止。

private final class ServiceHandler extends Handler {
public ServiceHandler(Looper looper) {
super(looper);
}

@Override
public void handleMessage(Message msg) {
onHandleIntent((Intent)msg.obj);
stopSelf(msg.arg1);
}
}

每次服务被销毁时,looper 也会停止:

@Override
public void onDestroy() {
mServiceLooper.quit();
}

所以我完全不知道哪里出了问题。有什么想法吗?

我使用特定设备来运行我的应用程序。它是 RugGear RG500。问题不会在模拟器上重现,因此可能是设备运行时的问题。

附言目前,我通过一些修改将 IntentService 实现应用到我的项目中来解决这个问题。我注释掉了 stopSelf 方法调用,以尽可能保持 Looper/Thread Activity 。它不能完全解决问题,因为 Android 可能会在内存不足的情况下停止服务并在最近重新启动它。

最佳答案

由于我之前没有检查过内存泄漏,所以需要一些时间才能弄清楚到底发生了什么。看起来设备制造商对 Looper 代码进行了一些检测以跟踪分配。它只是打印错误消息并转储调用堆栈,但同时应用程序非常稳定。我认为这是特定于供应商的代码,因为我没有在 Android SDK 的源代码中找到此消息。

如果你打开内存分配监视器,你会看到内存在一段时间内稳定分配,最后释放。这意味着垃圾收集是由 JVM 发起的。分配内存的峰值在连续的时间段内保持不变。它不会像预期的那样随着时间的推移急剧增长。

此外,GC 后错误消息消失。我假设分配计数器只是在检测类的 finalize 方法中重置。

关于android - IntentService 在 Android 4.2 (Jelly Bean) 上有问题吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44372892/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com