【问题标题】:Calling setProgress(0, 0, true) does not update Notification on > API 19调用 setProgress(0, 0, true) 不会更新 > API 19 上的通知
【发布时间】:2018-01-19 08:09:39
【问题描述】:

更新:

在进行了更多调试后,我发现了我的通知没有更新的原因:下载完成后调用setProgress(0, 0, false)。由于某种原因,当在notify() 之前调用此方法时,即将进行的更新实际上并没有通过。添加 NotificationChannel 没有任何作用。

我目前的解决方法是致电setProgress(100, 100, false),以便用户知道下载已完成并随后会得到更新。

原问题:

我有一个自定义文件下载实用程序,它会在下载文件时创建通知。此通知会随着下载的进行而更新。 但是,我在 19 以上的 API 级别上得到了一些奇怪的结果。下载完成后,NotificationManager 不会更新通知以通知用户。奇怪的是,只要下载进行,通知就会更新。 此外,当我激活调试器时,下载完成时通知会更新。这让我相信这里正在发生某种竞争状况,但我似乎无法真正找出在哪里或如何。

我的 FileDownloader 类:

public static void startGetRequestDownload(final Context context,
                                           String fileUrl,
                                           @Nullable String fileName,
                                           @Nullable Header[] headers,
                                           @Nullable RequestParams requestParams,
                                           final boolean showProgressNotification){

    final int notificationID = 0;
    final NotificationManager mNotifyManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
    if(mNotifyManager == null) {
        Log.e(TAG, "Failed to get NotificationManager service");
        return;
    }
    final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context);
    String notificationTitle = context.getString(R.string.default_filename);
    if(fileName != null && !fileName.isEmpty()){
        notificationTitle = fileName;
    }
    mBuilder.setContentTitle(notificationTitle)
            .setContentText(context.getString(R.string.download_in_progress))
            .setColor(ContextCompat.getColor(context, R.color.app_color_accent))
            .setSmallIcon(R.drawable.ic_elab);

    String uuid = "Temp_" + System.currentTimeMillis();
    final File tempFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString(), uuid);
    // Temporarily disable SSL as workaround.
    RestClient.getClient().setSSLSocketFactory(MySSLSocketFactory.getFixedSocketFactory());
    RestClient.getClient().get(context, fileUrl, headers, requestParams, new FileAsyncHttpResponseHandler(tempFile) {

        @Override
        public void onStart() {
            super.onStart();
            if(showProgressNotification){
                mBuilder.setProgress(100, 0, false);
                mNotifyManager.notify(notificationID, mBuilder.build());
            }
        }

        @Override
        public void onProgress(long bytesWritten, long totalSize) {
            super.onProgress(bytesWritten, totalSize);
            if(showProgressNotification){
                int progress = (int) (bytesWritten / totalSize * 100);
                mBuilder.setProgress(100, progress, false);
                mNotifyManager.notify(notificationID, mBuilder.build());
            }
        }

        @Override
        public void onFailure(int statusCode, Header[] headers, Throwable throwable, File file) {
            if(showProgressNotification){
                mBuilder.setContentText(context.getString(R.string.download_failed));
                mBuilder.setProgress(0,0,false);
                mNotifyManager.notify(notificationID, mBuilder.build());
            }
            Log.w(TAG, "File download failed", throwable);
        }

        @Override
        public void onSuccess(int statusCode, Header[] headers, File file) {
            FileMetaData metaData = validateResponse(headers);
            if(metaData != null){
                final File downloadDirectory = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
                File newFile = new File(downloadDirectory, metaData.fileName);
                if(file.renameTo(newFile)){
                    Uri fileUri = FileProvider.getUriForFile(context, context.getApplicationContext().getPackageName() + ".fileprovider", newFile);
                    Intent actionViewIntent = new Intent(Intent.ACTION_VIEW);
                    actionViewIntent.setDataAndType(fileUri, metaData.contentType);
                    actionViewIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);

                    if(showProgressNotification){
                        PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, actionViewIntent, PendingIntent.FLAG_ONE_SHOT);
                        mBuilder.setProgress(0,0,false);
                        mBuilder.setContentText(context.getString(R.string.download_completed));
                        mBuilder.setContentIntent(pendingIntent);
                        mBuilder.setSmallIcon(android.R.drawable.stat_sys_download_done);
                        mNotifyManager.notify(notificationID, mBuilder.build());
                    }
                    return;
                }
            }

            //Failover
            if(showProgressNotification){
                mBuilder.setContentText(context.getString(R.string.download_failed));
                mNotifyManager.notify(notificationID, mBuilder.build());
            }
        }
    });
}

【问题讨论】:

  • @notTidar 添加通知频道似乎没有帮助。我仍然得到相同的结果:通知更新一次以指示下载正在进行中,完成后发送更新,但它似乎并没有真正更新通知。
  • 使用标志更新当前,

标签: android android-notifications


【解决方案1】:

我找到了通知未更新的真正原因。 Android 文档在通知更新方面提到了以下内容:

注意:系统对更新通知应用速率限制。如果您过于频繁地发布通知更新,系统可能会丢弃一些通知。

每次下载进行时我都会打电话给notify()。显然,下载进度方法被频繁调用,导致多个通知被阻止。但是,我只看到最后一个通知被丢弃:下载完成通知。

onProgress() 中限制对notify() 的调用数量解决了我的问题。

【讨论】:

  • 你如何限制调用 notify() 的次数?
  • @KrupaKakkad 通过定义在再次调用notify() 之前必须完成的最小进度。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-13
  • 1970-01-01
  • 2017-09-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多