在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装。
效果如图:
用于下载文件和显示现在进度的线程类如下:
package com.channelsoft.ahzyfis.util;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;
import com.channelsoft.ahzyfis.AhzyFisActivity;
import com.channelsoft.ahzyfis.R;
/**
*
* <dl>
* <dt>AppFileDownUtils.java</dt>
* <dd>Description: 文件下载</dd>
* <dd>Copyright: Copyright (C) 2011</dd>
* <dd>Company: </dd>
* <dd>CreateDate: 2011-10-19</dd>
* </dl>
*
* @author ZhanHua
*/
public class AppFileDownUtils extends Thread {
private Context mContext;
private Handler mHandler;
private String mDownloadUrl; // 文件下载url,已做非空检查
private String mFileName;
private Message msg;
private final String APP_FOLDER = "DownDemo"; // sd卡应用目录
private final String APK_FOLDER = "apkFile"; // 下载apk文件目录
public static final int MSG_UNDOWN = 0; //未开始下载
public static final int MSG_DOWNING = 1; // 下载中
public static final int MSG_FINISH = 1; // 下载完成
public static final int MSG_FAILURE = 2;// 下载失败
private NotificationManager mNotifManager;
private Notification mDownNotification;
private RemoteViews mContentView; // 下载进度View
private PendingIntent mDownPendingIntent;
public AppFileDownUtils(Context context, Handler handler,
String downloadUrl, String fileName) {
mContext = context;
mHandler = handler;
mDownloadUrl = downloadUrl;
mFileName = fileName;
mNotifManager = (NotificationManager) mContext
.getSystemService(Context.NOTIFICATION_SERVICE);
msg = new Message();
}
@Override
public void run() {
try {
if (Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)) {
Message downingMsg = new Message();
downingMsg.what = MSG_DOWNING;
mHandler.sendMessage(downingMsg);
// SD卡准备好
File sdcardDir = Environment.getExternalStorageDirectory();
// 文件存放路径: sdcard/DownDemo/apkFile
File folder = new File(sdcardDir + File.separator + APP_FOLDER
+ File.separator + APK_FOLDER);
if (!folder.exists()) {
//创建存放目录
folder.mkdir();
}
File saveFilePath = new File(folder, mFileName);
System.out.println(saveFilePath);
mDownNotification = new Notification(
android.R.drawable.stat_sys_download, mContext
.getString(R.string.notif_down_file), System
.currentTimeMillis());
mDownNotification.flags = Notification.FLAG_ONGOING_EVENT;
mDownNotification.flags = Notification.FLAG_AUTO_CANCEL;
mContentView = new RemoteViews(mContext.getPackageName(),
R.layout.custom_notification);
mContentView.setImageViewResource(R.id.downLoadIcon,
android.R.drawable.stat_sys_download);
mDownPendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
boolean downSuc = downloadFile(mDownloadUrl, saveFilePath);
if (downSuc) {
msg.what = MSG_FINISH;
Notification notification = new Notification(
android.R.drawable.stat_sys_download_done, mContext
.getString(R.string.downloadSuccess),
System.currentTimeMillis());
notification.flags = Notification.FLAG_ONGOING_EVENT;
notification.flags = Notification.FLAG_AUTO_CANCEL;
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.setDataAndType(Uri.fromFile(saveFilePath),
"application/vnd.android.package-archive");
PendingIntent contentIntent = PendingIntent.getActivity(
mContext, 0, intent, 0);
notification.setLatestEventInfo(mContext, mContext
.getString(R.string.downloadSuccess), null,
contentIntent);
mNotifManager.notify(R.drawable.icon, notification);
} else {
msg.what = MSG_FAILURE;
Notification notification = new Notification(
android.R.drawable.stat_sys_download_done, mContext
.getString(R.string.downloadFailure),
System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent contentIntent = PendingIntent.getActivity(
mContext, 0, new Intent(), 0);
notification.setLatestEventInfo(mContext, mContext
.getString(R.string.downloadFailure), null,
contentIntent);
mNotifManager.notify(R.drawable.icon, notification);
}
} else {
Toast.makeText(mContext, Environment.getExternalStorageState(),
Toast.LENGTH_SHORT).show();
msg.what = MSG_FAILURE;
}
} catch (Exception e) {
Log.e(AhzyFisActivity.TAG, "AppFileDownUtils catch Exception:", e);
msg.what = MSG_FAILURE;
} finally {
mHandler.sendMessage(msg);
}
}
/**
*
* Desc:文件下载
*
* @param downloadUrl
* 下载URL
* @param saveFilePath
* 保存文件路径
* @return ture:下载成功 false:下载失败
*/
public boolean downloadFile(String downloadUrl, File saveFilePath) {
int fileSize = -1;
int downFileSize = 0;
boolean result = false;
int progress = 0;
try {
URL url = new URL(downloadUrl);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
if (null == conn) {
return false;
}
// 读取超时时间 毫秒级
conn.setReadTimeout(10000);
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.connect();
if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
fileSize = conn.getContentLength();
InputStream is = conn.getInputStream();
FileOutputStream fos = new FileOutputStream(saveFilePath);
byte[] buffer = new byte[1024];
int i = 0;
int tempProgress = -1;
while ((i = is.read(buffer)) != -1) {
downFileSize = downFileSize + i;
// 下载进度
progress = (int) (downFileSize * 100.0 / fileSize);
fos.write(buffer, 0, i);
synchronized (this) {
if (downFileSize == fileSize) {
// 下载完成
mNotifManager.cancel(R.id.downLoadIcon);
} else if (tempProgress != progress) {
// 下载进度发生改变,则发送Message
mContentView.setTextViewText(R.id.progressPercent,
progress + "%");
mContentView.setProgressBar(R.id.downLoadProgress,
100, progress, false);
mDownNotification.contentView = mContentView;
mDownNotification.contentIntent = mDownPendingIntent;
mNotifManager.notify(R.id.downLoadIcon,
mDownNotification);
tempProgress = progress;
}
}
}
fos.flush();
fos.close();
is.close();
result = true;
} else {
result = false;
}
} catch (Exception e) {
result = false;
Log.e(AhzyFisActivity.TAG, "downloadFile catch Exception:", e);
}
return result;
}
}
在下载过程中,如果需要和主线程(UI Main Thread)通信,及时让主线程了解下载进度和状态,可用通过Handle向主线程发送Message
进度条显示的布局文件如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="@+id/custom_notification"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView
android:id="@+id/downLoadIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dip"
android:layout_gravity="center_vertical"
/>
<TextView
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:layout_marginLeft="5dip"
android:text="@string/downloadProgress"
android:gravity="center_vertical"
/>
<ProgressBar
android:id="@+id/downLoadProgress"
style="?android:attr/progressBarStyleHorizontal"
mce_style="?android:attr/progressBarStyleHorizontal"
android:layout_marginLeft="10dip"
android:layout_width="150dip"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
/>
<TextView
android:id="@+id/progressPercent"
android:layout_height="fill_parent"
android:layout_width="wrap_content"
android:layout_marginLeft="5dip"
android:gravity="center_vertical"
/>
</LinearLayout>