首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >如何在更改按钮时避免闪烁通知更新

如何在更改按钮时避免闪烁通知更新
EN

Stack Overflow用户
提问于 2013-09-26 17:55:24
回答 2查看 6.2K关注 0票数 28

我有一个通知,它支持播放,暂停前进和后退。

代码语言:javascript
复制
private static Notification createNotification(String interpret, String title, boolean paused) {
//  if (builder == null)
       builder = new NotificationCompat.Builder(context);

    builder.setPriority(Notification.PRIORITY_MAX);
    builder.setAutoCancel(false);
    builder.setContentTitle(title);
    builder.setContentText(interpret);
    builder.setOngoing(true);
    builder.setOnlyAlertOnce(true);
    builder.setSmallIcon(R.drawable.ic_launcher);
    builder.setContentIntent(PendingIntent.getActivity(context, 9, new Intent(context, ApplicationActivity.class), Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT));
    builder.addAction(R.drawable.av_previous, "", PendingIntent.getBroadcast(context.getApplicationContext(), 0, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PREVIOUS), PendingIntent.FLAG_CANCEL_CURRENT));

    if (paused)
        builder.addAction(R.drawable.av_play, "", PendingIntent.getBroadcast(context.getApplicationContext(), 2, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PLAY), PendingIntent.FLAG_CANCEL_CURRENT));
    else
        builder.addAction(R.drawable.av_pause, "", PendingIntent.getBroadcast(context.getApplicationContext(), 3, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.PAUSE), PendingIntent.FLAG_CANCEL_CURRENT));

    builder.addAction(R.drawable.av_next, "", PendingIntent.getBroadcast(context.getApplicationContext(), 1, new Intent(NotificationPlayerControlReceiver.MUSIC_PLAYER_INTENT).putExtra("resultcode", NotificationPlayerControlReceiver.NEXT), PendingIntent.FLAG_CANCEL_CURRENT));

    Notification notification = builder.build();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
        notification.tickerView = null;

    return notification;
}

更新通知:

代码语言:javascript
复制
 public static void update(String interpret, String title, boolean paused) {
    NotificationManager manager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    manager.notify(0, createNotification(interpret, title, paused));
}

为了避免在更新时闪烁,我将构建器设置为一个全局变量,并在每次更新时重用它,这很有效。但是重用它,意味着我添加的所有按钮都会被重用,并且不可能删除我之前添加的操作。

只有当我在每次更新时重新初始化NotificationCompat.Builder时,按钮更改才有效,这意味着我再次闪烁。

我如何避免闪烁,但让按钮改变?

编辑:刚刚检查了Rocket Player,他们没有解决这个问题,但是Google Play Music解决了这个问题

EN

回答 2

Stack Overflow用户

发布于 2014-11-22 04:09:01

正如Boris所说,问题是每次更新都会生成一个新的通知。我的解决方案涵盖了相同的逻辑,但我使用NotificationBuilder...

代码如下:

代码语言:javascript
复制
if (mNotificationBuilder == null) {
            mNotificationBuilder = new NotificationCompat.Builder(this)
                    .setSmallIcon(iconId)
                    .setContentTitle(title)
                    .setContentText(message)
                    .setLargeIcon(largeIcon)
                    .setOngoing(true)
                    .setAutoCancel(false);
        } else {
            mNotificationBuilder.setContentTitle(title)
                    .setContentText(message);
        }

请记住,mNotificationBuilder是类中的私有字段。

票数 17
EN

Stack Overflow用户

发布于 2015-05-02 21:40:56

我知道这是一个相当古老的问题,但由于我在其他地方找不到解决方案,我认为现在回答这个问题可能会对其他有同样问题的人有所帮助。

这个问题一开始就有点棘手。我今天也遇到了这个问题,作为一个固执的自己,我在寻找和尝试了一段时间后,找到了一个解决方案。

如何解决这个问题:

为了与低于19级的API兼容,我的解决方案是使用支持库中的NotificationCompat类。

正如其他人所建议的那样,只要需要通知,我就会保留对NotificationCompat.Builder的引用。我在通知中使用的操作仅在初始创建Builder时添加,这些操作将根据情况而更改,我也会将其存储在服务的私有成员中。更改后,我重用Builder对象,并根据需要调整NotificationCompat.Action对象。然后,我根据API级别调用Builder.getNotification()Builder.build()方法(由于support-libs的原因,可能不是必需的,但我没有检查这一点。如果我可以省略这一点,请写一条评论,这样我就可以改进我的代码;)

下面是我刚才描述的示例代码:

代码语言:javascript
复制
public Notification createForegroundNotification(TaskProgressBean taskProgressBean, boolean indeterminate) {
  Context context = RewardCalculatorApplication.getInstance();

  long maxTime = TaskUtils.getMaxTime(taskEntry);
  long taskElapsedTime = TaskUtils.calculateActualElapsedTime(taskProgressBean);
  long pauseElapsedTime = taskProgressBean.getPauseElapsedTime();

  int pauseToggleActionIcon;
  int pauseToggleActionText;
  PendingIntent pauseToggleActionPI;
  boolean pauseButton = pauseElapsedTime == 0;
  if(pauseButton) {
    pauseToggleActionIcon = R.drawable.ic_stat_av_pause;
    pauseToggleActionText = R.string.btnTaskPause;
    pauseToggleActionPI = getPendingIntentServicePause(context);
  } else {
    pauseToggleActionIcon = R.drawable.ic_stat_av_play_arrow;
    pauseToggleActionText = R.string.btnTaskContinue;
    pauseToggleActionPI = getPendingIntentServiceUnpause(context);
  }

  String contentText = context.getString(R.string.taskForegroundNotificationText,
      TaskUtils.formatTimeForDisplay(taskElapsedTime),
      TaskUtils.formatTimeForDisplay(pauseElapsedTime),
      TaskUtils.formatTimeForDisplay(taskProgressBean.getPauseTotal()));


  // check if we have a builder or not...
  boolean createNotification = foregroundNotificationBuilder == null;
  if(createNotification) { // create one
    foregroundNotificationBuilder = new NotificationCompat.Builder(context);

    // set the data that never changes...plus the pauseAction, because we don't change the
    // pauseAction-object, only it's data...
    pauseAction = new NotificationCompat.Action(pauseToggleActionIcon, getString(pauseToggleActionText), pauseToggleActionPI);
    foregroundNotificationBuilder
        .setContentTitle(taskEntry.getName())
        .setSmallIcon(R.drawable.ic_launcher)
        .setContentIntent(getPendingIntentActivity(context))
        .setOngoing(true)
        .addAction(R.drawable.ic_stat_action_done, getString(R.string.btnTaskFinish), getPendingIntentServiceFinish(context))
        .addAction(pauseAction);
  }

  // this changes with every update
  foregroundNotificationBuilder.setContentText(contentText);

  if(indeterminate) {
    foregroundNotificationBuilder.setProgress(0, 0, true);
  } else {
    foregroundNotificationBuilder.setProgress((int) maxTime, (int) taskElapsedTime, false);
  }

  // if this is not the creation but the button has changed, change the pauseAction's data...
  if(!createNotification && (pauseButton != foregroundNotificationPauseButton)) {
    foregroundNotificationPauseButton = pauseButton;
    pauseAction.icon = pauseToggleActionIcon;
    pauseAction.title = getString(pauseToggleActionText);
    pauseAction.actionIntent = pauseToggleActionPI;
  }

  return (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
         ? foregroundNotificationBuilder.getNotification() // before jelly bean...
         : foregroundNotificationBuilder.build(); // since jelly bean...
}

变量foregroundNotificationBuilderpauseActionforegroundNotificationPauseButton是服务类的私有成员。getPendingIntent...()方法是简单地创建PendingIntent对象的方便方法。

然后,当我需要使用NotificationManager更新通知时,将调用此方法,并将其移交给服务的startForeground()方法。这解决了通知中的闪烁和不可更新操作的问题。

票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19025056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档