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

时间:2021-12-25 07:19:46

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

效果如图:

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

用于下载文件和显示现在进度的线程类如下:

[java] 
view plain
copy
  1. package com.channelsoft.ahzyfis.util;
  2. import java.io.File;
  3. import java.io.FileOutputStream;
  4. import java.io.InputStream;
  5. import java.net.HttpURLConnection;
  6. import java.net.URL;
  7. import android.app.Notification;
  8. import android.app.NotificationManager;
  9. import android.app.PendingIntent;
  10. import android.content.Context;
  11. import android.content.Intent;
  12. import android.net.Uri;
  13. import android.os.Environment;
  14. import android.os.Handler;
  15. import android.os.Message;
  16. import android.util.Log;
  17. import android.widget.RemoteViews;
  18. import android.widget.Toast;
  19. import com.channelsoft.ahzyfis.AhzyFisActivity;
  20. import com.channelsoft.ahzyfis.R;
  21. /**
  22. *
  23. * <dl>
  24. * <dt>AppFileDownUtils.java</dt>
  25. * <dd>Description: 文件下载</dd>
  26. * <dd>Copyright: Copyright (C) 2011</dd>
  27. * <dd>Company: </dd>
  28. * <dd>CreateDate: 2011-10-19</dd>
  29. * </dl>
  30. *
  31. * @author ZhanHua
  32. */
  33. public class AppFileDownUtils extends Thread {
  34. private Context mContext;
  35. private Handler mHandler;
  36. private String mDownloadUrl; // 文件下载url,已做非空检查
  37. private String mFileName;
  38. private Message msg;
  39. private final String APP_FOLDER = "DownDemo"; // sd卡应用目录
  40. private final String APK_FOLDER = "apkFile"; // 下载apk文件目录
  41. public static final int MSG_UNDOWN = 0; //未开始下载
  42. public static final int MSG_DOWNING = 1; // 下载中
  43. public static final int MSG_FINISH = 1; // 下载完成
  44. public static final int MSG_FAILURE = 2;// 下载失败
  45. private NotificationManager mNotifManager;
  46. private Notification mDownNotification;
  47. private RemoteViews mContentView; // 下载进度View
  48. private PendingIntent mDownPendingIntent;
  49. public AppFileDownUtils(Context context, Handler handler,
  50. String downloadUrl, String fileName) {
  51. mContext = context;
  52. mHandler = handler;
  53. mDownloadUrl = downloadUrl;
  54. mFileName = fileName;
  55. mNotifManager = (NotificationManager) mContext
  56. .getSystemService(Context.NOTIFICATION_SERVICE);
  57. msg = new Message();
  58. }
  59. @Override
  60. public void run() {
  61. try {
  62. if (Environment.getExternalStorageState().equals(
  63. Environment.MEDIA_MOUNTED)) {
  64. Message downingMsg = new Message();
  65. downingMsg.what = MSG_DOWNING;
  66. mHandler.sendMessage(downingMsg);
  67. // SD卡准备好
  68. File sdcardDir = Environment.getExternalStorageDirectory();
  69. // 文件存放路径: sdcard/DownDemo/apkFile
  70. File folder = new File(sdcardDir + File.separator + APP_FOLDER
  71. + File.separator + APK_FOLDER);
  72. if (!folder.exists()) {
  73. //创建存放目录
  74. folder.mkdir();
  75. }
  76. File saveFilePath = new File(folder, mFileName);
  77. System.out.println(saveFilePath);
  78. mDownNotification = new Notification(
  79. android.R.drawable.stat_sys_download, mContext
  80. .getString(R.string.notif_down_file), System
  81. .currentTimeMillis());
  82. mDownNotification.flags = Notification.FLAG_ONGOING_EVENT;
  83. mDownNotification.flags = Notification.FLAG_AUTO_CANCEL;
  84. mContentView = new RemoteViews(mContext.getPackageName(),
  85. R.layout.custom_notification);
  86. mContentView.setImageViewResource(R.id.downLoadIcon,
  87. android.R.drawable.stat_sys_download);
  88. mDownPendingIntent = PendingIntent.getActivity(mContext, 0, new Intent(), 0);
  89. boolean downSuc = downloadFile(mDownloadUrl, saveFilePath);
  90. if (downSuc) {
  91. msg.what = MSG_FINISH;
  92. Notification notification = new Notification(
  93. android.R.drawable.stat_sys_download_done, mContext
  94. .getString(R.string.downloadSuccess),
  95. System.currentTimeMillis());
  96. notification.flags = Notification.FLAG_ONGOING_EVENT;
  97. notification.flags = Notification.FLAG_AUTO_CANCEL;
  98. Intent intent = new Intent(Intent.ACTION_VIEW);
  99. intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
  100. intent.setDataAndType(Uri.fromFile(saveFilePath),
  101. "application/vnd.android.package-archive");
  102. PendingIntent contentIntent = PendingIntent.getActivity(
  103. mContext, 0, intent, 0);
  104. notification.setLatestEventInfo(mContext, mContext
  105. .getString(R.string.downloadSuccess), null,
  106. contentIntent);
  107. mNotifManager.notify(R.drawable.icon, notification);
  108. } else {
  109. msg.what = MSG_FAILURE;
  110. Notification notification = new Notification(
  111. android.R.drawable.stat_sys_download_done, mContext
  112. .getString(R.string.downloadFailure),
  113. System.currentTimeMillis());
  114. notification.flags = Notification.FLAG_AUTO_CANCEL;
  115. PendingIntent contentIntent = PendingIntent.getActivity(
  116. mContext, 0, new Intent(), 0);
  117. notification.setLatestEventInfo(mContext, mContext
  118. .getString(R.string.downloadFailure), null,
  119. contentIntent);
  120. mNotifManager.notify(R.drawable.icon, notification);
  121. }
  122. } else {
  123. Toast.makeText(mContext, Environment.getExternalStorageState(),
  124. Toast.LENGTH_SHORT).show();
  125. msg.what = MSG_FAILURE;
  126. }
  127. } catch (Exception e) {
  128. Log.e(AhzyFisActivity.TAG, "AppFileDownUtils catch Exception:", e);
  129. msg.what = MSG_FAILURE;
  130. } finally {
  131. mHandler.sendMessage(msg);
  132. }
  133. }
  134. /**
  135. *
  136. * Desc:文件下载
  137. *
  138. * @param downloadUrl
  139. *            下载URL
  140. * @param saveFilePath
  141. *            保存文件路径
  142. * @return ture:下载成功 false:下载失败
  143. */
  144. public boolean downloadFile(String downloadUrl, File saveFilePath) {
  145. int fileSize = -1;
  146. int downFileSize = 0;
  147. boolean result = false;
  148. int progress = 0;
  149. try {
  150. URL url = new URL(downloadUrl);
  151. HttpURLConnection conn = (HttpURLConnection) url.openConnection();
  152. if (null == conn) {
  153. return false;
  154. }
  155. // 读取超时时间 毫秒级
  156. conn.setReadTimeout(10000);
  157. conn.setRequestMethod("GET");
  158. conn.setDoInput(true);
  159. conn.connect();
  160. if (conn.getResponseCode() == HttpURLConnection.HTTP_OK) {
  161. fileSize = conn.getContentLength();
  162. InputStream is = conn.getInputStream();
  163. FileOutputStream fos = new FileOutputStream(saveFilePath);
  164. byte[] buffer = new byte[1024];
  165. int i = 0;
  166. int tempProgress = -1;
  167. while ((i = is.read(buffer)) != -1) {
  168. downFileSize = downFileSize + i;
  169. // 下载进度
  170. progress = (int) (downFileSize * 100.0 / fileSize);
  171. fos.write(buffer, 0, i);
  172. synchronized (this) {
  173. if (downFileSize == fileSize) {
  174. // 下载完成
  175. mNotifManager.cancel(R.id.downLoadIcon);
  176. } else if (tempProgress != progress) {
  177. // 下载进度发生改变,则发送Message
  178. mContentView.setTextViewText(R.id.progressPercent,
  179. progress + "%");
  180. mContentView.setProgressBar(R.id.downLoadProgress,
  181. 100, progress, false);
  182. mDownNotification.contentView = mContentView;
  183. mDownNotification.contentIntent = mDownPendingIntent;
  184. mNotifManager.notify(R.id.downLoadIcon,
  185. mDownNotification);
  186. tempProgress = progress;
  187. }
  188. }
  189. }
  190. fos.flush();
  191. fos.close();
  192. is.close();
  193. result = true;
  194. } else {
  195. result = false;
  196. }
  197. } catch (Exception e) {
  198. result = false;
  199. Log.e(AhzyFisActivity.TAG, "downloadFile catch Exception:", e);
  200. }
  201. return result;
  202. }
  203. }

在下载过程中,如果需要和主线程(UI Main Thread)通信,及时让主线程了解下载进度和状态,可用通过Handle向主线程发送Message

进度条显示的布局文件如下:

[html] 
view plain
copy
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout
  3. android:id="@+id/custom_notification"
  4. xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:orientation="horizontal"
  6. android:layout_width="fill_parent"
  7. android:layout_height="fill_parent">
  8. <ImageView
  9. 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. <TextView
  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. <ProgressBar
  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. <TextView
  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. </LinearLayout>