如何通过 PendingIntent 将自定义可序列化对象传递给 BroadcastReceiver
How to pass custom Serializable object to BroadcastReceiver via PendingIntent
我正在尝试使用 PendingIntent 将自定义序列化对象从我的 IntentService 传递到 BroadcastReceiver。
这是我的自定义对象:
Row.java
public class Row implements Serializable {
private String name;
private String address;
public Row(BluetoothDevice device) {
this.name = device.getName();
this.address = device.getAddress();
}
}
这是我的 IntentService
MyIntentService.java
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
protected void onHandleIntent(Intent workIntent) {
AlarmManager alarmMgr;
PendingIntent alarmPendingIntent;
Intent alarmIntent;
// The object "RowsList" is passed from my MainActivity and is correctly received by my IntentService.
// NO PROBLEMS HERE
Row[] arrRows = (Row[])workIntent.getSerializableExtra("RowsList");
Log.i(TAG, "Inside Intent Service...");
int interval = 2;
try{
if(interval != 0) {
alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.putExtra("IntentReason", "Reason"); // THIS GETS PASSED
alarmIntent.putExtra("RowsList", arrRows); // THIS DOES NOT GET PASSED
alarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (interval * 1000), alarmPendingIntent);
}
}
catch (Exception ignored){}
}
}
MainActivity.java
// NO PROBLEMS HERE
private Intent myIntent;
myIntent = new Intent(getApplicationContext(), MyIntentService.class);
Log.i(TAG, "Starting Intent Service...");
myIntent.putExtra("RowsList", arrRows);
getApplicationContext().startService(intentListenBT);
这是我的 BroadcastReceiver:
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
Row[] arrRows;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
String str = intent.getStringExtra("IntentReason"); // RECEIVED AS "Reason"
arrRows = (Row[])intent.getSerializableExtra("RowsList"); // HERE IT IS null
}
}
最烦人的是这段代码之前在我的 Nexus 6P (Lollipop 6.0 API23) 上运行。一旦我将相同的 phone 更新为 Android 7.0(Nougat),它就停止工作了。 Nougat 中是否有任何变化导致此问题?
注意:
我 运行 我的代码在 Nexus 6P 上使用模拟器 API 23,它工作正常。
很可能,您 运行 遇到了与 custom Parcelable
implementations 相同的问题。从那个博客 post 中解释我自己:基本上,如果一个核心 OS 进程需要修改 Intent
额外的,该进程最终会尝试重新创建你的 Serializable
对象作为设置 extras Bundle
进行修改。该进程没有您的 class,因此它会出现运行时异常。
The most annoying part is that this code was working previously on my Nexus 6P (Lollipop 6.0 API23).
行为会因 Android 版本、您使用 PendingIntent
的方式而异,并且可能因 firmware/ROM 而异。不要假设您当前的实施在任何 Android 版本上都是可靠的。
您唯一的选择是不要将 Serializable
直接放在 Intent
extra 中。使用 Serializable
以外的东西(例如,嵌套的 Bundle
),将 Serializable
转换为 byte[]
,等等
This sample app demonstrates the latter approach, applied to a Parcelable
object. The same basic technique 应该适用于 Serializable
。 (向 AyeVeeKay 致敬评论中的 link)。
我正在尝试使用 PendingIntent 将自定义序列化对象从我的 IntentService 传递到 BroadcastReceiver。
这是我的自定义对象:
Row.java
public class Row implements Serializable {
private String name;
private String address;
public Row(BluetoothDevice device) {
this.name = device.getName();
this.address = device.getAddress();
}
}
这是我的 IntentService
MyIntentService.java
public class MyIntentService extends IntentService {
public MyIntentService() {
super("MyIntentService");
}
@Override
public void onCreate() {
super.onCreate();
}
@Override
protected void onHandleIntent(Intent workIntent) {
AlarmManager alarmMgr;
PendingIntent alarmPendingIntent;
Intent alarmIntent;
// The object "RowsList" is passed from my MainActivity and is correctly received by my IntentService.
// NO PROBLEMS HERE
Row[] arrRows = (Row[])workIntent.getSerializableExtra("RowsList");
Log.i(TAG, "Inside Intent Service...");
int interval = 2;
try{
if(interval != 0) {
alarmMgr = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
alarmIntent = new Intent(this, AlarmReceiver.class);
alarmIntent.putExtra("IntentReason", "Reason"); // THIS GETS PASSED
alarmIntent.putExtra("RowsList", arrRows); // THIS DOES NOT GET PASSED
alarmPendingIntent = PendingIntent.getBroadcast(this, 0, alarmIntent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmMgr.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + (interval * 1000), alarmPendingIntent);
}
}
catch (Exception ignored){}
}
}
MainActivity.java
// NO PROBLEMS HERE
private Intent myIntent;
myIntent = new Intent(getApplicationContext(), MyIntentService.class);
Log.i(TAG, "Starting Intent Service...");
myIntent.putExtra("RowsList", arrRows);
getApplicationContext().startService(intentListenBT);
这是我的 BroadcastReceiver:
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
Row[] arrRows;
@Override
public void onReceive(Context context, Intent intent) {
this.context = context;
String str = intent.getStringExtra("IntentReason"); // RECEIVED AS "Reason"
arrRows = (Row[])intent.getSerializableExtra("RowsList"); // HERE IT IS null
}
}
最烦人的是这段代码之前在我的 Nexus 6P (Lollipop 6.0 API23) 上运行。一旦我将相同的 phone 更新为 Android 7.0(Nougat),它就停止工作了。 Nougat 中是否有任何变化导致此问题?
注意:
我 运行 我的代码在 Nexus 6P 上使用模拟器 API 23,它工作正常。
很可能,您 运行 遇到了与 custom Parcelable
implementations 相同的问题。从那个博客 post 中解释我自己:基本上,如果一个核心 OS 进程需要修改 Intent
额外的,该进程最终会尝试重新创建你的 Serializable
对象作为设置 extras Bundle
进行修改。该进程没有您的 class,因此它会出现运行时异常。
The most annoying part is that this code was working previously on my Nexus 6P (Lollipop 6.0 API23).
行为会因 Android 版本、您使用 PendingIntent
的方式而异,并且可能因 firmware/ROM 而异。不要假设您当前的实施在任何 Android 版本上都是可靠的。
您唯一的选择是不要将 Serializable
直接放在 Intent
extra 中。使用 Serializable
以外的东西(例如,嵌套的 Bundle
),将 Serializable
转换为 byte[]
,等等
This sample app demonstrates the latter approach, applied to a Parcelable
object. The same basic technique 应该适用于 Serializable
。 (向 AyeVeeKay 致敬评论中的 link)。