`

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
分享到:
评论

相关推荐

    android实现后台下载状态栏显示进度

    在Android开发中,后台下载是一项常见的需求,尤其是在处理大文件或者需要用户在其他应用界面同时进行操作时。本文将详细讲解如何实现一个Android应用,它能在后台执行文件下载任务,并在状态栏显示下载进度,下载...

    显示文件下载进度,下载完成并自动安装apk

    本话题将深入探讨如何实现"显示文件下载进度,下载完成并自动安装apk"这一功能,这在Android开发中尤为常见。 首先,我们需要理解文件下载的过程。当用户点击下载按钮时,应用会启动一个后台服务或使用异步任务来...

    android通知栏提示下载进度源码

    在Android开发中,通知栏(Notification)是向用户传达应用状态和信息的重要手段,尤其在后台运行时。"android通知栏提示下载进度源码"是一个示例项目,它展示了如何在Android的通知栏创建一个更新下载进度的提示。...

    状态栏显示进度的版本更新

    在“状态栏显示进度的版本更新”中,我们关注的是如何在用户界面中提供一个直观、友好的更新体验,特别是通过状态栏来展示下载进度。这种设计能够使用户在使用应用的同时,对后台的更新过程有清晰的认知,避免了因...

    android中DownloadManager实现版本更新,监听下载进度实例

    在Android开发中,DownloadManager是处理长时间下载操作的一个系统服务。通过使用DownloadManager,开发者可以实现应用的自动更新功能,并通过监听下载进度,向用户展示当前下载状态。下面详细介绍一下Download...

    Android 多文件下载进度条

    在Android开发中,实现多文件下载并展示进度条是一项常见的需求。这涉及到网络编程、线程管理、数据存储以及UI更新等多个方面的知识。下面将详细解释如何在Android中实现这一功能。 1. **网络编程**:Android中进行...

    Android 断点下载文件通知栏提示

    在Android开发中,断点下载是一项重要的功能,它允许用户在网络连接不稳定或者设备电量不足时暂停下载,并在后续时间继续从上次停止的地方开始,而无需重新下载整个文件。结合通知栏提示,可以提供用户友好的体验,...

    Android 自动更新 下载文件 APK

    为了不打扰用户,可以考虑在充电时或者Wi-Fi连接时自动下载更新,避免消耗用户的数据流量。 10. **安全问题**: 当下载APK时,确保只从可信源下载,以防止恶意软件。同时,应用的数字签名应保持一致,以验证更新...

    android从网络上下载文件

    在Android平台上,从网络下载文件是一项常见的任务,无论是更新应用、获取用户数据还是同步资源,都需要用到这个功能。...在实际开发中,还需要考虑错误处理、进度显示、多线程下载等问题,以提供更好的用户体验。

    DownAPKServiceDemo:Service下载apk通过notification显示下载进度 下载完成自动安装

    这个服务通过通知(notification)向用户展示下载进度,并在下载完成后自动进行安装。 【核心知识点】 1. **Android Service**:Service是Android系统中的一个组件,用于在后台执行长时间运行的操作,即使用户离开...

    android开发上传文件

    在Android开发中,上传文件是一项常见的任务,尤其在涉及到用户交互、数据同步或者服务端处理时更为重要。这里,我们主要关注的是如何在Android应用程序中实现文件上传到服务器的功能。这个场景通常涉及到网络编程和...

    Android 检查更新,文件下载后自动安装demo

    "Android检查更新,文件下载后自动安装demo"就是一个用于实现这一功能的示例项目。在这个项目中,开发者自定义了一个下载管理器,适用于Android 7.0及以上版本,解决了在不同Android系统版本中进行文件下载和更新的...

    android应用下载安装apk升级版本实现demo适配Android10

    本示例“android应用下载安装apk升级版本实现demo适配Android10”聚焦于如何在Android 10(API级别29)及更高版本中实现这一过程。以下是关于这一主题的详细知识: 1. **安全下载APK**:在Android 10中,为了保障...

    android 多线程下载,退出后返回后更新组件显示

    在Android开发中,多线程下载是一项常见的任务,特别是在处理大文件时,为了提高下载效率和用户体验,通常会采用多线程技术。本项目显然关注的是如何实现这一功能,并且在用户退出应用后,能够保存下载状态,在重新...

    android 多任务下载,并在下载管理界面刷新进度条

    在Android开发中,多任务下载是一项常见的需求,它允许用户同时下载多个文件,极大地提高了效率。而实时更新下载管理界面的进度条则是提供良好用户体验的关键。以下是对这一主题的详细阐述: 1. **多任务下载原理**...

    Android单个文件,断点下载

    在Android开发中,实现“单个文件的断点下载”是一项常见的需求,它涉及到多个关键技术和组件的协同工作。下面将详细阐述这个过程中的主要知识点。 首先,我们要理解什么是“断点下载”。断点下载允许用户在下载...

    Android-使用DownloadManager下载完apk自动提示安装的功能

    在Android应用开发中,有时我们需要实现一个功能,即使用系统内置的`DownloadManager`服务来下载APK文件,并在下载完成后自动提示用户进行安装。这个功能对于应用的更新或者安装外部资源非常实用。本文将详细讲解...

    android客户端与服务端文件上传及下载

    本章节将详细探讨如何实现Android客户端与服务端的文件上传及下载,包括使用进度条显示上传和下载状态。 一、Android客户端文件上传 1. 文件选择:首先,需要一个文件选择器组件,如`Intent Chooser`或自定义的...

    Android实例:多线程文件下载+在线音乐播放+清除下载文件

    在Android开发中,实现多线程文件下载、在线音乐播放以及清除下载文件是常见的功能需求。下面我们将逐一探讨这些知识点。 1. **Android多线程下载** 在Android中,由于主线程(UI线程)不能执行耗时操作,因此在...

    Android开发高仿下载管理界面

    在Android开发中,创建一个高仿的下载管理界面是一项常见的任务,这涉及到用户界面设计、多线程处理、网络通信以及文件操作等多个方面的技术。以下将详细解析这一过程中的关键知识点。 1. **用户界面设计**:...

Global site tag (gtag.js) - Google Analytics