DP5 7.0-将额外内容添加到挂起的意图中是否会失败? [英] DP5 7.0 - Does adding extras to a pending intent fail?

查看:90
本文介绍了DP5 7.0-将额外内容添加到挂起的意图中是否会失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在跟踪器上添加链接的问题:
https://code.google.com/p/android/issues/detail?id=216581&thanks=216581&ts=1468962325

Adding the linked issue on tracker: https://code.google.com/p/android/issues/detail?id=216581&thanks=216581&ts=1468962325

所以我今天在Nexus 5X上安装了DP5 Android 7.0版本。我一直在开发一个使用Android的AlarmManager类在特定时间安排本地通知的应用程序。在此发行版之前,该代码在运行KitKat,Lollipop和棉花糖的设备上运行良好。

So I installed the DP5 Android 7.0 release onto my Nexus 5X today. I've been working on an app that schedules local notifications at specific times using Android's AlarmManager class. Up until this release, the code has been working great on devices running KitKat, Lollipop, and Marshmallow.

下面是我安排警报的方式:

Below is how I'm scheduling the alarms:

Intent intent = new Intent(context, AlarmManagerUtil.class);
            intent.setAction(AlarmManagerUtil.SET_NOTIFICATION_INTENT);
            intent.putExtra(AlarmManagerUtil.REMINDER_EXTRA, Parcels.wrap(reminders));
            intent.putExtra("time", when.getMillis());
            PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
            if (alarmManager != null) {
                if (Build.VERSION.SDK_INT >= 23) {
                  alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);
                } else if (Build.VERSION.SDK_INT >= 19) {
                    alarmManager.setExact(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);
                } else {
                    alarmManager.set(AlarmManager.RTC_WAKEUP, when.getMillis(), pendingIntent);
                }

我的AlarmManagerUtil @on接收 SET_NOTIFICATION_INTENT如下所示:

My AlarmManagerUtil @onReceive of the "SET_NOTIFICATION_INTENT" looks like this:

public void fireNotification(Context context, Intent intent) {
    List<Reminder> reminderToFire = Parcels.unwrap(intent.getParcelableExtra(REMINDER_EXTRA));
    long timeToFire = intent.getLongExtra("time", 0L); //.... }

奇怪的是 reminderToFire在这里为空 仅在Android N设备上 ,但是timeToFire是正确的。

What's strange is the "reminderToFire" is null here only on Android N devices but the timeToFire is correct.

我在想它与包裹库有关吗?我正在使用Java 1.8进行编译,并以Android API 24为目标。

I'm thinking its something to do with the Parceler Library? I'm compiling using Java 1.8 and targeting Android API 24.

我肯定在网上寻找答案,但是自从我的案例以来代码100%适用于所有早期版本的Android(N预览版之下的所有内容)...因此,我将尽可能遵循以下答案:

I've definitely looked around the net for an answer to this, but my case is a bit unique since the code 100% works on all prior versions of Android (everything below N preview)...so I am following the below answers as much as I can:

如何正确地将唯一的额外内容传递给待处理的意图?

还有其他人遇到这个问题吗?

Anybody else have this issue?

推荐答案

对于到这里结束工作的任何人,都希望通过AlarmManager(尚未放弃并转到JobScheduler),在生产API 24版本中的Google不支持将Parcelable对象传递给AlarmManager。

For anyone ending up here pulling your hair out over AlarmManager (and haven't given up and gone to JobScheduler yet), Google in the production API 24 build does not support passing a Parcelable object into the AlarmManager.

我解决这个问题的方法:
如果您需要将列表(或单个对象)发送到AlarmManager中,请将该项目作为字符串存储到SharedPreferences中。 (Gson.toJson(object,type))如果对象是一个接口,则有许多接口适配器解决方案。我发现一个漂浮在S / O周围的东西:

The way I got around this: If you need to send a List (or single object) into the AlarmManager, store the item into SharedPreferences as a String. (Gson.toJson(object, type)) If the object is an interface, there are a number of interface adapter solutions out there. One I found floating around S/O:

public final class InterfaceAdapter<T> implements JsonSerializer<T>, JsonDeserializer<T> {

public JsonElement serialize(T object, Type interfaceType, JsonSerializationContext context) {
    final JsonObject wrapper = new JsonObject();
    wrapper.addProperty("type", object.getClass().getName());
    wrapper.add("data", context.serialize(object));
    return wrapper;
}

public T deserialize(JsonElement elem, Type interfaceType, JsonDeserializationContext context) throws JsonParseException {
    final JsonObject wrapper = (JsonObject) elem;
    final JsonElement typeName = get(wrapper, "type");
    final JsonElement data = get(wrapper, "data");
    final Type actualType = typeForName(typeName);
    return context.deserialize(data, actualType);
}

private Type typeForName(final JsonElement typeElem) {
    try {
        return Class.forName(typeElem.getAsString());
    } catch (ClassNotFoundException e) {
        throw new JsonParseException(e);
    }
}

private JsonElement get(final JsonObject wrapper, String memberName) {
    final JsonElement elem = wrapper.get(memberName);
    if (elem == null)
        throw new JsonParseException("no '" + memberName + "' member found in what was expected to be an interface wrapper");
    return elem;
}
}

一旦设置了适配器,您将不会如果您使用像这样的某种DI框架(例如Dagger2),则每次都需要使用TypeAdapter设置GS0N ...

Once you have the adapter set up, you won't need to set up GS0N each time with the TypeAdapter if you're using some sort of DI framework (i.e. Dagger2) like so...

@Singleton
@Provides
public Gson providesGson() {
    return new GsonBuilder()
            .registerTypeAdapter(YourInterfaceClass.class, new InterfaceAdapter<YourInterfaceClass>())
            .create();

因此,您所要做的就是运行...。

So all you'll have to do is run....

/**
 * stores yourInterfaceClass in shared prefs
 */
public void setNextReminder(List<YourInterfaceClass> yourInterfaceClass) {
    Type type = new TypeToken<List<YourInterfaceClass>>() {}.getType();
    sharedPrefs.edit().putString(YOUR_KEY, gson.toJson(yourInterfaceClass, type)).apply();
}

希望这会有所帮助。当然,当您需要从共享首选项中删除此对象时......

Hope this helps. Of course, when you need to get this object out of shared prefs....

String json = sharedPrefs.getString(YOUR_KEY, "No object found");

执行典型的List对象= gson.fromJson(json,type)应该可以。

Doing the typical List object = gson.fromJson(json, type) should work.

干杯。

这篇关于DP5 7.0-将额外内容添加到挂起的意图中是否会失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆