用于AppWidget更新的IntentService很少发生崩溃

问题描述

| 我在做什么? 我正在使用IntentService更新AppWidget。 问题是什么? 一切工作都很好,除了极少数情况下,大概每12-15个小时,或者我可能会说随机的,小部件更新不会发生。在调试完这种情况之后,这里显示的是logcat消息,这似乎是问题所在。
05-27 20:21:13.122: WARN/ActivityManager(97): Scheduling restart of crashed service com.myapp.android/.myAppWidget$UpdateService in 5000ms
以下是一些更多的logcat消息-确实很难复制此消息,因为这种情况有时会发生一次,但是当我在使用调试模式通过USB端口连接的真实设备上重新启动该应用程序时,就会发生这种情况。
05-27 20:21:16.712: DEBUG/AndroidRuntime(24419): --- registering native functions ---
05-27 20:21:16.742: INFO/global(24420): Default buffer size used in BufferedInputStream constructor. It would be better to be explicit if an 8k buffer is required.
05-27 20:21:16.842: DEBUG/Configuration(24420): active site = local
05-27 20:21:16.872: DEBUG/FREESPACE(24420): Bytes to fill: 580550656
05-27 20:21:16.942: VERBOSE/AlarmManager(97): Adding Alarm{46389f38 type 2 com.google.android.apps.maps} Jan 01 09:30:42 am
05-27 20:21:17.032: INFO/ActivityManager(97): Start proc com.myApp.android for broadcast com.myApp.android/.myAppWidget: pid=24431 uid=10080 gids={1015,3003}
05-27 20:21:17.092: DEBUG/dalvikvm(24420): GC_FOR_MALLOC freed 3967 objects / 320968 bytes in 162ms
05-27 20:21:17.172: DEBUG/FREESPACE(24420): Bytes to fill: 580550656
05-27 20:21:17.252: ERROR/UpdateService(24431): Service Started.. 
05-27 20:21:17.332: INFO/ActivityManager(97): Force stopping package com.myApp.android uid=10080
05-27 20:21:17.332: INFO/Process(97): Sending signal. PID: 24431 SIG: 9
05-27 20:21:17.332: WARN/ActivityManager(97): Scheduling restart of crashed service com.myApp.android/.myAppWidget$UpdateService in 5000ms
05-27 20:21:17.332: INFO/ActivityManager(97): Starting activity: Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] flg=0x10000000 cmp=com.myApp.android/.myApp3 }
05-27 20:21:17.372: INFO/ActivityManager(97): Start proc com.myApp.android for activity com.myApp.android/.myApp3: pid=24444 uid=10080 gids={1015,3003}
05-27 20:21:17.402: DEBUG/AndroidRuntime(24419): Shutting down VM
这是扩展IntentService的UpdateService类的onReceive(),onUpdate()和onHandleIntent()的代码段
@Override
public void onReceive(Context context,Intent intent) {
    check_intent = intent.getAction();

    if (check_intent.equals(\"android.appwidget.action.APPWIDGET_UPDATE\")) {
        if (!getLock(context).isHeld()) {   // fail-safe for crash restart
            getLock(context).acquire();
        }
        try {
            this.onUpdate(context,intent);
        } finally {
            getLock(context).release();
        }
    }       
    if (check_intent.equals(\"android.appwidget.action.APPWIDGET_ENABLED\")) {
        this.onEnabled(context);
    }
    if (check_intent.equals(\"android.appwidget.action.APPWIDGET_DELETED\")) {
        this.onDeleted(context);
    }
    if (check_intent.equals(\"android.appwidget.action.APPWIDGET_DISABLED\")) {
        this.onDisabled(context);
    }
    super.onReceive(context,intent);
}
这是
onUpdate
,其中称为
startService
方法
public void onUpdate(Context context,Intent intent) {

    mAppPreferences = PreferenceManager.getDefaultSharedPreferences(context);
    int saved_num_widgets = mAppPreferences.getInt(NUM_WIDGETS,0);

    if (saved_num_widgets > 0) {     
        Intent widgetUpdate = new Intent(context,myAppWidget.class);
        widgetUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        AlarmManager alarms =
            (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        PendingIntent newPending =
            PendingIntent.getBroadcast(context,widgetUpdate,PendingIntent.FLAG_CANCEL_CURRENT);
        alarms.set(AlarmManager.ELAPSED_REALTIME,SystemClock.elapsedRealtime() + PERIOD,newPending); 
        context.startService(new Intent(context,UpdateService.class));
    } else {
        //Show Notification         
    }
}
最后是ѭ6的代码
@Override
protected void onHandleIntent(Intent intent) {
    // here is where your long running task goes

    RemoteViews updateViews = buildUpdate(this);
    // Push update for this widget to the home screen
    if (updateViews != null) {
        ComponentName thisWidget = new ComponentName(this,myAppWidget.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(this);
        manager.updateAppWidget(thisWidget,updateViews);
    } else {
        updateViews = new RemoteViews(getApplicationContext().getPackageName(),R.layout.tuwidget);
        updateViews.setImageViewResource(R.id.ad,R.drawable.myApp_null_game);
        Intent defineIntent1 = new Intent(getApplicationContext(),myApp3.class);
        PendingIntent pendingIntent1 =
            PendingIntent.getActivity(getApplicationContext(),0 /* no requestCode */,defineIntent1,0 /* no flags */);
        updateViews.setOnClickPendingIntent(R.id.tuwidget,pendingIntent1);
        ComponentName thisWidget = new ComponentName(this,updateViews);
    }   

} 
我还想提到IntentService扩展的UpdateService类是 我没有使用onStartCommand onCreate()如下
@Override
public void onCreate() {
    super.onCreate();
    Log.e(\"UpdateService\",\"Service Started.. \");
}
小部件以正确的时间间隔进行更新,并且一切正常,并且根本没有强制关闭,但是我完全迷失了为什么更新不会只发生几次。 我没有为buildUpdate函数提供代码,该函数返回RemoteViews以更新小部件,因为我110%确信该部分可以正常工作。 更新:我注意到的是,每当发生此问题时,我都会看到IntentService的较早实例仍在Applications-> Running Services中运行,这意味着有时不会调用onDestroy(),并且该服务不会像预期的那样自动停止。有趣的是,我所做的是创建一个共享首选项以将服务的状态存储为正在运行或已停止,并从onCreate()和onDestroy()进行切换。现在,在调用startService()之前,我先检查共享首选项的状态,如果服务实例仍在运行,则先调用stopService(),然后再调用startService()。我仍在测试,但是在编码此替代方法后,问题尚未发生!!     

解决方法

        此日志表明有人致电活动管理器杀死您的应用程序:
05-27 20:21:17.332: INFO/ActivityManager(97): Force stopping package com.myApp.android uid=10080
05-27 20:21:17.332: INFO/Process(97): Sending signal. PID: 24431 SIG: 9
在Android 2.2之前的版本中,这将是强制停止API,例如,任务管理器用于终止应用程序并停止其所有服务等。请检查以确保您的设备上没有安装任何任务管理器类型的应用,在做令人讨厌的事情。 从2.2版本开始,任务管理器使用的API进行了更改,以使其只能杀死后台进程。看来这是这里正在发生的事情–该进程已被终止,但是并未强制停止整个应用程序,因为该服务将留待以后重新启动。 (如果设备的内存严重不足到系统无法在一段时间内保持所有后台服务运行的程度,则基本上完全相同,这也是正常情况。) 因为您看到了这一点,所以我们实际上处于正常操作情况下:
05-27 20:21:17.332: WARN/ActivityManager(97): Scheduling restart of crashed service com.myApp.android/.myAppWidget$UpdateService in 5000ms
也就是说,您的进程在后台被杀死。好的,这很正常,我们将重新安排您的服务,以便稍后重新启动。这就是为什么该服务保留在“正在运行的服务” UI中的原因,因为它仍处于启动状态,只是现在没有要运行的进程。 在这种情况下,是的,您的onDestroy()不被调用,因为整个服务都消失了。同样,这是正常的。 因此,从日志中我看不到发生了什么错误(除了某些应用可能导致它发生的频率比您通常遇到的情况还要多)。您的应用程序肯定需要处理这种情况,而不会崩溃。 :)     

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...