Android自定义下载通知如何添加暂停与取消按钮
给DownloadManager自定义通知添加暂停/取消按钮的解决方案
首先得先给你提个关键限制:Android系统自带的DownloadManager没有提供暂停下载的API,它只支持取消下载。如果你的需求里必须要有暂停功能,那你得放弃用DownloadManager,改用自定义的下载实现(比如基于OkHttp/Retrofit构建带断点续传的下载服务)。如果只是需要取消按钮,那可以结合自定义通知+BroadcastReceiver来实现。下面分两种情况说明:
一、只添加取消按钮(基于DownloadManager)
步骤1:创建接收取消操作的BroadcastReceiver
先写一个广播接收器,用来处理用户点击取消按钮的事件:
public class DownloadActionReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if ("ACTION_CANCEL_DOWNLOAD".equals(action)) { long downloadId = intent.getLongExtra("DOWNLOAD_ID", -1); if (downloadId != -1) { DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); downloadManager.remove(downloadId); // 取消通知 NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.cancel((int) downloadId); } } } }
记得在AndroidManifest.xml里注册这个接收器:
<receiver android:name=".DownloadActionReceiver" />
步骤2:构建自定义通知并添加取消按钮
修改你原来的DownloadManager请求,先隐藏系统默认的通知,然后自己构建带取消按钮的自定义通知:
if (!downloadUrl.toString().isEmpty()) { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downloadUrl)); request.setMimeType("audio/MP3"); request.setTitle(vMeta.getTitle()); request.allowScanningByMediaScanner(); // 隐藏系统默认的下载通知 request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN); // 获取DownloadManager并发起下载 DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); long downloadId = downloadManager.enqueue(request); // 创建取消按钮的PendingIntent Intent cancelIntent = new Intent(this, DownloadActionReceiver.class); cancelIntent.setAction("ACTION_CANCEL_DOWNLOAD"); cancelIntent.putExtra("DOWNLOAD_ID", downloadId); PendingIntent cancelPendingIntent = PendingIntent.getBroadcast( this, (int) downloadId, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 构建自定义通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "YOUR_DOWNLOAD_CHANNEL_ID") .setSmallIcon(R.drawable.ic_download) .setContentTitle(vMeta.getTitle()) .setContentText("正在下载...") .setPriority(NotificationCompat.PRIORITY_LOW) // 添加取消按钮 .addAction(R.drawable.ic_cancel, "取消", cancelPendingIntent); // 显示通知(如果是在Service里,建议用startForeground;如果是Activity,直接用NotificationManager) NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.notify((int) downloadId, builder.build()); }
注意:Android 8.0+必须创建通知渠道,你可以在App启动时初始化:
private void createDownloadNotificationChannel() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { CharSequence name = "下载通知"; String description = "显示MP3下载进度和操作按钮"; int importance = NotificationManager.IMPORTANCE_LOW; NotificationChannel channel = new NotificationChannel("YOUR_DOWNLOAD_CHANNEL_ID", name, importance); channel.setDescription(description); NotificationManager notificationManager = getSystemService(NotificationManager.class); notificationManager.createNotificationChannel(channel); } }
二、需要暂停+取消按钮(放弃DownloadManager,自定义下载)
因为DownloadManager不支持暂停,所以要实现这个功能,得自己写下载逻辑。这里给你一个简化的思路:
- 用OkHttp实现带断点续传的下载,通过
Range请求头支持断点。 - 用前台Service托管下载任务,确保后台持续运行并显示自定义通知。
- 在Service里维护下载任务的状态(运行/暂停),点击通知按钮时触发对应的操作。
核心代码片段(Service里的逻辑)
// 暂停下载的PendingIntent Intent pauseIntent = new Intent(this, DownloadService.class); pauseIntent.setAction("ACTION_PAUSE_DOWNLOAD"); pauseIntent.putExtra("DOWNLOAD_ID", downloadId); PendingIntent pausePendingIntent = PendingIntent.getService( this, (int) downloadId, pauseIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 取消下载的PendingIntent Intent cancelIntent = new Intent(this, DownloadService.class); cancelIntent.setAction("ACTION_CANCEL_DOWNLOAD"); cancelIntent.putExtra("DOWNLOAD_ID", downloadId); PendingIntent cancelPendingIntent = PendingIntent.getService( this, (int) downloadId, cancelIntent, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE ); // 构建带暂停/取消按钮的通知 NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "DOWNLOAD_CHANNEL") .setSmallIcon(R.drawable.ic_download) .setContentTitle("正在下载:" + vMeta.getTitle()) .setContentText("进度:" + progress + "%") .setPriority(NotificationCompat.PRIORITY_LOW) .addAction(R.drawable.ic_pause, "暂停", pausePendingIntent) .addAction(R.drawable.ic_cancel, "取消", cancelPendingIntent); // 设为前台服务通知 startForeground((int) downloadId, builder.build());
然后在Service的onStartCommand里处理暂停/取消的Action:
@Override public int onStartCommand(Intent intent, int flags, int startId) { if (intent != null) { String action = intent.getAction(); long downloadId = intent.getLongExtra("DOWNLOAD_ID", -1); DownloadTask task = mDownloadTasks.get(downloadId); if (task != null) { switch (action) { case "ACTION_PAUSE_DOWNLOAD": task.pause(); // 更新通知为"已暂停"状态,按钮换成"继续" updateNotification(downloadId, true); break; case "ACTION_CANCEL_DOWNLOAD": task.cancel(); mDownloadTasks.remove(downloadId); stopForeground(true); break; } } } return START_STICKY; }
这里的DownloadTask是你自己封装的下载任务类,需要实现暂停、取消、断点续传的具体逻辑。
最后提醒:如果用自定义下载,要注意处理网络变化、App被杀后台等情况,建议把下载进度、文件路径等信息持久化到SharedPreferences或数据库中,避免状态丢失。
内容的提问来源于stack exchange,提问作者PSN
相关产品推荐
相关产品推荐

