Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/233.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何避免在更改按钮时闪烁通知更新_Android_Notifications_Android Notifications - Fatal编程技术网

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

Android 如何避免在更改按钮时闪烁通知更新,android,notifications,android-notifications,Android,Notifications,Android Notifications,我有一个通知,它支持播放、向前和向后暂停 private static Notification createNotification(String interpret, String title, boolean paused) { // if (builder == null) builder = new NotificationCompat.Builder(context); builder.setPriority(Notification.PRIORITY_MA

我有一个通知,它支持播放、向前和向后暂停

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;
}
更新通知:

 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解决了这个问题。问题是每次你想更新时都会创建新的通知。我也有同样的问题,当我执行以下操作时,问题得到了解决:

  • createNotification
    的不同调用之间保留通知实例
  • 每次从通知栏中删除此实例时,都将其设置为null
  • 执行以下代码:
代码:

现在,当您调用
notify
时,不会出现闪烁:

manager.notify(0, createNotification(interpret, title, paused));
PS:我还面临一个问题,如果我执行
setLatestEventInfo
的话,大小图标都会被弄乱。这就是我这么做的原因:

int tmpIconResourceIdStore = mNotification.icon;
// this is needed to make the line below not change the large icon of the notification
mNotification.icon = 0;
// The below method is deprecated, but is the only way I have found to set the content title and text
mNotification.setLatestEventInfo(context, contentTitle, contentText, contentIntent);
mNotification.icon = tmpIconResourceIdStore;

查看Adnroid ccode此行
mNotification.icon=0禁用图标出错。

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

代码如下:

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
是类中的一个私有字段。

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

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

如何解决这个问题: 为了与低于19的API级别兼容,我的解决方案是使用支持库中的
NotificationCompat

正如其他人所建议的,只要需要通知,我就保留对
NotificationCompat.Builder
的引用。我在通知中使用的操作仅在初始创建
生成器时添加,而那些将根据情况而改变的操作,我还存储在服务的私有成员中。更改后,我重新使用
Builder
对象,并根据需要调整
NotificationCompat.Action
对象。然后我调用
Builder.getNotification()
Builder.build()
方法,具体取决于API级别(由于支持libs,可能没有必要,但我没有检查它。如果我可以忽略它,请写一条注释,这样我就可以改进代码;)

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

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...
}
公共通知createForegroundNotification(TaskProgressBean TaskProgressBean,布尔不确定){
Context=RewardCalculatorApplication.getInstance();
long maxTime=TaskUtils.getMaxTime(taskEntry);
long taskElapsedTime=TaskUtils.calculateActualLapsedTime(taskProgressBean);
long PauseeReleasedTime=taskProgressBean.getPauseeReleasedTime();
int PAUSETOGLEACTIONIONCON;
int pauseToggleActionText;
悬而未决的暂停切换PI;
布尔pauseButton=pauseereleasedtime==0;
如果(暂停按钮){
PauseTogleActionIcon=R.drawable.ic\u stat\u av\u pause;
pauseToggleActionText=R.string.btnTaskPause;
PauseTogleActionPi=GetPendingEntertServicePause(上下文);
}否则{
PauseTogleActionIcon=R.drawable.ic\u stat\u av\u play\u arrow;
pauseToggleActionText=R.string.btnTaskContinue;
pauseToggleActionPI=GetPendingEntertServiceUnpuse(上下文);
}
String contentText=context.getString(R.String.taskForegroundNotificationText,
TaskUtils.formatTimeForDisplay(taskElapsedTime),
TaskUtils.FormatTimeOrdSplay(PauseeFassedTime),
TaskUtils.formatTimeForDisplay(taskProgressBean.getPauseTtal());
//检查我们是否有建筑商。。。
布尔createNotification=foregroundNotificationBuilder==null;
if(createNotification){//创建一个
foregroundNotificationBuilder=新的NotificationCompat.Builder(上下文);
//设置永不更改的数据…加上pauseAction,因为我们不会更改
//pauseAction对象,只有它的数据。。。
pauseAction=新的NotificationCompat.Action(PauseTogleActionCon、getString(PauseTogleActionText)、PauseTogleActionPi);
foregroundNotificationBuilder
.setContentTitle(taskEntry.getName())
.setSmallIcon(R.drawable.ic_启动器)
.setContentIntent(GetPendingEntertActivity(上下文))
.正在进行(正确)
.addAction(R.drawable.ic_stat_action_done,getString(R.string.btnTaskFinish),getPendingEntertServiceFinish(上下文))
.addAction(暂停反应);
}
//这会随着每次更新而改变
setContentText(contentText);
如果(不确定){
setProgress(0,0,true);
}否则{
setProgress((int)maxTime,(int)taskElapsedTime,false);
}
//如果这不是创建,但按钮已更改,请更改pauseAction的数据。。。
如果(!createNotification&&(pauseButton!=foregroundNotificationPauseButton)){
foregroundNotificationPauseButton=pauseButton;
pauseAction.icon=pauseToggleActionIcon;
pauseAction.title=getString(PauseToggleeActionText);
pauseAction.actionIntent=PauseToggleeActionPi;
}
返回(Build.VERSION.SDK\u INTpublic 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...
}