这里使用的是github上的一个开源项目 DownloadProvider 下载地址:https://github.com/yxl/DownloadProvider,支持多线程下载和断点续传功能,自己在它上面作了一些修改以满足业务需求。
先看效果图吧:
通知栏下载进度 提示
工程目录结构如下:
清单文件
[java] view plain copy
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.downloadtest"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="17" />
<permission
android:name="com.example.downloadtest.permission.ACCESS_DOWNLOAD_MANAGER"
android:description="@string/permdesc_downloadManager"
android:label="@string/permlab_downloadManager"
android:protectionLevel="normal" />
<permission
android:name="com.example.downloadtest.permission.ACCESS_DOWNLOAD_MANAGER_ADVANCED"
android:description="@string/permdesc_downloadManagerAdvanced"
android:label="@string/permlab_downloadManagerAdvanced"
android:protectionLevel="normal" />
<permission
android:name="com.example.downloadtest.permission.SEND_DOWNLOAD_COMPLETED_INTENTS"
android:description="@string/permdesc_downloadCompletedIntent"
android:label="@string/permlab_downloadCompletedIntent"
android:protectionLevel="normal" />
<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" android:name=".app.MyApplication">
<activity
android:name="com.example.downloadtest.MainActivity"
android:label="@string/app_name" >
<provider
android:name="com.example.downloadtest.providers.downloads.DownloadProvider"
android:authorities="com.example.downloadtest.downloads" android:exported="false"/>
<receiver
android:name="com.example.downloadtest.providers.downloads.DownloadReceiver"
android:exported="false" >
界面布局文件 activity_main.xml
[html] view plain copy
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity" >
<ListView
android:id="@+id/mListView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:cacheColorHint="@android:color/transparent"/>
</RelativeLayout>
MainActivity.java
[java] view plain copy
package com.example.downloadtest;
import java.util.ArrayList;
import java.util.List;
import android.app.Activity;
import android.content.Context;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import com.example.downloadtest.app.MyApplication;
import com.example.downloadtest.entity.AppInfo;
import com.example.downloadtest.entity.DownloadItem;
import com.example.downloadtest.providers.DownloadManager;
import com.example.downloadtest.providers.DownloadManager.Request;
import com.example.downloadtest.providers.downloads.Downloads;
public class MainActivity extends Activity {
public static final String TAG = MainActivity.class.getSimpleName();
private static final int QUERY_DOWNLOAD_PROGRESS = 10;
private static final String DOWNLOAD_DIR_NAME = "test_download";
private DownloadManager mDownloadManager;
private ListView mListView;
private MyContentObserver mContentObserver = new MyContentObserver();
private List
private DownloadAdapter mAdapter;
private MyApplication mApp;
private Handler handler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case QUERY_DOWNLOAD_PROGRESS:
if (mAdapter != null) {
mAdapter.notifyDataSetChanged();
}
break;
default:
break;
}
};
};
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDownloadManager = new DownloadManager(getContentResolver(),
getPackageName());
mApp = (MyApplication) getApplication();
initDownloadData();
findView();
handleDownloadsChanged(); // 默认初始化
}
protected void onStart() {
getContentResolver().registerContentObserver(Downloads.CONTENT_URI,
true, mContentObserver);
super.onStart();
}
protected void onStop() {
getContentResolver().unregisterContentObserver(mContentObserver);
super.onStop();
}
public void handleDownloadsChanged() {
DownloadManager.Query baseQuery = new DownloadManager.Query()
.setOnlyIncludeVisibleInDownloadsUi(true);
Cursor cursor = mDownloadManager.query(baseQuery);
int mIdColumnId = cursor
.getColumnIndexOrThrow(DownloadManager.COLUMN_ID);
int mStatusColumnId = cursor
.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS);
int mTotalBytesColumnId = cursor
.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int mCurrentBytesColumnId = cursor
.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
while (cursor.moveToNext()) {
long downloadId = cursor.getLong(mIdColumnId);
long totalBytes = cursor.getLong(mTotalBytesColumnId);
long currentBytes = cursor.getLong(mCurrentBytesColumnId);
int status = cursor.getInt(mStatusColumnId);
int progress = getProgressValue(totalBytes, currentBytes);
DownloadItem di = mApp.downloadMap
.get(mApp.mapping.get(downloadId));
if (di != null) {
di.setDownloadId(downloadId);
di.setTotalBytes(totalBytes);
di.setCurrentBytes(currentBytes);
di.setStatus(status);
di.setProgress(progress);
}
}
cursor.close();
handler.sendEmptyMessage(QUERY_DOWNLOAD_PROGRESS);
}
public int getProgressValue(long totalBytes, long currentBytes) {
if (totalBytes == -1) {
return 0;
}
return (int) (currentBytes * 100 / totalBytes);
}
private void findView() {
mListView = (ListView) findViewById(R.id.mListView);
mAdapter = new DownloadAdapter(getApplicationContext());
mListView.setAdapter(mAdapter);
}
private void initDownloadData() {
String[] names = { "易信", "百度地图", "天天动听", "网易新闻", "电话帮", "墨迹天气", "生活日历",
"豆果美食" };
String[] urls = {
"http://gdown.baidu.com/data/wisegame/653346a13ab69081/yixin_146.apk",
"http://gdown.baidu.com/data/wisegame/824ed743d6cdbbb6/baiduditu_431.apk",
"http://gdown.baidu.com/data/wisegame/839ca8c2da93e9e8/tiantiandongting_5902.apk",
"http://gdown.baidu.com/data/wisegame/8cafd2fb933d5c09/NetEaseNews_273.apk",
"http://www.yulore.com/go/?id=30",
"http://gdown.baidu.com/data/wisegame/2fdcb550af198691/mojitianqi_24402.apk",
"http://gdown.baidu.com/data/wisegame/0a3e9a0575a77fe2/shenghuorili_19.apk",
"http://gdown.baidu.com/data/wisegame/e61ab2327372efdf/DouguoRecipe_80.apk" };
String[] infos = { "32万人安装 . 16.0MB", "4182万人安装 . 10.5MB",
"4493万人安装 . 7.9MB", "1148万人安装 . 6.1MB", "21万人安装 . 3.1MB",
"8000万人安装 . 8.1MB", "100万人安装 . 6.1MB", "500万人安装 . 8.6MB" };
for (int i = 0; i < names.length; i++) {
String name = names[i];
String url = urls[i];
AppInfo info = new AppInfo();
info.setId("1000" + i);
info.setName(name);
info.setUrl(url);
info.setInfo(infos[i]);
downloadList.add(info);
}
}
private class MyContentObserver extends ContentObserver {
public MyContentObserver() {
super(new Handler());
}
public void onChange(boolean selfChange) {
handleDownloadsChanged();
}
}
private long startDownload(AppInfo ai) {
//判断SD卡是否可用
if(!checkSDCardIsAvailable()){
Toast.makeText(getApplicationContext(), "外部存储空间不可用,请检查后再试", Toast.LENGTH_LONG).show();
return -1;
}
try {
String url = ai.getUrl();
Log.e(TAG, "download url:" + url);
Uri srcUri = Uri.parse(url);
DownloadManager.Request request = new Request(srcUri);
// 设置文件保存的路径
// request.setDestinationInExternalDir(getApplicationContext(),
// DOWNLOAD_DIR_NAME, ai.getName() + ".apk");
request.setDestinationInExternalFilesDir(getApplicationContext(), DOWNLOAD_DIR_NAME, "");
request.setDescription("下载");
return mDownloadManager.enqueue(request);
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
/**
* 判断 SDCard是否可用
*
* @return
*/
public boolean checkSDCardIsAvailable() {
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED))
return true;
else
return false;
}
private class DownloadAdapter extends BaseAdapter {
private Context ctx;
private LayoutInflater inflater;
public DownloadAdapter(Context ctx) {
this.ctx = ctx;
inflater = LayoutInflater.from(ctx);
}
public int getCount() {
return downloadList.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return downloadList.get(position);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public View getView(final int position, View convertView,
ViewGroup parent) {
View view;
ViewHolder holder;
if (convertView == null) {
view = inflater.inflate(R.layout.download_item, null);
holder = new ViewHolder();
holder.tv_app_name = (TextView) view
.findViewById(R.id.tv_app_name);
holder.tv_app_info = (TextView) view
.findViewById(R.id.tv_app_info);
holder.tv_progress_percent = (TextView) view
.findViewById(R.id.tv_progress_percent);
holder.bt_app_download = (Button) view.findViewById(R.id.bt_app_download);
holder.pb_download_progress = (ProgressBar) view
.findViewById(R.id.pb_download_progress);
view.setTag(holder);
} else {
view = convertView;
holder = (ViewHolder) view.getTag();
}
AppInfo ai = downloadList.get(position);
holder.tv_app_name.setText(ai.getName());
holder.tv_app_info.setText(ai.getInfo());
holder.bt_app_download.setText(R.string.download);
final DownloadItem di = mApp.downloadMap.get(ai.getId());
if (di != null) {
int status = di.getStatus();
switch (status) {
case DownloadManager.STATUS_FAILED:
Toast.makeText(ctx,
"下载 " + ai.getName() + " 失败,请检查网络之后重试",
Toast.LENGTH_LONG).show();
holder.pb_download_progress.setVisibility(View.GONE);
holder.tv_progress_percent.setVisibility(View.GONE);
mApp.mapping.remove(di.getDownloadId());// 删除
mApp.downloadMap.remove(ai.getId());// 删除
// mDownloadManager.remove(downloadId);
mDownloadManager.markRowDeleted(di.getDownloadId()); // 删除该下载
holder.bt_app_download.setText(R.string.failed);
holder.tv_app_info.setVisibility(View.VISIBLE);
break;
case DownloadManager.STATUS_SUCCESSFUL:
Log.i(TAG, "download complete " + di.getDownloadId());
holder.pb_download_progress.setVisibility(View.GONE);
holder.tv_progress_percent.setVisibility(View.GONE);
mApp.mapping.remove(di.getDownloadId());// 删除
mApp.downloadMap.remove(ai.getId());// 删除
holder.bt_app_download.setText(R.string.complete);
holder.tv_app_info.setVisibility(View.VISIBLE);
break;
case DownloadManager.STATUS_PENDING:
holder.tv_progress_percent.setVisibility(View.VISIBLE);
holder.pb_download_progress.setVisibility(View.VISIBLE);
holder.tv_app_info.setVisibility(View.GONE);
holder.tv_progress_percent.setText(R.string.pending);
holder.bt_app_download.setText(R.string.cancel);
break;
case DownloadManager.STATUS_RUNNING:
holder.tv_progress_percent.setVisibility(View.VISIBLE);
holder.pb_download_progress.setVisibility(View.VISIBLE);
holder.tv_app_info.setVisibility(View.GONE);
int progress = di.getProgress();
holder.pb_download_progress.setProgress(progress);
holder.tv_progress_percent.setText(progress + "%");
break;
case DownloadManager.STATUS_PAUSED:
holder.tv_progress_percent.setVisibility(View.VISIBLE);
holder.pb_download_progress.setVisibility(View.VISIBLE);
holder.tv_app_info.setVisibility(View.GONE);
holder.bt_app_download.setText(R.string.resume);
break;
default:
break;
}
} else {
holder.tv_progress_percent.setVisibility(View.GONE);
holder.pb_download_progress.setVisibility(View.GONE);
holder.tv_app_info.setVisibility(View.VISIBLE);
}
holder.bt_app_download.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Button bt = (Button) v;
AppInfo info = downloadList.get(position);
DownloadItem di = mApp.downloadMap.get(info.getId());
String str = bt.getText().toString();
if ("下载".equals(str)) {
long downloadId = startDownload(info);
if (downloadId != -1) {
DownloadItem downloadItem = new DownloadItem();
downloadItem.setDownloadId(downloadId);
downloadItem.setId(info.getId());
mApp.downloadMap.put(info.getId(), downloadItem);
mApp.mapping.put(downloadId, info.getId());
}
} else if ("暂停".equals(str)) {
if (di != null && (di.getStatus() == DownloadManager.STATUS_RUNNING)) {
mDownloadManager.pauseDownload(di.getDownloadId());
}
} else if ("继续".equals(str)) {
if (di != null && (di.getStatus() == DownloadManager.STATUS_PAUSED)) {
mDownloadManager.resumeDownload(di.getDownloadId());
}
} else if ("取消".equals(str)) {
if (di != null && (di.getStatus() == DownloadManager.STATUS_PENDING)) {
mDownloadManager.markRowDeleted(di.getDownloadId());
}
}
notifyDataSetChanged(); // 刷新
}
});
return view;
}
}
static class ViewHolder {
public TextView tv_app_name;
public TextView tv_app_info;
public TextView tv_progress_percent;
public Button bt_app_download;
public ProgressBar pb_download_progress;
}
}
MyApplication.java
[java] view plain copy
package com.example.downloadtest.app;
import java.util.HashMap;
import java.util.Map;
import android.app.Application;
import android.content.Intent;
import com.example.downloadtest.entity.DownloadItem;
import com.example.downloadtest.providers.downloads.DownloadService;
public class MyApplication extends Application {
public Map
public Map
public void onCreate() {
startDownloadService();
super.onCreate();
}
private void startDownloadService() {
Intent intent = new Intent();
intent.setClass(this, DownloadService.class);
startService(intent);
}
}
手机扫一扫
移动阅读更方便
你可能感兴趣的文章