android memory leak in notification service

2019-02-03 06:48发布

问题:

I have a service which creates a notification and then updates it with certain information periodically. After about 12 mins or so the phone crashes and reboots, I believe it is caused by a memory leak in the following code to do with how I am updating the notification, could someone please check/advise me if this is the case and what I am doing wrong.

onCreate:

mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

createNotification:

private void createNotification() {
  Intent contentIntent = new Intent(this,MainScreen.class);
  contentIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);
  PendingIntent appIntent =PendingIntent.getActivity(this,0, contentIntent, 0);

  contentView = new RemoteViews(getPackageName(), R.layout.notification);
  contentView.setImageViewResource(R.id.image, R.drawable.icon);
  contentView.setTextViewText(R.id.text, "");

  notification = new Notification();
  notification.when=System.currentTimeMillis();
  notification.contentView = contentView;
  notification.contentIntent = appIntent;
}

updateNotification:

private void updateNotification(String text){
  contentView.setTextViewText(R.id.text, text);
  mNotificationManager.notify(0, notification);
}

Thanks in advance.

回答1:

I stumbled upon the same problem. Looks like that if you don't "cache" the RemoteView and Notification in the service, but re-create them from scratch in the "update" routine this problem disappears. Yes, I know it is not efficient, but at least the phone does not reboot from out of memory errors.



回答2:

I had the very same problem. My solution is close to the one that @haimg said, but I do cache the notification (just the RemoteView is recreated). By doing so, the notification won't flash again if you are looking at it.

Example:

public void createNotification(Context context){
    Notification.Builder builder = new Notification.Builder(context);

    // Set notification stuff...

    // Build the notification
    notification = builder.build();
}

public void updateNotification(){
    notification.bigContentView = getBigContentView();
    notification.contentView = getCompactContentView();

    mNM.notify(NOTIFICATION_ID, notification);
}

And in the methods getBigContentView and getCompactContentView I return a new RemoteViews with the updated layout.