暂停和恢复下载
Pausing and resuming a download
我知道有一些用于此的库,但我想为 android 实现我自己的 pause/resume 功能。
我现在正在使用 DownloadManager 进行下载,这是我实现的下载服务:
public class DownloadService extends Service {
public static boolean isServiceRunning = false;
private static String downloadingPackageName;
private DownloadManager downloadManager;
long downloadRef;
RemoteViews contentView;
private boolean isDownloading = false;
Notification notification;
NotificationManager manager;
DownloadRequestListener downloadRequestListener;
NotificationManager notifManager;
private String dirPath;
private String packageName;
public static String PACKAGE_NAME;
@Override
public void onCreate() {
super.onCreate();
PACKAGE_NAME = getApplicationContext().getPackageName();
Log.e("OnCreate","OnCreateCommandClled...");
downloadRequestListener = new DownloadRequestListener();
IntentFilter filter = new IntentFilter("ir.amulay.downloadRequest");
registerReceiver(downloadRequestListener, filter);
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceRunning = true;
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.e("Service","Service Destroyed...");
unregisterReceiver(downloadRequestListener);
isServiceRunning = false;
super.onDestroy();
}
public Long downloadFile(String path, String packageName, String dirPath){
if(isDownloading) return null;
isDownloading =true;
this.dirPath = dirPath;
notifManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
contentView = new RemoteViews(getPackageName(), R.layout.download_notification_bar);
contentView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
contentView.setTextViewText(R.id.title, "Custom notification");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChanel = new NotificationChannel(
"downloadChanel",
"Example Service Chanel",
NotificationManager.IMPORTANCE_LOW
);
manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChanel);
}
notification = new NotificationCompat.Builder(this,"downloadChanel")
.setContentTitle("test")
.setContentText("test Againg")
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setAutoCancel(false)
.build();
startForeground(1,notification);
//I Dont Want many files to be downloaded at same time, so here is a check...
downloadingPackageName = packageName;
Uri uri = Uri.parse(path);
//Uri dir = Uri.parse(dirPath + "/" + packageName + ".apk");
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
this.packageName = packageName;
request.setTitle("Download File");
request.setDestinationInExternalPublicDir(dirPath, packageName+".apk");
request.setDescription("download apk files using download manager");
request.setMimeType(getMimeType(uri.toString()));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setVisibleInDownloadsUi(false);
// request.setDestinationUri(dir);
request.setAllowedOverMetered(true);
request.setAllowedOverRoaming(true);
downloadRef = downloadManager.enqueue(request);
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
boolean downloading = true;
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadRef); //filter by id which you have receieved when reqesting download from download manager
Cursor cursor = manager.query(q);
if(cursor.getCount() <= 0 ){
return;
}
cursor.moveToFirst();
//if its Running Send BroadCast... :)
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_RUNNING) {
int bytes_downloaded = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);
Log.e("DownloadProgress", "progress= " + dl_progress);
contentView.setTextViewText(R.id.title,"Downloading " +dl_progress);
// contentView.setProgressBar(R.id.downloadProgress,200,dl_progress,true);
notification.contentView.setProgressBar(R.id.downloadProgress, 100, dl_progress, false);
notifManager.notify(1, notification );
Intent intent = new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadProgress");
intent.putExtra("progresspercent",""+dl_progress);
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
downloading = false;
}
cursor.close();
if(!downloading) {
Intent intent= new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadCompleted");
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
//send a broadcast to tell its completed
return;
}
handler.postDelayed(this,300);
}
});
return downloadRef;
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadRef == id) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
openDownloadedAttachment(context, downloadId);
}
}
};
private String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
private void openDownloadedAttachment(final Context context, final long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) {
openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType);
}
}
cursor.close();
}
private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) {
if(attachmentUri!=null) {
// Get Content Uri.
if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) {
// FileUri - Convert it to contentUri.
File file = new File(attachmentUri.getPath());
attachmentUri = FileProvider.getUriForFile(this, "com.freshdesk.helpdesk.provider", file);
}
Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW);
openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType);
openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(openAttachmentIntent);
} catch (ActivityNotFoundException e) {
// Toast.makeText(context, context.getString("cant O"), Toast.LENGTH_LONG).show();
}
finally {
stopSelf();
}
}
}
private class DownloadRequestListener extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received", Toast.LENGTH_SHORT).show();
String reqType = intent.getStringExtra("reqType");
String packageName =intent.getStringExtra("package");
if(reqType.equals("download")){
String url = intent.getStringExtra("url");
String dirPath = intent.getStringExtra("dirPath");
downloadFile(url,packageName,dirPath);
}
else if(reqType.equals("stop")){
if(downloadingPackageName.equals(packageName) && downloadManager!= null){
downloadManager.remove(downloadRef);
isDownloading =false;
unregisterReceiver(onDownloadComplete);
stopSelf();
}
}
}
}
}
如何为我的下载实施 Pause/Resume?没有图书馆?
是否可以通过下载管理器本身或我应该使用其他方法?
您可以向您创建的 DownloadService 发送消息,并调用 DownloadManager 来执行暂停和恢复操作。
当DownloadManager入队一个下载任务时,你会得到一个id(long)
DownloadManager 将下载信息保存在 ContentProvider 中,只需使用给定的 id(长)更新 ContentProvider 信息,如果网络或其他条件满足该操作将执行。
您可以扩展 DownloadManager 并创建一对如下所示的方法。
- 暂停下载
/**
* pause download
*
* @param ids the IDs of the downloads to be paused
* @return the number of downloads actually paused
*/
public int pauseDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_PAUSED);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PAUSED_BY_APP);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}
- 继续下载
/**
* resume download
*
* @param ids the IDs of the downloads to be resumed
* @return the number of downloads actually resumed
*/
public int resumeDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_RUN);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}
我知道有一些用于此的库,但我想为 android 实现我自己的 pause/resume 功能。
我现在正在使用 DownloadManager 进行下载,这是我实现的下载服务:
public class DownloadService extends Service {
public static boolean isServiceRunning = false;
private static String downloadingPackageName;
private DownloadManager downloadManager;
long downloadRef;
RemoteViews contentView;
private boolean isDownloading = false;
Notification notification;
NotificationManager manager;
DownloadRequestListener downloadRequestListener;
NotificationManager notifManager;
private String dirPath;
private String packageName;
public static String PACKAGE_NAME;
@Override
public void onCreate() {
super.onCreate();
PACKAGE_NAME = getApplicationContext().getPackageName();
Log.e("OnCreate","OnCreateCommandClled...");
downloadRequestListener = new DownloadRequestListener();
IntentFilter filter = new IntentFilter("ir.amulay.downloadRequest");
registerReceiver(downloadRequestListener, filter);
registerReceiver(onDownloadComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
isServiceRunning = true;
return START_STICKY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Log.e("Service","Service Destroyed...");
unregisterReceiver(downloadRequestListener);
isServiceRunning = false;
super.onDestroy();
}
public Long downloadFile(String path, String packageName, String dirPath){
if(isDownloading) return null;
isDownloading =true;
this.dirPath = dirPath;
notifManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
contentView = new RemoteViews(getPackageName(), R.layout.download_notification_bar);
contentView.setImageViewResource(R.id.image, R.mipmap.ic_launcher);
contentView.setTextViewText(R.id.title, "Custom notification");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel serviceChanel = new NotificationChannel(
"downloadChanel",
"Example Service Chanel",
NotificationManager.IMPORTANCE_LOW
);
manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(serviceChanel);
}
notification = new NotificationCompat.Builder(this,"downloadChanel")
.setContentTitle("test")
.setContentText("test Againg")
.setContent(contentView)
.setSmallIcon(R.drawable.ic_launcher_foreground)
.setAutoCancel(false)
.build();
startForeground(1,notification);
//I Dont Want many files to be downloaded at same time, so here is a check...
downloadingPackageName = packageName;
Uri uri = Uri.parse(path);
//Uri dir = Uri.parse(dirPath + "/" + packageName + ".apk");
downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
DownloadManager.Request request = new DownloadManager.Request(uri);
this.packageName = packageName;
request.setTitle("Download File");
request.setDestinationInExternalPublicDir(dirPath, packageName+".apk");
request.setDescription("download apk files using download manager");
request.setMimeType(getMimeType(uri.toString()));
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);
request.setVisibleInDownloadsUi(false);
// request.setDestinationUri(dir);
request.setAllowedOverMetered(true);
request.setAllowedOverRoaming(true);
downloadRef = downloadManager.enqueue(request);
Handler handler = new Handler();
handler.post(new Runnable() {
@Override
public void run() {
boolean downloading = true;
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query q = new DownloadManager.Query();
q.setFilterById(downloadRef); //filter by id which you have receieved when reqesting download from download manager
Cursor cursor = manager.query(q);
if(cursor.getCount() <= 0 ){
return;
}
cursor.moveToFirst();
//if its Running Send BroadCast... :)
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_RUNNING) {
int bytes_downloaded = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));
int bytes_total = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
final int dl_progress = (int) ((bytes_downloaded * 100L) / bytes_total);
Log.e("DownloadProgress", "progress= " + dl_progress);
contentView.setTextViewText(R.id.title,"Downloading " +dl_progress);
// contentView.setProgressBar(R.id.downloadProgress,200,dl_progress,true);
notification.contentView.setProgressBar(R.id.downloadProgress, 100, dl_progress, false);
notifManager.notify(1, notification );
Intent intent = new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadProgress");
intent.putExtra("progresspercent",""+dl_progress);
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_SUCCESSFUL) {
downloading = false;
}
if (cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) == DownloadManager.STATUS_FAILED) {
downloading = false;
}
cursor.close();
if(!downloading) {
Intent intent= new Intent();
intent.setAction("ir.amulay.downloadEvent");
intent.putExtra("eventType","downloadCompleted");
intent.putExtra("packagename",packageName);
intent.putExtra("refID",""+downloadRef);
sendBroadcast(intent);
//send a broadcast to tell its completed
return;
}
handler.postDelayed(this,300);
}
});
return downloadRef;
}
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadRef == id) {
long downloadId = intent.getLongExtra(
DownloadManager.EXTRA_DOWNLOAD_ID, 0);
openDownloadedAttachment(context, downloadId);
}
}
};
private String getMimeType(String url) {
String type = null;
String extension = MimeTypeMap.getFileExtensionFromUrl(url);
if (extension != null) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
type = mime.getMimeTypeFromExtension(extension);
}
return type;
}
private void openDownloadedAttachment(final Context context, final long downloadId) {
DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
Cursor cursor = downloadManager.query(query);
if (cursor.moveToFirst()) {
int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE));
if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) {
openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType);
}
}
cursor.close();
}
private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) {
if(attachmentUri!=null) {
// Get Content Uri.
if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) {
// FileUri - Convert it to contentUri.
File file = new File(attachmentUri.getPath());
attachmentUri = FileProvider.getUriForFile(this, "com.freshdesk.helpdesk.provider", file);
}
Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW);
openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType);
openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
try {
context.startActivity(openAttachmentIntent);
} catch (ActivityNotFoundException e) {
// Toast.makeText(context, context.getString("cant O"), Toast.LENGTH_LONG).show();
}
finally {
stopSelf();
}
}
}
private class DownloadRequestListener extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "Received", Toast.LENGTH_SHORT).show();
String reqType = intent.getStringExtra("reqType");
String packageName =intent.getStringExtra("package");
if(reqType.equals("download")){
String url = intent.getStringExtra("url");
String dirPath = intent.getStringExtra("dirPath");
downloadFile(url,packageName,dirPath);
}
else if(reqType.equals("stop")){
if(downloadingPackageName.equals(packageName) && downloadManager!= null){
downloadManager.remove(downloadRef);
isDownloading =false;
unregisterReceiver(onDownloadComplete);
stopSelf();
}
}
}
}
}
如何为我的下载实施 Pause/Resume?没有图书馆? 是否可以通过下载管理器本身或我应该使用其他方法?
您可以向您创建的 DownloadService 发送消息,并调用 DownloadManager 来执行暂停和恢复操作。
当DownloadManager入队一个下载任务时,你会得到一个id(long) DownloadManager 将下载信息保存在 ContentProvider 中,只需使用给定的 id(长)更新 ContentProvider 信息,如果网络或其他条件满足该操作将执行。
您可以扩展 DownloadManager 并创建一对如下所示的方法。
- 暂停下载
/**
* pause download
*
* @param ids the IDs of the downloads to be paused
* @return the number of downloads actually paused
*/
public int pauseDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_PAUSED);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_PAUSED_BY_APP);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}
- 继续下载
/**
* resume download
*
* @param ids the IDs of the downloads to be resumed
* @return the number of downloads actually resumed
*/
public int resumeDownload(long... ids) {
if (ids == null || ids.length == 0) {
// called with nothing to remove!
throw new IllegalArgumentException("input param 'ids' can't be null");
}
ContentValues values = new ContentValues();
values.put(Downloads.Impl.COLUMN_CONTROL, Downloads.Impl.CONTROL_RUN);
values.put(Downloads.Impl.COLUMN_STATUS, Downloads.Impl.STATUS_RUNNING);
if (ids.length == 1) {
return mResolver.update(ContentUris.withAppendedId(mBaseUri, ids[0]), values,
null, null);
}
return mResolver.update(mBaseUri, values, getWhereClauseForIds(ids),
getWhereArgsForIds(ids));
}