如何在警报管理器启动服务时使用intent更新发送到服务的数据?

use*_*117 5 service android alarmmanager android-intent

我正在编写一个Android应用程序,用户可以选择多个股票进行观察,并在预定义的警报条件匹配时收到警报.库存数据保存到自定义Parcelable类"alert"的5个对象(每个库存和条件一个对象).定期数据更新是通过AlarmManager启动的服务完成的.警报对象通过将它们放入Intent而传递给服务,该Intent被放入AlarmManager的PendingIntent中.

    Intent intent = new Intent(this, UpdateService.class);
    Bundle b = new Bundle();
    saveAlertsToBundle(b);      
    intent.putExtras(b);
    intent.setData(Uri.parse("updateManager"));
    PendingIntent pendIntent = PendingIntent.getService(this,0,intent,0);

    // 1min intervall
    long intervall = DateUtils.MINUTE_IN_MILLIS * 1;
    // time of first start
    long firstStartDelay = DateUtils.SECOND_IN_MILLIS * 30;
    long firstStart = System.currentTimeMillis() + firstStartDelay;

    AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
    // kill running
    am.cancel(pendIntent);
    //start new
    am.setRepeating(AlarmManager.RTC_WAKEUP,firstStart,intervall,pendIntent);
Run Code Online (Sandbox Code Playgroud)

我的问题是:

当第一次启动服务时,只有一个警报对象传递给服务,一切正常.一旦存在更多警报对象,它们也需要传递给服务,但这不适用于上面的代码.该服务不会使用其他警报对象接收更新的意图,而只会接收仅具有一个警报对象的初始意图.上面的代码正确地创建了一个包含额外警报对象的Intent,但它们从未进入该服务.

所以我的问题是,如何将更新的意图传递给已经运行的AlarmManager.

我已经尝试停止AlarmManager(// kill运行注释中的行)并重新启动它,但这不起作用.也许是因为意图没有像他创建时那样保持相同的警报对象?我尝试通过在意图的数据部分设置uri来解决这个问题,但这也无济于事.

感谢帮助.

Dav*_*ser 2

你的问题是工作方式PendingIntent。系统管理一个PengingIntents池。当你的代码执行以下操作时:

PendingIntent pendIntent = PendingIntent.getService(this,0,intent,0);
Run Code Online (Sandbox Code Playgroud)

这会导致系统搜索与PendingIntent您传入的参数(在本例中为您的Intent)相匹配的 。但是,使用的匹配算法PendingIntent仅比较 的某些字段Intent来确定它是否是您要查找的参数。特别是,它不比较 extras。所以这意味着在您创建第一个之后PendingIntent,对 的调用将始终从池中PendingIntent.getService()返回相同的值(而不是创建一个新的,这正是您想要的)。PendingIntent

为了使每次调用时都PendingIntent.getService()创建一个新的调用PendingIntent,请尝试使传递给调用的参数唯一,如下所示:

int requestCode = (int) System.currentTimeMillis(); // Create unique request code
PendingIntent pendIntent = PendingIntent.getService(this, requestCode, intent, 0);
Run Code Online (Sandbox Code Playgroud)

由于requestCode每次调用都会不同PendingIntent.getService(),这应该可以解决您的问题。

编辑根据下面OP的评论

您想要取消现有警报并使用新数据创建一个新警报。在这种情况下,您不需要使用唯一标识符,因为您只想PendingIntent在池中拥有一个。但是,您想更改数据。尝试这个:

// Create a PendingIntent (or update the existing PendingIntent with new values
PendingIntent pendIntent = PendingIntent.getService(this, 0, intent,
                      PendingIntent.FLAG_UPDATE_CURRENT);

AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// cancel any pending alarms
am.cancel(pendIntent);
//start new
am.setRepeating(AlarmManager.RTC_WAKEUP,firstStart,intervall,pendIntent);
Run Code Online (Sandbox Code Playgroud)