У меня есть Intent Service, называемая ParserService, которая выполняет какую-то задачу и создает объект (ArtistInfo), который можно обработать.Затем он проверяет, находится ли приложение на переднем плане.Если это так, то он отправляет широковещательную рассылку с объектом parcelable в дополнительных функциях.Эта широковещательная передача принимается действием MainActivity.java, которое затем создает намерение с тем же объектом и запускает действие с именем ListSongsActivity, где удачно получаемый объект может быть получен.
Но если приложение не на переднем плане, то ParserServiceотправляет уведомление, которое имеет то же намерение, что и трансляция.Но когда ListSongsActivity запускается через уведомление, объект, подлежащий обработке (ArtistInfo), на этот раз равен нулю.И я также передаю строку в намерении.Эта строка корректно принимается через намерение уведомления, но объект пакета не имеет значения.
Ниже приведены соответствующие фрагменты кода.
Код трансляции и уведомления от ParserService:
if (CommonUtils.appInForeground(getApplicationContext())) {
Log.d(TAG, "onHandleIntent(): Sending success broadcast.");
sendBroadcast(createSuccessIntent(artistInfo));
} else {
// TODO: 10-10-2018 tapping on notification does nothing!!
Log.d(TAG, "onHandleIntent(): Sending success notification.");
String body = "Parsing complete for the url: " + url;
Intent notifyIntent = new Intent(getApplicationContext(), ListSongsActivity.class);
notifyIntent.putExtra(Constants.MUSIC_SITE, siteName);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.PARSED_ARTIST_INFO, artistInfo);
intent.putExtras(bundle);
CommonUtils.sendNotification(getApplicationContext(), Constants.LIST_SONGS_NOTIFICATION_TITLE
, body, Constants.LIST_SONGS_NOTIFICATION_CHANNEL_ID, notifyIntent,
Constants.LIST_SONGS_NOTIFICATION_ID, R.drawable.ic_launcher_background);
}
private Intent createSuccessIntent(ArtistInfo artistInfo) {
Intent intent = new Intent();
intent.setAction(Constants.PARSE_SUCCESS_ACTION_KEY);
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.PARSE_SUCCESS_MESSAGE_KEY, artistInfo);
intent.putExtras(bundle);
return intent;
}
Broadcast, полученный во фрагменте MainActivity:
private class ParserBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "ParserBroadcastReceiver, onReceive()");
String parseResult = intent.getAction();
if (parseResult == null || parseResult.equals(Constants.EMPTY_STRING)) {
return;
}
switch (parseResult) {
case Constants.PARSE_SUCCESS_ACTION_KEY:
ArtistInfo artistInfo = intent.getParcelableExtra(Constants.PARSE_SUCCESS_MESSAGE_KEY);
Log.d(TAG, "ParserBroadcastReceiver, onReceive() PARSE_SUCCESS_ACTION_KEY, artistInfo: "
+ artistInfo.toString());
Log.d(TAG, "site: " + musicSite);
createIntentAndDelegateActivity(artistInfo);
break;
default:
break;
}
}
}
private void createIntentAndDelegateActivity(ArtistInfo artistInfo) {
Log.d(TAG, "createIntentAndDelegateActivity()");
Intent intent = new Intent(getContext(), ListSongsActivity.class);
intent.putExtra(Constants.MUSIC_SITE, musicSite);
Bundle bundle = new Bundle();
bundle.putParcelable(Constants.PARSED_ARTIST_INFO, artistInfo);
intent.putExtras(bundle);
startActivity(intent);
}
sendNotification в CommonUtils:
public static void sendNotification(Context context, String title, String body,
String channelId, Intent intent, Integer id, Integer iconResourceId) {
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager == null) {
Log.d(TAG, "sendNotification(): noti manager null!!");
return;
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(channelId,
Constants.DEFAULT_NOTIFICATION_CHANNEL_NAME,
NotificationManager.IMPORTANCE_DEFAULT);
channel.setDescription(Constants.DEFAULT_NOTIFICATION_CHANNEL_DESCRIPTION);
notificationManager.createNotificationChannel(channel);
}
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
stackBuilder.addNextIntentWithParentStack(intent);
PendingIntent pendingIntent1 = stackBuilder.getPendingIntent(Constants.PENDING_INTENT_DEFAULT_REQ_CODE,
PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, channelId);
builder.setContentTitle(title);
builder.setContentText(body);
builder.setSmallIcon(iconResourceId);
builder.setContentIntent(pendingIntent1);
Notification notification = builder.build();
// Play default notification sound
notification.defaults |= Notification.DEFAULT_SOUND;
// Vibrate if vibrate is enabled
notification.defaults |= Notification.DEFAULT_VIBRATE;
NotificationManagerCompat.from(context).notify(id, notification);
}
Вот как я получаюIntentExtras в ListSongsActivity:
private void getIntentExtras() {
Log.d(TAG, "getIntentExtras()");
Intent intent = getIntent();
parsedArtistInfo = intent.getParcelableExtra(Constants.PARSED_ARTIST_INFO);
String siteName = intent.getStringExtra(Constants.MUSIC_SITE);
Log.d(TAG, "getIntentExtras() sitename: " + siteName);
musicSite = Enum.valueOf(MusicSite.class, siteName);
Log.d(TAG, "getIntentExtras() artInfo: " + parsedArtistInfo.toString());
}
Когда ListSongsActivity запускается получателем широковещательной рассылки, объект parsedArtistInfo является правильным объектом, переданным ParserService, но когда ListSongsActivity открывается посредством уведомления, объект parsedArtistInfo имеет значение null.
Класс ArtistInfo:
public class ArtistInfo implements Parcelable {
private static final String TAG = ArtistInfo.class.getSimpleName();
private String url;
private String artist;
// album name to list of ids of songs
private HashMap<String, List<Integer>> albumInfo;
// song id to songInfo
private SparseArray<SongInfo> songsMap;
/**
* to be used only for ui display logic, don't use for downloading logic
*/
private HashMap<String, Boolean> albumCheckedStatus;
public ArtistInfo() {
}
private ArtistInfo(Parcel in) {
url = in.readString();
artist = in.readString();
// Read album info
getAlbumInfo();
int albumInfoSize = in.readInt();
for (int i = 0; i < albumInfoSize; i++) {
String key = in.readString();
List<Integer> value = new ArrayList<>();
in.readList(value, null);
albumInfo.put(key, value);
}
// Read songs map
getSongsMap();
int songsMapSize = in.readInt();
for (int i = 0; i < songsMapSize; i++) {
int key = in.readInt();
SongInfo value = in.readParcelable(SongInfo.class.getClassLoader());
songsMap.put(key, value);
}
getAlbumCheckedStatus();
int albumCheckStatusSize = in.readInt();
for (int i = 0; i < albumCheckStatusSize; i++) {
String key = in.readString();
Boolean value = in.readByte() != 0;
albumCheckedStatus.put(key, value);
}
}
public static final Creator<ArtistInfo> CREATOR = new Creator<ArtistInfo>() {
@Override
public ArtistInfo createFromParcel(Parcel in) {
return new ArtistInfo(in);
}
@Override
public ArtistInfo[] newArray(int size) {
return new ArtistInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(url);
dest.writeString(artist);
// Write album info
getAlbumInfo();
dest.writeInt(albumInfo.size());
for (Map.Entry<String, List<Integer>> item : albumInfo.entrySet()) {
dest.writeString(item.getKey());
dest.writeList(item.getValue());
}
// Write song map
getSongsMap();
dest.writeInt(songsMap.size());
for (int i = 0; i < songsMap.size(); i++) {
int key = songsMap.keyAt(i);
dest.writeInt(key);
dest.writeParcelable(songsMap.get(key), flags);
}
getAlbumCheckedStatus();
dest.writeInt(albumCheckedStatus.size());
for (Map.Entry<String, Boolean> item : albumCheckedStatus.entrySet()) {
dest.writeString(item.getKey());
dest.writeByte((byte) (item.getValue() ? 1 : 0));
}
}
Может кто-нибудь указать на ошибку, которую я совершаю при отправке объекта через уведомление.Спасибо!