Android 开发之文件下载,状态时显示下载进度,点击自动安装

2013年09月04日 15:51    发布者:reggae
在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装。
效果如图:


用于下载文件和显示现在进度的线程类如下:
001
package com.channelsoft.ahzyfis.util;
002
003
import java.io.File;
004
import java.io.FileOutputStream;
005
import java.io.InputStream;
006
import java.net.HttpURLConnection;
007
import java.net.URL;
008
009
import android.app.Notification;
010
import android.app.NotificationManager;
011
import android.app.PendingIntent;
012
import android.content.Context;
013
import android.content.Intent;
014
import android.net.Uri;
015
import android.os.Environment;
016
import android.os.Handler;
017
import android.os.Message;
018
import android.util.Log;
019
import android.widget.RemoteViews;
020
import android.widget.Toast;
021
022
import com.channelsoft.ahzyfis.AhzyFisActivity;
023
import com.channelsoft.ahzyfis.R;
024
025
037
public class AppFileDownUtils extends Thread {
038
039
private Context mContext;
040
private Handler mHandler;
041
private String mDownloadUrl; // 文件下载url,已做非空检查
042
private String mFileName;
043
private Message msg;
044
045
private final String APP_FOLDER = "DownDemo"; // sd卡应用目录
046
private final String APK_FOLDER = "apkFile"; // 下载apk文件目录
047
048
public static final int MSG_UNDOWN = 0; //未开始下载
049
public static final int MSG_DOWNING = 1; // 下载中
050
public static final int MSG_FINISH = 1; // 下载完成
051
public static final int MSG_FAILURE = 2;// 下载失败
052
053
private NotificationManager mNotifManager;
054
private Notification mDownNotification;
055
private RemoteViews mContentView; // 下载进度View
056
private PendingIntent mDownPendingIntent;
057
058
public AppFileDownUtils(Context context, Handler handler,
059
String downloadUrl, String fileName) {
060
mContext = context;
061
mHandler = handler;
062
mDownloadUrl = downloadUrl;
063
mFileName = fileName;
064
mNotifManager = (NotificationManager) mContext
065
.getSystemService(Context.NOTIFICATION_SERVICE);
066
msg = new Message();
067
}
068
069
@Override
070
public void run() {
071
try {
072
if (Environment.getExternalStorageState().equals(
073
Environment.MEDIA_MOUNTED)) {
074
Message downingMsg = new Message();
075
downingMsg.what = MSG_DOWNING;
076
mHandler.sendMessage(downingMsg);
077
// SD卡准备好
078
File sdcardDir = Environment.getExternalStorageDirectory();
079
// 文件存放路径: sdcard/DownDemo/apkFile
080
File folder = new File(sdcardDir + File.separator + APP_FOLDER
081
+ File.separator + APK_FOLDER);
082
if (!folder.exists()) {
083
//创建存放目录
084
folder.mkdir();
085
}
086
File saveFilePath = new File(folder, mFileName);
087
System.out.println(saveFilePath);
088
mDownNotification = new Notification(
089
android.R.drawable.stat_sys_download, mContext
090
.getString(R.string.notif_down_file), System
091
.currentTimeMillis());
092
mDownNotification.flags = Notification.FLAG_ONGOING_EVENT;
093
mDownNotification.flags = Notification.FLAG_AUTO_CANCEL;
094
mContentView = new RemoteViews(mContext.getPackageName(),
095
R.layout.custom_notification);
096
mContentView.setImageViewResource(R.id.downLoadIcon,
097
android.R.drawable.stat_sys_download);
098
mDownPendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
099
boolean downSuc = downloadFile(mDownloadUrl, saveFilePath);
100
if (downSuc) {
101
msg.what = MSG_FINISH;
102
Notification notification = new Notification(
103
android.R.drawable.stat_sys_download_done, mContext
104
.getString(R.string.downloadSuccess),
105
System.currentTimeMillis());
106
notification.flags = Notification.FLAG_ONGOING_EVENT;
107
notification.flags = Notification.FLAG_AUTO_CANCEL;
108
Intent intent = new Intent(Intent.ACTION_VIEW);
109
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
110
intent.setDataAndType(Uri.fromFile(saveFilePath),
111
"application/vnd.android.package-archive");
112
PendingIntent contentIntent = PendingIntent.getActivity(
113
mContext, 0, intent, 0);
114
notification.setLatestEventInfo(mContext, mContext
115
.getString(R.string.downloadSuccess), null,
116
contentIntent);
117
mNotifManager.notify(R.drawable.icon, notification);
118
} else {
119
msg.what = MSG_FAILURE;
120
Notification notification = new Notification(
121
android.R.drawable.stat_sys_download_done, mContext
122
.getString(R.string.downloadFailure),
123
System.currentTimeMillis());
124
notification.flags = Notification.FLAG_AUTO_CANCEL;
125
PendingIntent contentIntent = PendingIntent.getActivity(
126
mContext, 0, new Intent(), 0);
127
notification.setLatestEventInfo(mContext, mContext
128
.getString(R.string.downloadFailure), null,
129
contentIntent);
130
mNotifManager.notify(R.drawable.icon, notification);
131
}
132
133
} else {
134
Toast.makeText(mContext, Environment.getExternalStorageState(),
135
Toast.LENGTH_SHORT).show();
136
msg.what = MSG_FAILURE;
137
}
138
} catch (Exception e) {
139
Log.e(AhzyFisActivity.TAG, "AppFileDownUtils catch Exception:", e);
140
msg.what = MSG_FAILURE;
141
} finally {
142
mHandler.sendMessage(msg);
143
}
144
}
145
146
156
public boolean downloadFile(String downloadUrl, File saveFilePath) {
157
int fileSize = -1;
158
int downFileSize = 0;
159
boolean result = false;
160
int progress = 0;
161
try {
162
URL url = new URL(downloadUrl);
163
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
164
if (null == conn) {
165
return false;
166
}
167
// 读取超时时间 毫秒级
168
conn.setReadTimeout(10000);
169
conn.setRequestMethod("GET");
170
conn.setDoInput(true);
171
conn.connect();
172
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
173
fileSize = conn.getContentLength();
174
InputStream is = conn.getInputStream();
175
FileOutputStream fos = new FileOutputStream(saveFilePath);
176
byte[] buffer = new byte;
177
int i = 0;
178
int tempProgress = -1;
179
while ((i = is.read(buffer)) != -1) {
180
downFileSize = downFileSize + i;
181
// 下载进度
182
progress = (int) (downFileSize * 100.0 / fileSize);
183
fos.write(buffer, 0, i);
184
185
synchronized (this) {
186
if (downFileSize == fileSize) {
187
// 下载完成
188
mNotifManager.cancel(R.id.downLoadIcon);
189
} else if (tempProgress != progress) {
190
// 下载进度发生改变,则发送Message
191
mContentView.setTextViewText(R.id.progressPercent,
192
progress + "%");
193
mContentView.setProgressBar(R.id.downLoadProgress,
194
100, progress, false);
195
mDownNotification.contentView = mContentView;
196
mDownNotification.contentIntent = mDownPendingIntent;
197
mNotifManager.notify(R.id.downLoadIcon,
198
mDownNotification);
199
tempProgress = progress;
200
}
201
}
202
}
203
fos.flush();
204
fos.close();
205
is.close();
206
result = true;
207
} else {
208
result = false;
209
}
210
} catch (Exception e) {
211
result = false;
212
Log.e(AhzyFisActivity.TAG, "downloadFile catch Exception:", e);
213
}
214
return result;
215
}
216
}
在下载过程中,如果需要和主线程(UI Main Thread)通信,及时让主线程了解下载进度和状态,可用通过Handle向主线程发送Message
进度条显示的布局文件如下:
查看源码打印?
01
02
03
android:id="@+id/custom_notification"
04
xmlns:android="http://schemas.android.com/apk/res/android"
05
android:orientation="horizontal"
06
android:layout_width="fill_parent"
07
android:layout_height="fill_parent">
08
09
android:id="@+id/downLoadIcon"
10
android:layout_width="wrap_content"
11
android:layout_height="wrap_content"
12
android:layout_marginLeft="5dip"
13
android:layout_gravity="center_vertical"
14
/>
15
16
android:layout_height="fill_parent"
17
android:layout_width="wrap_content"
18
android:layout_marginLeft="5dip"
19
android:text="@string/downloadProgress"
20
android:gravity="center_vertical"
21
/>
22
23
android:id="@+id/downLoadProgress"
24
style="?android:attr/progressBarStyleHorizontal"
25
mce_style="?android:attr/progressBarStyleHorizontal"
26
android:layout_marginLeft="10dip"
27
android:layout_width="150dip"
28
android:layout_height="wrap_content"
29
android:layout_gravity="center_vertical"
30
/>
31
32
android:id="@+id/progressPercent"
33
android:layout_height="fill_parent"
34
android:layout_width="wrap_content"
35
android:layout_marginLeft="5dip"
36
android:gravity="center_vertical"
37
/>
38希望本文对广大安卓开发者有所帮助,感谢阅读本文。更多安卓技术问题欢迎加群探讨:278744577,验证码:eec,不写验证不予通过哟~