定期更新小部件不起作用

Periodically updating widget not working

我创建了一个小部件,我想每 5 秒定期更新一次(出于测试目的)。但是,该服务从未被调用。

public class WidgetProvider extends AppWidgetProvider {


    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        Log.i("STATUS", "APPWIDGET onUpdate");
        final int count = appWidgetIds.length;

        for (int i = 0; i < count; i++) {
            int widgetId = appWidgetIds[i];
            String number = String.format("%03d", (new Random().nextInt(900) + 100));
            Log.i("NUMBER", number);

            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_large);
            remoteViews.setTextViewText(R.id.tv_inmonths, number);

             Intent intentt = new Intent(context, UpdateService.class);
             PendingIntent pendingIntent = PendingIntent.getService(context, 0, intentt, PendingIntent.FLAG_UPDATE_CURRENT);
             AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
             alarmManager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (5 * 1000), pendingIntent);

            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
    }

  @Override
    public void onReceive(Context context, Intent intent) {
        super.onReceive(context, intent);
        Log.i("STATUS", "APPWIDGET onReceive");
            Bundle extras = intent.getExtras();
            if(extras!=null) {
                AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
                ComponentName thisAppWidget = new ComponentName(context.getPackageName(), WidgetProvider.class.getName());
                int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidget);
                if (appWidgetIds.length > 0) {

                    new WidgetProvider().onUpdate(context, appWidgetManager, appWidgetIds);
                }

            }

    }
}

public final class UpdateService extends Service {


    PendingIntent pendingIntent;

    @Override
    public void onCreate(){
        Log.i("STATUS", "Service onCreate");

        String number = String.format("%03d", (new Random().nextInt(900) + 100));
        Log.i("NUMBER2", number);

        RemoteViews updateViews = new RemoteViews(this.getPackageName(), R.layout.widget_large);
        updateViews.setTextViewText(R.id.tv_inmonths, number);  //ha ez AAAA akkor is eltűnik


        ComponentName thisWidget = new ComponentName(this, WidgetProvider.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(this);
        manager.updateAppWidget(thisWidget, updateViews);


    } 

    @Override
    public IBinder onBind(Intent intent) {
        // TODO Auto-generated method stub
        return null;
    }
}

清单:

<receiver android:name=".WidgetProvider" >
   <intent-filter>
      <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
   </intent-filter>
   <meta-data android:name="android.appwidget.provider"
              android:resource="@xml/widget_provider_large" />
</receiver>
<service android:enabled="true" android:name=".UpdateService" />

一旦我将小部件放在主屏幕上,这就是 logcat:

09-09 18:36:48.330  10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onReceive
09-09 18:36:48.340  10551-10551/myapp.myapp I/STATUS﹕ APPWIDGET onUpdate
09-09 18:36:48.340  10551-10551/myapp.myapp I/NUMBER﹕ 809

有时它会调用服务,但仅此而已。

更新: 我也用 Handler 尝试过,虽然它每 3 秒运行一次,但该服务只被调用一次

m_Handler = new Handler();
        mRunnable = new Runnable(){
            @Override
            public void run() {
                Log.i("STATUS", "run");
                Intent myIntent = new Intent(context, UpdateService.class);
                context.startService(myIntent);

                m_Handler.postDelayed(mRunnable, 3000);
            }
        };
        mRunnable.run();

两件事:

频繁报警

根据 AlarmManager.set() 的文档:

Note: Beginning in API 19, the trigger time passed to this method is treated as inexact: the alarm will not be delivered before this time, but may be deferred and delivered some time later. The OS will use this policy in order to "batch" alarms together across the entire system, minimizing the number of times the device needs to "wake up" and minimizing battery use. In general, alarms scheduled in the near future will not be deferred as long as alarms scheduled far in the future.

您可以使用 adb shell dumpsys alarm 确认何时安排警报,它提供了

的非常详细的输出

但请注意,即使使用 setExact() may not trigger with small intervals。相反,如 AlarmManager 文档顶部所述:

Note: The Alarm Manager is intended for cases where you want to have your application code run at a specific time, even if your application is not currently running. For normal timing operations (ticks, timeouts, etc) it is easier and much more efficient to use Handler.

服务

您正在使用 Service。根据 Services guide,以 startService() 开头的 Service 将保持 运行,直到您在 Service 中调用 stopSelf() 或某些其他组件调用 stopService()。由于 onCreate() 仅在首次创建 Service 时发生,因此您对 startService() 的后续调用不会重新触发您的代码。

相反,请考虑使用 IntentService - for each call to startService(), you'll get a callback to onHandleIntent() and the Service will be stopped immediately upon completion of all pending calls to onHandleIntent() or even better, just use a BroadcastReceiver - there's no reason to have a Service in this case as you aren't doing any long processing tasks (of course, you'd update your startService() to be instead use sendBroadcast())