在github上面苦苦寻找都木有找到有关Android自带下载器DownloadManager多并发下载的,于是就决定自己试试写一个。
先上个图:
我的上篇文章
http://blog.csdn.net/u013277740/article/details/51737080
只实现了单个下载安装,这次升级一下
实现步骤:
1、初始化一个缓存线程池
cachedThreadPool = Executors.newCachedThreadPool();
1
2、在渲染每一条数据的时候往里面加任务
private void initView() {
mRvList.setLayoutManager(new LinearLayoutManager(this));
mDownloadAdapter = new CommonAdapter<Download>(this, R.layout.listitem_mul, mList) {
@Override
protected void convert(ViewHolder holder, final Download download, int position) {
holder.setText(R.id.tv_name, download.getName());
//往线程池中增加任务
cachedThreadPool.execute(new DownLoadTask(holder, download, position));
final NumberProgressBar numberBar = holder.getView(R.id.number_download);
holder.setOnClickListener(R.id.btn_install, new View.OnClickListener() {
@Override
public void onClick(View v) {
if (numberBar.getProgress() == 100) {
install(MulActivity.this, download.getLastDownLoadId());
}
}
});
}
};
mRvList.setAdapter(mDownloadAdapter);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
3、更新UI
//转换到主线程
runOnUiThread(new Runnable() {
@Override
public void run() {
NumberProgressBar numberBar = holder.getView(R.id.number_download);
numberBar.setProgress(progress);
}
});
1
2
3
4
5
6
7
8
具体代码如下:
1、MulActivity
package com.zx.download;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
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.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import com.daimajia.numberprogressbar.NumberProgressBar;
import com.zhy.adapter.recyclerview.CommonAdapter;
import com.zhy.adapter.recyclerview.base.ViewHolder;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import butterknife.Bind;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class MulActivity extends AppCompatActivity {
public static final String DOWNLOAD_ID = "download_id";
@Bind(R.id.rv_list)
RecyclerView mRvList;
private DownloadChangeObserver downloadObserver;
public static final Uri CONTENT_URI = Uri.parse("content://downloads/my_downloads");
private ExecutorService cachedThreadPool;
private List<Download> mList = new ArrayList<>();
private CommonAdapter mDownloadAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_mul);
ButterKnife.bind(this);
initData();
cachedThreadPool = Executors.newCachedThreadPool();
}
private void initData() {
for (int i = 0; i < Contans.URLS.length; i++) {
Download download = new Download();
download.setFileName(Contans.FILE_NAMES[i]);
download.setName(Contans.NAMES[i]);
download.setTitle(Contans.TITLES[i]);
download.setDescription(Contans.DESCRIPTIONS[i]);
download.setDownLoadUrl(Contans.URLS[i]);
mList.add(download);
}
}
private void initView() {
mRvList.setLayoutManager(new LinearLayoutManager(this));
mDownloadAdapter = new CommonAdapter<Download>(this, R.layout.listitem_mul, mList) {
@Override
protected void convert(ViewHolder holder, final Download download, int position) {
holder.setText(R.id.tv_name, download.getName());
cachedThreadPool.execute(new DownLoadTask(holder, download, position));
final NumberProgressBar numberBar = holder.getView(R.id.number_download);
holder.setOnClickListener(R.id.btn_install, new View.OnClickListener() {
@Override
public void onClick(View v) {
if (numberBar.getProgress() == 100) {
install(MulActivity.this, download.getLastDownLoadId());
}
}
});
}
};
mRvList.setAdapter(mDownloadAdapter);
}
@OnClick(R.id.btn_downs)
public void onViewClicked() {
initView();
}
public class DownLoadTask implements Runnable {
private ViewHolder holder;
private Download downLoad;
private int position;
public DownLoadTask(ViewHolder holder, Download download, int position) {
this.holder = holder;
this.downLoad = download;
this.position = position;
}
@Override
public void run() {
downLoadFile(downLoad);
}
private void downLoadFile(Download downLoad) {
//1.得到下载对象
DownloadManager dowanloadmanager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
//2.创建下载请求对象,并且把下载的地址放进去
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(downLoad.getDownLoadUrl()));
//3.给下载的文件指定路径
request.setDestinationInExternalFilesDir(MulActivity.this, Environment.DIRECTORY_DOWNLOADS, downLoad.getFileName());
//4.设置显示在文件下载Notification(通知栏)中显示的文字。6.0的手机Description不显示
request.setTitle(downLoad.getTitle());
request.setDescription(downLoad.getDescription());
//5更改服务器返回的minetype为android包类型
request.setMimeType("application/vnd.android.package-archive");
//6.设置在什么连接状态下执行下载操作
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
//7. 设置为可被媒体扫描器找到
request.allowScanningByMediaScanner();
//8. 设置为可见和可管理
request.setVisibleInDownloadsUi(true);
long lastDownloadId = dowanloadmanager.enqueue(request);
downLoad.setLastDownLoadId(lastDownloadId);
//10.采用内容观察者模式实现进度
downloadObserver = new DownloadChangeObserver(null, holder, downLoad, position);
getContentResolver().registerContentObserver(CONTENT_URI, true, downloadObserver);
}
}
//用于显示下载进度
class DownloadChangeObserver extends ContentObserver {
private ViewHolder holder;
private Download downLoad;
private int position;
public DownloadChangeObserver(Handler handler, ViewHolder holder, Download download, int position) {
super(handler);
this.holder = holder;
this.downLoad = download;
this.position = position;
}
@Override
public void onChange(boolean selfChange) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downLoad.getLastDownLoadId());
DownloadManager dManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
final Cursor cursor = dManager.query(query);
if (cursor != null && cursor.moveToFirst()) {
final int totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
final int currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
int totalSize = cursor.getInt(totalColumn);
int currentSize = cursor.getInt(currentColumn);
float percent = (float) currentSize / (float) totalSize;
final int progress = Math.round(percent * 100);
runOnUiThread(new Runnable() {
@Override
public void run() {
NumberProgressBar numberBar = holder.getView(R.id.number_download);
numberBar.setProgress(progress);
}
});
Log.v("progress" + downLoad.getLastDownLoadId(), progress + "");
}
}
}
@Override
protected void onDestroy() {
super.onDestroy();
getContentResolver().unregisterContentObserver(downloadObserver);
}
//安装
private void install(Context context, long downloadId) {
Intent install = new Intent(Intent.ACTION_VIEW);
File apkFile = queryDownloadedApk(context, downloadId);
install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
//通过downLoadId查询下载的apk,解决6.0以后安装的问题
public static File queryDownloadedApk(Context context, long downloadId) {
File targetApkFile = null;
DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
if (downloadId != -1) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
Cursor cur = downloader.query(query);
if (cur != null) {
if (cur.moveToFirst()) {
String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
if (!TextUtils.isEmpty(uriString)) {
targetApkFile = new File(Uri.parse(uriString).getPath());
}
}
cur.close();
}
}
return targetApkFile;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
2、activity_mul.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
android:orientation="vertical"
tools:context="com.zx.download.MainActivity">
<Button
android:id="@+id/btn_downs"
android:text="开始"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<android.support.v7.widget.RecyclerView
android:id="@+id/rv_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
3、Contans
package com.zx.download;
/**
* Created by user on 2017/6/19.
*/
public class Contans {
private static String NETURL_WEIXIN = "http://gdown.baidu.com/data/wisegame/8d5889f722f640c8/weixin_800.apk";
private static String NETURL_QQ = "http://gdown.baidu.com/data/wisegame/41a04ccb443cd61a/QQ_692.apk";
private static String NETURL_WANGYIYUN = "http://gdown.baidu.com/data/wisegame/9bfeb688ff2e0a19/wangyiyunyinle_95.apk";
private static String NETURL_KUWO = "http://gdown.baidu.com/data/wisegame/82337e10d2a72e61/kuwoyinle_8474.apk";
public static final String FILE_NAMES[] = {"weixin1.0.apk", "qq1.0.apk","wyy1.0.apk", "kuwo1.0.apk"};
public static final String NAMES[] = {"微信1.0", "QQ1.0","网易云音乐1.0", "酷我音乐1.0"};
public static final String URLS[] = {NETURL_WEIXIN, NETURL_QQ, NETURL_WANGYIYUN, NETURL_KUWO};
public static final String TITLES[] = {"weixin1.0", "qq1.0","wyy1.0", "kuwo1.0"};
public static final String DESCRIPTIONS[] = {"1、新增朋友圈","1、新增QQ空间","1、新增云音乐","1、新增酷我调频"};
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
4、Download
package com.zx.download;
import java.io.Serializable;
/**
* Created by user on 2017/6/19.
*/
public class Download implements Serializable {
private long lastDownLoadId;
//weixin.apk
private String fileName;
//weixin1.0
private String name;
private String downLoadUrl;
//通知栏
private String title;
private String description;
public String getDownLoadUrl() {
return downLoadUrl;
}
public void setDownLoadUrl(String downLoadUrl) {
this.downLoadUrl = downLoadUrl;
}
public long getLastDownLoadId() {
return lastDownLoadId;
}
public void setLastDownLoadId(long lastDownLoadId) {
this.lastDownLoadId = lastDownLoadId;
}
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
5、UpdataBroadcastReceiver
package com.zx.download;
import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.text.TextUtils;
import java.io.File;
import cn.trinea.android.common.util.PreferencesUtils;
/**
* Created by Administrator on 2016/9/20.
*/
public class UpdataBroadcastReceiver extends BroadcastReceiver {
@SuppressLint("NewApi")
public void onReceive(Context context, Intent intent) {
long downLoadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
long cacheDownLoadId = PreferencesUtils.getLong(context, MainActivity.DOWNLOAD_ID);
if (cacheDownLoadId == downLoadId) {
install(context);
}
}
private void install(Context context){
Intent install = new Intent(Intent.ACTION_VIEW);
File apkFile = queryDownloadedApk(context);
install.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
//通过downLoadId查询下载的apk,解决6.0以后安装的问题
public static File queryDownloadedApk(Context context) {
File targetApkFile = null;
DownloadManager downloader = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
long downloadId = PreferencesUtils.getLong(context, MainActivity.DOWNLOAD_ID);
if (downloadId != -1) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(downloadId);
query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
Cursor cur = downloader.query(query);
if (cur != null) {
if (cur.moveToFirst()) {
String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
if (!TextUtils.isEmpty(uriString)) {
targetApkFile = new File(Uri.parse(uriString).getPath());
}
}
cur.close();
}
}
return targetApkFile;
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
6、AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.zx.download">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".UpdataBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
</intent-filter>
</receiver>
<activity android:name=".MulActivity">
</activity>
</application>
</manifest>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
7、build.gradle
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.zx.download"
minSdkVersion 14
targetSdkVersion 23
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.2.1'
compile 'com.daimajia.numberprogressbar:library:1.4@aar'
compile 'cn.trinea.android.common:trinea-android-common:4.2.15'
compile('com.github.afollestad.material-dialogs:core:0.8.5.7@aar') {
transitive = true
}
compile 'com.zhy:base-rvadapter:3.0.3'
compile 'com.jakewharton:butterknife:7.0.1'
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
附加一个小功能,怎么判断所有的下载任务都完成了呢?
这里用SparseArray简单实现下
1、实例化一个SparseArray和计数变量
private SparseArray<Integer> progressArray = new SparseArray<>();
private int progressCount;
1
2
3
2、在downLoadFile方法中,把每个Key放进去,value都赋值为0
long lastDownloadId =dowanloadmanager.enqueue(request);
downLoad.setLastDownLoadId(lastDownloadId);
//把每个key放入map中
progressArray.put((int)lastDownloadId, 0);
1
2
3
4
5
3、在onChange方法中简单处理
float percent = (float) currentSize / (float) totalSize;
final int progress = Math.round(percent * 100);
runOnUiThread(new Runnable() {
@Override
public void run() {
NumberProgressBar numberBar = holder.getView(R.id.number_download);
numberBar.setProgress(progress);
if(progress == 100) {
int id = (int)downLoad.getLastDownLoadId();
if(progressArray.get(id) == 0) {
progressArray.put(id, progress);
Log.v("progress === " + downLoad.getLastDownLoadId(), progress + "");
progressCount ++;
if(progressCount == mList.size()) {
Log.v("progress === ","下载完成。。。。。。");
progressCount = 0;
}
}
}
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
最后附上Github源码:
https://github.com/MrXiong/MaterialDownLoad
————————————————
版权声明:本文为CSDN博主「大雄童鞋」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013277740/article/details/73467980