`

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

阅读更多
在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装。

效果如图:






用于下载文件和显示现在进度的线程类如下:
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>
  • 大小: 17.9 KB
分享到:
评论

相关推荐

    pandas-1.3.5-cp37-cp37m-macosx_10_9_x86_64.zip

    pandas whl安装包,对应各个python版本和系统(具体看资源名字),找准自己对应的下载即可! 下载后解压出来是已.whl为后缀的安装包,进入终端,直接pip install pandas-xxx.whl即可,非常方便。 再也不用担心pip联网下载网络超时,各种安装不成功的问题。

    基于java的大学生兼职信息系统答辩PPT.pptx

    基于java的大学生兼职信息系统答辩PPT.pptx

    基于java的乐校园二手书交易管理系统答辩PPT.pptx

    基于java的乐校园二手书交易管理系统答辩PPT.pptx

    tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl

    tornado-6.4-cp38-abi3-musllinux_1_1_i686.whl

    Android Studio Ladybug(android-studio-2024.2.1.10-mac.zip.002)

    Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175

    基于ssm框架+mysql+jsp实现的监考安排与查询系统

    有学生和教师两种角色 登录和注册模块 考场信息模块 考试信息模块 点我收藏 功能 监考安排模块 考场类型模块 系统公告模块 个人中心模块: 1、修改个人信息,可以上传图片 2、我的收藏列表 账号管理模块 服务模块 eclipse或者idea 均可以运行 jdk1.8 apache-maven-3.6 mysql5.7及以上 tomcat 8.0及以上版本

    tornado-6.1b2-cp38-cp38-macosx_10_9_x86_64.whl

    tornado-6.1b2-cp38-cp38-macosx_10_9_x86_64.whl

    Android Studio Ladybug(android-studio-2024.2.1.10-mac.zip.001)

    Android Studio Ladybug 2024.2.1(android-studio-2024.2.1.10-mac.dmg)适用于macOS Intel系统,文件使用360压缩软件分割成两个压缩包,必须一起下载使用: part1: https://download.csdn.net/download/weixin_43800734/89954174 part2: https://download.csdn.net/download/weixin_43800734/89954175

    基于MATLAB车牌识别代码实现代码【含界面GUI】.zip

    matlab

    基于java的毕业生就业信息管理系统答辩PPT.pptx

    基于java的毕业生就业信息管理系统答辩PPT.pptx

    基于Web的毕业设计选题系统的设计与实现(springboot+vue+mysql+说明文档).zip

    随着高等教育的普及和毕业设计的日益重要,为了方便教师、学生和管理员进行毕业设计的选题和管理,我们开发了这款基于Web的毕业设计选题系统。 该系统主要包括教师管理、院系管理、学生管理等多个模块。在教师管理模块中,管理员可以新增、删除教师信息,并查看教师的详细资料,方便进行教师资源的分配和管理。院系管理模块则允许管理员对各个院系的信息进行管理和维护,确保信息的准确性和完整性。 学生管理模块是系统的核心之一,它提供了学生选题、任务书管理、开题报告管理、开题成绩管理等功能。学生可以在此模块中进行毕业设计的选题,并上传任务书和开题报告,管理员和教师则可以对学生的报告进行审阅和评分。 此外,系统还具备课题分类管理和课题信息管理功能,方便对毕业设计课题进行分类和归档,提高管理效率。在线留言功能则为学生、教师和管理员提供了一个交流互动的平台,可以就毕业设计相关问题进行讨论和解答。 整个系统设计简洁明了,操作便捷,大大提高了毕业设计的选题和管理效率,为高等教育的发展做出了积极贡献。

    机器学习(预测模型):2000年至2015年期间193个国家的预期寿命和相关健康因素的数据

    这个数据集来自世界卫生组织(WHO),包含了2000年至2015年期间193个国家的预期寿命和相关健康因素的数据。它提供了一个全面的视角,用于分析影响全球人口预期寿命的多种因素。数据集涵盖了从婴儿死亡率、GDP、BMI到免疫接种覆盖率等多个维度,为研究者提供了丰富的信息来探索和预测预期寿命。 该数据集的特点在于其跨国家的比较性,使得研究者能够识别出不同国家之间预期寿命的差异,并分析这些差异背后的原因。数据集包含22个特征列和2938行数据,涉及的变量被分为几个大类:免疫相关因素、死亡因素、经济因素和社会因素。这些数据不仅有助于了解全球健康趋势,还可以辅助制定公共卫生政策和社会福利计划。 数据集的处理包括对缺失值的处理、数据类型转换以及去重等步骤,以确保数据的准确性和可靠性。研究者可以使用这个数据集来探索如教育、健康习惯、生活方式等因素如何影响人们的寿命,以及不同国家的经济发展水平如何与预期寿命相关联。此外,数据集还可以用于预测模型的构建,通过回归分析等统计方法来预测预期寿命。 总的来说,这个数据集是研究全球健康和预期寿命变化的宝贵资源,它不仅提供了历史数据,还为未来的研究和政策制

    基于微信小程序的高校毕业论文管理系统小程序答辩PPT.pptx

    基于微信小程序的高校毕业论文管理系统小程序答辩PPT.pptx

    基于java的超市 Pos 收银管理系统答辩PPT.pptx

    基于java的超市 Pos 收银管理系统答辩PPT.pptx

    基于java的网上报名系统答辩PPT.pptx

    基于java的网上报名系统答辩PPT.pptx

    基于java的网上书城答辩PPT.pptx

    基于java的网上书城答辩PPT.pptx

    婚恋网站 SSM毕业设计 附带论文.zip

    婚恋网站 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B

    基于java的戒烟网站答辩PPT.pptx

    基于java的戒烟网站答辩PPT.pptx

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    基于微信小程序的“健康早知道”微信小程序答辩PPT.pptx

    机器学习(预测模型):自行车共享使用情况的数据集

    Capital Bikeshare 数据集是一个包含从2020年5月到2024年8月的自行车共享使用情况的数据集。这个数据集记录了华盛顿特区Capital Bikeshare项目中自行车的租赁模式,包括了骑行的持续时间、开始和结束日期时间、起始和结束站点、使用的自行车编号、用户类型(注册会员或临时用户)等信息。这些数据可以帮助分析和预测自行车共享系统的需求模式,以及了解用户行为和偏好。 数据集的特点包括: 时间范围:覆盖了四年多的时间,提供了长期的数据观察。 细节丰富:包含了每次骑行的详细信息,如日期、时间、天气条件、季节等,有助于深入分析。 用户分类:数据中区分了注册用户和临时用户,可以分析不同用户群体的使用习惯。 天气和季节因素:包含了天气情况和季节信息,可以研究这些因素对骑行需求的影响。 通过分析这个数据集,可以得出关于自行车共享使用模式的多种见解,比如一天中不同时间段的使用高峰、不同天气条件下的使用差异、季节性变化对骑行需求的影响等。这些信息对于城市规划者、交通管理者以及自行车共享服务提供商来说都是非常宝贵的,可以帮助他们优化服务、提高效率和满足用户需求。同时,这个数据集也

Global site tag (gtag.js) - Google Analytics