android - widget AlarmManager重复得太快了

时间:2014-08-18 12:53:11

标签: android android-widget alarmmanager

我有一个显示数据使用情况的小部件,为此我创建了一个PreferenceActivity,用户可以从中选择各种更新频率。 我从SharedPreferences中获取所选的freq值,然后我开始发出警报,但结果很奇怪。这是我的AppWidgetProvider:

private static PendingIntent pendingIntent = null;
...
public void onReceive(Context context, Intent intent) {
    Log.d("TAG", "receive");
    super.onReceive(context, intent);

    if (CLOCK_WIDGET_UPDATE.equals(intent.getAction())) {
        ComponentName thisAppWidget = new ComponentName(context.getPackageName(), getClass().getName());
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
        int ids[] = appWidgetManager.getAppWidgetIds(thisAppWidget);
        for (int appWidgetID : ids) {
            updateAppWidget(context, appWidgetManager, appWidgetID);

        }
    }
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    Log.d("TAG", "update");
    super.onUpdate(context, appWidgetManager, appWidgetIds);

    for (int i = 0; i < appWidgetIds.length; i++) {
        int appWidgetId = appWidgetIds[i];

        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

public static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int appWidgetId) {

    // starting timer
    AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    alarmManager.cancel(pendingIntent);

    Intent intent = new Intent(CLOCK_WIDGET_UPDATE);
    pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);


    SharedPreferences prefs = context.getSharedPreferences(Integer.toString(appWidgetId), Context.MODE_PRIVATE);
    int updateFrequencyMin = Integer.parseInt(prefs.getString(KEY_UPDATE_FREQ, DEFAULT_UPDATE_FREQ));
    Log.d("TAG", "Update freq: " + updateFrequencyMin);
    long updateFrequencyMillis = updateFrequencyMin * 60 * 1000;
    // alarmManager.cancel(pendingIntent); 
    alarmManager.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), updateFrequencyMillis,
            pendingIntent);

    ....
    appWidgetManager.updateAppWidget(appWidgetId, view);
}

public void onDisabled(Context context) {

    AlarmManager m = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    m.cancel(pendingIntent);
}

如果我使用InexactRepeating将更新频率设置为5分钟,我会收到此日志:

08-18 15:30:17.902: D/TAG(23624): receive
08-18 15:30:18.122: D/TAG(23624): receive
08-18 15:30:18.122: D/TAG(23624): update
08-18 15:30:18.122: D/TAG(23624): Update freq: 60
08-18 15:30:22.582: D/TAG(23624): receive
08-18 15:30:22.602: D/TAG(23624): Update freq: 60
08-18 15:30:33.272: D/TAG(23624): receive
08-18 15:30:33.282: D/TAG(23624): Update freq: 60
08-18 15:30:39.692: D/TAG(23624): receive 
08-18 15:30:39.692: D/TAG(23624): Update freq: 60
08-18 15:31:33.292: D/TAG(23624): receive <--- I have chosen the freq
08-18 15:31:33.292: D/TAG(23624): Update freq: 5
08-18 15:31:39.962: D/TAG(23624): receive
08-18 15:31:39.962: D/TAG(23624): Update freq: 5

我不知道为什么在配置活动时多次调用onReceive和onUpdate。

使用setRepeat方法会更糟糕,因为您可以看到时间戳:

08-18 15:38:59.992: D/TAG(24011): receive
08-18 15:39:00.242: D/TAG(24011): receive
08-18 15:39:00.242: D/TAG(24011): update
08-18 15:39:00.252: D/TAG(24011): Update freq: 60
08-18 15:39:00.442: D/TAG(24011): receive
08-18 15:39:00.442: D/TAG(24011): Update freq: 60
08-18 15:39:00.562: D/TAG(24011): receive
08-18 15:39:00.562: D/TAG(24011): Update freq: 60
08-18 15:39:00.642: D/TAG(24011): receive
08-18 15:39:00.642: D/TAG(24011): Update freq: 60
08-18 15:39:00.652: D/TAG(24011): receive
08-18 15:39:00.652: D/TAG(24011): Update freq: 60
08-18 15:39:00.662: D/TAG(24011): receive
08-18 15:39:00.662: D/TAG(24011): Update freq: 60

最后,这是我的偏好活动:

public class DataStatWidgetConfigure extends PreferenceActivity {
    private int widgetId;

    @SuppressWarnings("deprecation")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {

            widgetId = extras.getInt(AppWidgetManager.EXTRA_APPWIDGET_ID,     AppWidgetManager.INVALID_APPWIDGET_ID);
            Log.d("meeegy", Integer.toString(widgetId));
            getPreferenceManager().setSharedPreferencesName(Integer.toString(widgetId));
            addPreferencesFromResource(R.xml.prefs);
        }

    }

    @Override
    public void onBackPressed() {
        Intent resultValue = new Intent();
        resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
        setResult(RESULT_OK, resultValue);
        finish();
    }
}

2 个答案:

答案 0 :(得分:1)

从我在代码中看到的内容,您在更新窗口小部件时永远不会取消以前的警报。所以你不断向AlarmManager添加越来越多的回调。尝试删除之前的回叫,然后添加一个新回复

答案 1 :(得分:0)

问题在于:

 alarmManager.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis(), updateFrequencyMillis,
        pendingIntent);

第二个参数是需要先调用的时候,System.currentTimeMillis()现在意味着,所以在OnReceive()之后就调用了updateAppWidget(),它立即再次调用了这个setInexactRepeating(),依此类推..

解决方案:

alarmManager.setInexactRepeating(AlarmManager.RTC, System.currentTimeMillis() + updateFrequencyMillis,
            updateFrequencyMillis, pendingIntent);