暂停和恢复下载

时间:2019-05-20 06:33:46

标签: android android-download-manager

我知道有一些用于此的库,但是我想为android实现自己的暂停/恢复功能。

我现在正在使用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();
                }
            }
        }
    }

}

如何为我的下载实现暂停/恢复?没有图书馆? 下载管理器本身可能会掉线,还是我应该使用其他方法?

1 个答案:

答案 0 :(得分:1)

您可以向创建的DownloadService发送消息,并调用DownloadManager进行暂停和恢复操作。

当DownloadManager排队下载任务时,您将获得一个ID(长) 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));
}