Android 通知重建而不是更新?

Android notification rebuilds instead of updating?

我正在下载一个文件,我想让用户了解进度所以我创建了一个 notification.The 问题是通知不断重建而不是更新。我在网上搜索了类似的行为,并按照他们说的做了,但我的问题仍然存在。

每个人都说要使用通知生成器,所以它第一次生成整个通知,然后只更新我告诉它的内容to.Tried,它仍然无法正常工作。

我在这里声明通知和 notificationManager。

private NotificationCompat.Builder notification;
private NotificationManager notificationManager;

这是创建 notification.DOWNLOAD_NOTIFICATION_ID 是一个值为 2

的最终 int 的方法
private void createDownloadNotification(){

        notificationManager = (NotificationManager) getSystemService(GuideSelected.this.NOTIFICATION_SERVICE);

            notification = new NotificationCompat.Builder(GuideSelected.this,CHANNEL_DOWNLOAD)
                    .setSmallIcon(android.R.drawable.stat_sys_download)  // here is the animated icon
                    .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), android.R.drawable.stat_sys_download))
                    .setContentTitle("title")
                    .setContentText("Download starting...")
                    .setStyle(new NotificationCompat.BigTextStyle())

                    //.setContentIntent(pendingIntent)
                    //la notifica si cancella da sola dopo che clicco
                    .setOngoing(true)
                    .setPriority(NotificationCompat.PRIORITY_LOW)
                    .setProgress(100,0,false);
            notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,notification.build());
        }
}

这是我更新通知的异步任务

private class DownloadFile extends AsyncTask<String, String, String> {
        final Handler handler = new Handler();

        @Override
        protected void onPreExecute() {
            super.onPreExecute();

        }

        @Override
        protected String doInBackground(String... f_url) {
            int count;
           // HERE I'M CREATING THE NOTIFICATION
                createDownloadNotification();

        //DOWNLOADING STUFF....

        }

        // Updating progress bar

        protected void onProgressUpdate(String... progress) {

            // UPDATING IT EVERY 5% SO I DON't MAKE TOO MANY CALLS

            currentPercentage=Integer.parseInt(progress[0]);

                if (previousPercentage != currentPercentage && currentPercentage%5==0) {// line : 6
                    notification.setProgress(100,previousPercentage, false).setContentText(previousPercentage+"%").setSubText("Downloading...");
                    notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notification.build());
                    previousPercentage=currentPercentage;
                }

        }


        @Override
        protected void onPostExecute(String message) {

            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    notification.setProgress(0,0,false).setOngoing(false).setContentText("Download complete").setSubText(null);
                    notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notification.build());
                }
            }, 2000);


        }
    }

我只想更新通知而不是每次都重建,我可以看到它从动画下载图标重建,因为它一直在重新启动。

编辑: 添加了通知和通知管理器的声明。

https://developer.android.com/training/notify-user/build-notification#Updating

To update this notification after you've issued it, call NotificationManagerCompat.notify() again, passing it a notification with the same ID you used previously. If the previous notification has been dismissed, a new notification is created instead.

You can optionally call setOnlyAlertOnce() so your notification interupts the user (with sound, vibration, or visual clues) only the first time the notification appears and not for later updates.

        notification = new NotificationCompat.Builder(GuideSelected.this,CHANNEL_DOWNLOAD)
                .setSmallIcon(android.R.drawable.stat_sys_download)  // here is the animated icon
                .setContentTitle("title")
                .setContentText("Download starting...")
                .setPriority(NotificationCompat.PRIORITY_LOW);
        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notification.build());

应该继续更新相同的通知,一旦你有这个工作,我会添加回你在构建器上的其他设置(比如 bigIcon 等,看看添加其中一个是否会破坏它。 )

在你的Activity

private NotificationCompat.Builder notification;
    private NotificationManager notificationManager;

    int DOWNLOAD_NOTIFICATION_ID = 232;
 private void createDownloadNotification(){


        notificationManager = (NotificationManager) getSystemService(MainActivity.this.NOTIFICATION_SERVICE);

        notification = new NotificationCompat.Builder(MainActivity.this,"download")
                .setSmallIcon(android.R.drawable.stat_sys_download)  // here is the animated icon
                .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), android.R.drawable.stat_sys_download))
                .setContentTitle("title")
                .setContentText("Download starting...")
                .setStyle(new NotificationCompat.BigTextStyle())

                //.setContentIntent(pendingIntent)
                //la notifica si cancella da sola dopo che clicco
                .setOngoing(true)
                .setPriority(NotificationCompat.PRIORITY_LOW)
                .setProgress(100,0,false);
        notificationManager.notify(DOWNLOAD_NOTIFICATION_ID,notification.build());
    }

现在在您的 AsyncTask 中像

一样使用它
  class DownloadFile extends AsyncTask<String, String, String>
{
    final Handler handler = new Handler();
    int currentPercentage;
    int previousPercentage;
    @Override
    protected void onPreExecute()
    {
        super.onPreExecute();
        createDownloadNotification();
    }
    @Override
    protected String doInBackground(String... f_url)
    {
        // Dummy code for notificaion progress you can change it with download file logic.
        for (int i = 0; i < 100; i++)
        {
            try
            {
                Thread.sleep(50);
                publishProgress(i + ""); //publish the progress to update the progress of Notification.
            } catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        return "";
    }
    protected void onProgressUpdate(String... progress)
    {
        // UPDATING IT EVERY 5% SO I DON't MAKE TOO MANY CALLS
        currentPercentage = Integer.parseInt(progress[0]);

        if (previousPercentage != currentPercentage && currentPercentage % 5 == 0)
        {// line : 6
            notification.setProgress(100, previousPercentage, false).setContentText(previousPercentage + "%").setSubText("Downloading...");
            notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notification.build());
            previousPercentage = currentPercentage;
        }

    }
    @Override
    protected void onPostExecute(String message)
    {
        handler.postDelayed(new Runnable()
        {
            @Override
            public void run()
            {
                notification.setSmallIcon(android.R.drawable.stat_sys_download_done); //update the icon 
                notification.setProgress(0, 0, false).setOngoing(false).setContentText("Download complete").setSubText(null);
                notificationManager.notify(DOWNLOAD_NOTIFICATION_ID, notification.build());
            }
        }, 2000);
    }
}

PreExecute 方法中创建通知,然后在 onBackGround 方法中发布进度。

希望这会解决您的问题

最后我通过使用扩展 IntentService 的自定义下载意图服务 class 解决了这个问题,当我更新通知时我正在控制最后的 % 是否与当前的不同一个(因为 updateProgress 在一秒钟内被多次调用)并且我还添加了一个计时器所以它每 1.3 秒更新一次(这是下载图标动画完成所需的时间)这样我终于实现了我的目标并且通知不会持续重建。

这是我更新通知的方式:



   while ((count = input.read(data)) != -1) {
                if (Constants.stopService) {
                    output.flush();
                    output.close();
                    input.close();
                    stopSelf();
                    return;
                }
                if (count != 0) {
                    total += count;

                    latestPercentDone = (int) Math.round(total / lengthOfFile * 100.0);
                    if (percentDone != latestPercentDone) {
                        percentDone = latestPercentDone;
                        if (SystemClock.elapsedRealtime() - mLastClickTime > 1300) { // 1000 = 1second
                            mLastClickTime = SystemClock.elapsedRealtime();
                            sendMessage(percentDone, idLesson);
                            notification.setProgress(100, percentDone, false);
                            notificationManager.notify(realNotificationID, notification.build());
                        }
                    }
                    output.write(data, 0, count);
                }
            }
            // flushing output
            output.flush();
            // closing streams
            output.close();
            input.close();