问题
I'm downloading a file and i want to keep the user informed about the progress so i created a notification.The problem is that the notification keeps getting rebuild instead of updating. I searched for similar behaviours online and i did as they said but my problem persists.
Everybody is saying to use a notification builder so the first time it builds the whole notification and then only updates what i tell it to.Tried it,still not working.
Here i'm declaring the notification and the notificationManager.
private NotificationCompat.Builder notification;
private NotificationManager notificationManager;
This is the method that creates the notification.DOWNLOAD_NOTIFICATION_ID is a final int with value 2
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());
}
}
This is the asynctask where i'm updating the notification
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);
}
}
I just want the notification to update without rebuilding everytime, i can see it rebuilds from the animated download icon because it keeps restarting.
EDIT: Added the declaration of notification and notification manager.
回答1:
In your 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());
}
now in your AsyncTask use it like
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);
}
}
Create you notification in PreExecute
method, then in onBackGround
Method just publish the progress.
Hope this will fix your issue
回答2:
In the end i solved it by using custom download intent service class which extends IntentService and when i'm updating the notification i'm controlling if the last % is different than the current one (since the updateProgress is called multiple times in a second) and i also added a timer so it only updates every 1.3 seconds (this is the time that the download icon aniamtion takes to complete) and in this way i finally achieved my goal and the notification doesn't continuously rebuild.
Here is how i'm updating the notification:
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();
回答3:
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());
Should work to keep updating the same notification, once you have this working, I would then add back the other settings you had on the builder (such a bigIcon etc, too see if adding one of those is breaking it.)
来源:https://stackoverflow.com/questions/57169517/android-notification-rebuilds-instead-of-updating