探究在APP中使用DownloadManager完成下载

来源:互联网 发布:淘宝旺铺全屏代码 编辑:程序博客网 时间:2024/05/17 07:57

所谓探究,这里进行逐层深入,想看最终结果的同学,请直接翻看最后部分。这里少量的注释,就在代码中进行添加了.

before add some permission

 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"></uses-permission>

1.使用DownloadManager下载一张简单图片

package com.hang.downloadmanagerdemo;import android.app.DownloadManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.ParcelFileDescriptor;import android.support.v7.app.AppCompatActivity;import android.widget.ImageView;import java.io.File;public class MainActivity extends AppCompatActivity {    public static final String URL_MUSIC = "http://vfile.dingdongfm.com/2015/1450/2617/4979/145026174979.ssm/145026174979.mp3";    public static final String URL_IMAGE = "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3741636297,2352266532&fm=116&gp=0.jpg";    private long myDownloadReference;    private DownloadManager downloadManager;    private ImageView imageView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        imageView = new ImageView(this);        setContentView(imageView);        //1.create downloadManager&&Request add request to downloadManager        String serviceNameInString = Context.DOWNLOAD_SERVICE;        downloadManager = (DownloadManager) getSystemService(serviceNameInString);        Uri uri = Uri.parse(URL_IMAGE);        DownloadManager.Request request = new DownloadManager.Request(uri);        File destFile = new File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.mp3");        if (destFile.exists()) {            destFile.delete();        }        request.setDestinationUri(Uri.parse("file://" + destFile.getAbsolutePath()));        //be care if you want to add below code,you must add DOWNLOAD_WITHOUT_NOTIFICATION permission        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);        myDownloadReference = downloadManager.enqueue(request);    }    @Override    protected void onResume() {        super.onResume();        //2.register receiver detect download finish        IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);        registerReceiver(broadcastReceiver, intentFilter);    }    @Override    protected void onPause() {        super.onPause();        unregisterReceiver(broadcastReceiver);    }    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            long downloadCompleteReference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);            if (myDownloadReference == downloadCompleteReference) {                //3.download over ,and show image                try {                    ParcelFileDescriptor parcelFileDescriptor = downloadManager.openDownloadedFile(myDownloadReference);                    Bitmap bitmap = BitmapFactory.decodeFileDescriptor(parcelFileDescriptor.getFileDescriptor());                    imageView.setImageBitmap(bitmap);                    System.out.println();                } catch (Exception e) {                    e.printStackTrace();                }            }        }    };}

2.下载大文件并更新下载进度

package com.hang.downloadmanagerdemo;import android.app.DownloadManager;import android.app.ProgressDialog;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.os.ParcelFileDescriptor;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.widget.Toast;import java.io.File;public class MainActivity extends AppCompatActivity {    public static final String TAG = "xxxx";    public static final String URL_MUSIC = "http://vfile.dingdongfm.com/2016/1473/4999/6792/147349996792.ssm/147349996792.mp3";    private long myDownloadReference;    private DownloadManager downloadManager;    private ProgressDialog progressDialog;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        String serviceNameInString = Context.DOWNLOAD_SERVICE;        downloadManager = (DownloadManager) getSystemService(serviceNameInString);        Uri uri = Uri.parse(URL_MUSIC);        DownloadManager.Request request = new DownloadManager.Request(uri);        File destFile = new File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.mp3");        if (destFile.exists()) {            destFile.delete();        }        request.setDestinationUri(Uri.parse("file://" + destFile.getAbsolutePath()));        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);        myDownloadReference = downloadManager.enqueue(request);        //1.add listener to downloaded progress        getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),                true, new DownloadObserver(handler, MainActivity.this, myDownloadReference));        //2.use progressDialog&& handler to show download progress        progressDialog = new ProgressDialog(this);        progressDialog.setProgress(0);        progressDialog.setIndeterminate(false);        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);        progressDialog.show();    }    @Override    protected void onResume() {        super.onResume();        IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);        registerReceiver(broadcastReceiver, intentFilter);    }    @Override    protected void onPause() {        super.onPause();        unregisterReceiver(broadcastReceiver);    }    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            long downloadCompleteReference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);            //3.play audio            if (myDownloadReference == downloadCompleteReference) {                try {                    ParcelFileDescriptor parcelFileDescriptor = downloadManager.openDownloadedFile(myDownloadReference);                    MediaPlayer mediaPlayer = new MediaPlayer();                    mediaPlayer.setDataSource(parcelFileDescriptor.getFileDescriptor());                    mediaPlayer.prepare();                    mediaPlayer.start();                    System.out.println();                } catch (Exception e) {                    e.printStackTrace();                }            }        }    };    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            if (progressDialog != null && msg.what > 0) {                progressDialog.setProgress(msg.what);                Log.d(TAG, "" + msg.what);            }            if (msg.what == 100) {                progressDialog.dismiss();                Toast.makeText(MainActivity.this, "download finished~", Toast.LENGTH_LONG).show();            }        }    };}

3.处理Pause/Resume

搜索了一番,没有找到DownloadManager的Pause/Resume方法,找到的一个折中的办法是,通过

         public void cancelDownload() {        if (downloadManager != null && myDownloadReference > 0) {            downloadManager.remove(myDownloadReference);            myDownloadReference = 0;        }    }

将要下载的任务从下载管理器中删除。
通过

  myDownloadReference                = downloadManager.enqueue(request);

将下载任务“再次”添加到下载管理器。
这里一定要注意以下:重复enqueue而没有调用相应的remove方法,会造成文件的重复下载!

package com.hang.downloadmanagerdemo;import android.app.DownloadManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.media.MediaPlayer;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.os.ParcelFileDescriptor;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.view.View;import android.widget.LinearLayout;import android.widget.Toast;import com.hang.androidtestdemo.R;import java.io.File;public class MainActivity extends AppCompatActivity implements View.OnClickListener {    public static final String TAG = "xxxx";    public static final String URL_MUSIC = "http://vfile.dingdongfm.com/2016/1473/4999/6792/147349996792.ssm/147349996792.mp3";    private DownloadManager downloadManager;    private long myDownloadReference;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.main);        LinearLayout totalLayout = (LinearLayout) findViewById(R.id.ll);        for (int j = 0; j < totalLayout.getChildCount(); j++) {            View view = totalLayout.getChildAt(j);            view.setOnClickListener(this);        }    }    public void cancelDownload() {        if (downloadManager != null && myDownloadReference > 0) {            downloadManager.remove(myDownloadReference);            myDownloadReference = 0;        }    }    public void startDownload() {        String serviceNameInString = Context.DOWNLOAD_SERVICE;        downloadManager = (DownloadManager) getSystemService(serviceNameInString);        Uri uri = Uri.parse(URL_MUSIC);        DownloadManager.Request request = new DownloadManager.Request(uri);        File destFile = new File(getExternalFilesDir(Environment.DIRECTORY_MUSIC), "test.mp3");        if (destFile.exists()) {            destFile.delete();        }        request.setDestinationUri(Uri.parse("file://" + destFile.getAbsolutePath()));//        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);        myDownloadReference                = downloadManager.enqueue(request);        //1.add listener to downloaded progress        getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),                true, new DownloadObserver(handler, MainActivity.this, myDownloadReference));    }//be carefult not to download repeatly    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.btn_start: {                if (myDownloadReference == 0) {                    startDownload();                } else {                    Toast.makeText(MainActivity.this, "already added to downloading queue", Toast.LENGTH_LONG).show();                }                break;            }            case R.id.btn_cancel: {                if (myDownloadReference > 0) {                    cancelDownload();                }                break;            }        }    }    @Override    protected void onResume() {        super.onResume();        IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);        registerReceiver(broadcastReceiver, intentFilter);    }    @Override    protected void onPause() {        super.onPause();        unregisterReceiver(broadcastReceiver);    }    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            long downloadCompleteReference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);            //3.play audio            if (myDownloadReference > 0 && myDownloadReference == downloadCompleteReference) {                try {                    ParcelFileDescriptor parcelFileDescriptor = downloadManager.openDownloadedFile(myDownloadReference);                    MediaPlayer mediaPlayer = new MediaPlayer();                    mediaPlayer.setDataSource(parcelFileDescriptor.getFileDescriptor());                    mediaPlayer.prepare();                    mediaPlayer.start();                    System.out.println();                } catch (Exception e) {                    e.printStackTrace();                }            }        }    };    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            Log.d(TAG, "" + msg.what);        }    };}

4.列表下载

为了方便管理,这里定义一个DownloadBean

package com.hang.downloadmanagerdemo;public class DownloadBean {    private String name;    private double downloadProgress;    private long downloadReference;    private String downloadUrl;    @Override    public boolean equals(Object obj) {        boolean isEqual = false;        if (obj != null && obj instanceof DownloadBean) {            isEqual = (this.downloadReference == ((DownloadBean) obj).downloadReference);        }        return isEqual;    }    public DownloadBean(String name, String downloadUrl) {        this.name = name;        this.downloadUrl = downloadUrl;        this.downloadProgress = 0;        this.downloadReference = 0;    }    //TODO getter and setter}

定义Adapter展示下载列表:
为了简化处理,这里使用了ListView的多选模式

package com.hang.downloadmanagerdemo;import android.content.Context;import android.view.LayoutInflater;import android.view.View;import android.view.ViewGroup;import android.widget.BaseAdapter;import android.widget.ImageView;import android.widget.ListView;import android.widget.TextView;import com.hang.androidtestdemo.R;import java.text.DecimalFormat;import java.util.List;public class DownloadAdapter extends BaseAdapter {    private List<DownloadBean> beanList;    private Context mContext;    private ListView listView;    DecimalFormat df2 = new DecimalFormat("00.0%");    public DownloadAdapter(Context context, ListView listView) {        this.mContext = context;        this.listView = listView;    }    public void setData(List<DownloadBean> beanList) {        this.beanList = beanList;        notifyDataSetChanged();    }    public List<DownloadBean> getData() {        return this.beanList;    }    @Override    public int getCount() {        return (beanList == null) ? 0 : beanList.size();    }    @Override    public DownloadBean getItem(int position) {        DownloadBean bean = beanList.get(position);        return bean;    }    @Override    public long getItemId(int position) {        return position;    }    @Override    public View getView(int position, View convertView, ViewGroup parent) {        ViewHolder viewHolder = null;        if (convertView == null) {            viewHolder = new ViewHolder();            convertView = LayoutInflater.from(mContext).inflate(R.layout.item_download, parent, false);            viewHolder.checkView = (ImageView) convertView.findViewById(R.id.iv_check);            viewHolder.nameView = (TextView) convertView.findViewById(R.id.tv_name);            viewHolder.progressView = (TextView) convertView.findViewById(R.id.tv_progress);            convertView.setTag(viewHolder);        } else {            viewHolder = (ViewHolder) convertView.getTag();        }        if (listView.isItemChecked(position)) {            viewHolder.checkView.setImageResource(R.drawable.download_chosed);        } else {            viewHolder.checkView.setImageResource(R.drawable.download_unchosed);        }        DownloadBean item = getItem(position);        viewHolder.nameView.setText(item.getName());        viewHolder.progressView.setText("" + df2.format(item.getDownloadProgress()));        return convertView;    }    class ViewHolder {        ImageView checkView;        TextView nameView;        TextView progressView;    }}

cell布局文件

<?xml version="1.0" encoding="utf-8"?><!--item_download.xml--><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    android:layout_height="64dp"    android:gravity="center_vertical"    android:paddingLeft="@dimen/distance_16dp"    android:paddingRight="@dimen/distance_16dp"    android:textColor="@android:color/black"    android:textSize="14sp">    <ImageView        android:id="@+id/iv_check"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:src="@drawable/download_unchosed" />    <TextView        android:id="@+id/tv_progress"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:text="0%" />    <TextView        android:id="@+id/tv_name"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:layout_toLeftOf="@id/tv_progress"        android:layout_toRightOf="@id/iv_check"        android:gravity="center_vertical" /></RelativeLayout>

最后的Java代码

package com.hang.downloadmanagerdemo;import android.app.DownloadManager;import android.content.BroadcastReceiver;import android.content.Context;import android.content.Intent;import android.content.IntentFilter;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.support.v7.app.AppCompatActivity;import android.util.Log;import android.util.SparseBooleanArray;import android.view.View;import android.widget.AdapterView;import android.widget.Button;import android.widget.ListView;import android.widget.RelativeLayout;import android.widget.Toast;import com.hang.androidtestdemo.R;import java.io.File;import java.util.Arrays;import java.util.List;public class MainActivity extends AppCompatActivity implements View.OnClickListener, AdapterView.OnItemClickListener {    public static final String TAG = "xxxx";    public static final String URL_MUSIC_0 = "http://vfile.dingdongfm.com/2016/1473/4999/6792/147349996792.ssm/147349996792.mp3";    public static final String URL_MUSIC_1 = "http://vfile.dingdongfm.com/2016/1472/6907/0485/147269070485.ssm/147269070485.mp3";    public static final String URL_MUSIC_2 = "http://vfile.dingdongfm.com/2016/1470/3842/4921/147038424921.ssm/147038424921.mp3";    public static final String URL_MUSIC_3 = "http://vfile.dingdongfm.com/2015/1450/2643/2692/145026432692.ssm/145026432692.mp3";    private DownloadAdapter mAdapter;    private ListView listView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        RelativeLayout outLayout = new RelativeLayout(this);        setContentView(outLayout);        listView = new ListView(this);        listView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);        listView.setOnItemClickListener(this);        outLayout.addView(listView);        Button button = new Button(this);        button.setId(R.id.btn);        button.setText("Download");        outLayout.addView(button);        RelativeLayout.LayoutParams buttonParams = (RelativeLayout.LayoutParams) button.getLayoutParams();        buttonParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, R.id.btn);        button.setOnClickListener(this);        mAdapter = new DownloadAdapter(this, listView);        listView.setAdapter(mAdapter);        List<DownloadBean> downloadList = Arrays.asList(new DownloadBean("audio 0", URL_MUSIC_0),                new DownloadBean("audio 1", URL_MUSIC_1), new DownloadBean("audio 2", URL_MUSIC_2),                new DownloadBean("audio 3", URL_MUSIC_3));        mAdapter.setData(downloadList);    }    @Override    public void onClick(View view) {        switch (view.getId()) {            case R.id.btn: {                SparseBooleanArray booleanArray = listView.getCheckedItemPositions();                for (int j = 0; j < booleanArray.size(); j++) {                    int key = booleanArray.keyAt(j);                    if (booleanArray.get(key)) {                        startDownload(mAdapter.getItem(key), MainActivity.this);                        Log.d(TAG, "" + key + ": true");                    } else {                        Log.d(TAG, "" + key + ": false");                    }                }                break;            }        }    }    public void startDownload(DownloadBean downloadBean, Context mContext) {        String serviceNameInString = Context.DOWNLOAD_SERVICE;        DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(serviceNameInString);        Uri uri = Uri.parse(downloadBean.getDownloadUrl());        DownloadManager.Request request = new DownloadManager.Request(uri);        File destFile = new File(mContext.getExternalFilesDir(Environment.DIRECTORY_MUSIC), downloadBean.getName());        if (destFile.exists()) {            destFile.delete();        }        request.setDestinationUri(Uri.parse("file://" + destFile.getAbsolutePath()));//        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);        long myDownloadReference                = downloadManager.enqueue(request);        //1.add listener to downloaded progress        mContext.getContentResolver().registerContentObserver(Uri.parse("content://downloads/"),                true, new DownloadObserver(handler, mContext, myDownloadReference));        downloadBean.setDownloadReference(myDownloadReference);    }    @Override    public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {        mAdapter.notifyDataSetChanged();    }    @Override    protected void onResume() {        super.onResume();        IntentFilter intentFilter = new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE);        registerReceiver(broadcastReceiver, intentFilter);    }    @Override    protected void onPause() {        super.onPause();        unregisterReceiver(broadcastReceiver);    }    BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {        @Override        public void onReceive(Context context, Intent intent) {            long downloadCompleteReference = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);            List<DownloadBean> beanList = mAdapter.getData();            if (beanList != null) {                for (int j = 0; j < beanList.size(); j++) {                    DownloadBean bean = beanList.get(j);                    if (bean.getDownloadReference() == downloadCompleteReference) {                        Toast.makeText(MainActivity.this, bean.getName() + " finish download~", Toast.LENGTH_SHORT).show();                    }                }            }        }    };    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            //be careful total size may be -1            if (msg.arg2 > 0) {                List<DownloadBean> beanList = mAdapter.getData();                for (int j = 0; j < beanList.size(); j++) {                    DownloadBean bean = beanList.get(j);                    if (bean.getDownloadReference() == (Long) msg.obj) {                        bean.setDownloadProgress(msg.arg1 * 1.0 / msg.arg2);                        mAdapter.notifyDataSetChanged();                        break;                    }                }            }        }    };}

这里对DownloadObserver也进行了修改

package com.hang.downloadmanagerdemo;import android.app.DownloadManager;import android.content.Context;import android.database.ContentObserver;import android.database.Cursor;import android.os.Handler;import android.os.Message;import android.util.Log;public class DownloadObserver extends ContentObserver {    private long downid;    private Handler handler;    private Context context;    public DownloadObserver(Handler handler, Context context, long downid) {        super(handler);        this.handler = handler;        this.downid = downid;        this.context = context;    }    @Override    public void onChange(boolean selfChange) {        //每当/data/data/com.android.providers.download/database/database.db变化后,触发onCHANGE,开始具体查询        Log.w("onChangeID", String.valueOf(downid));        super.onChange(selfChange);        //实例化查询类,这里需要一个刚刚的downid        DownloadManager.Query query = new DownloadManager.Query().setFilterById(downid);        DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);        Cursor cursor = downloadManager.query(query);        while (cursor.moveToNext()) {            int mDownload_so_far = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));            int mDownload_all = cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));//            int mProgress = (int) (mDownload_so_far * 1.0 / mDownload_all);//            Log.w(getClass().getSimpleName(), String.valueOf(mProgress));            Message message = Message.obtain();            message.arg1 = mDownload_so_far;            message.arg2 = mDownload_all;            message.obj = downid;            handler.sendMessage(message);        }    }}
0 0