首页 > 代码库 > Android 演示 DownloadManager 下载
Android 演示 DownloadManager 下载
本文内容
- 环境
- 项目结构
- 演示下载
- 参考资料
本文是 github 上 Trinea-common 和 Trinea-Demo 项目的一部分。(不知道此人攒了多久~ )
假设,现在有个下载 apk 包的需求,你大概能想到什么?
- 下载本身;
- 下载进度;
- 期间还能取消;
- 由于网络不好或中断,下载失败,还要能重试;
- 因为下载的是 apk,下载完还要能提示安装更好,而且,很多手机管理 app,还能静默安装;
- 还能在手机通知栏看到下载提示;
- 这些就涉及到 android.app.DownloadManager、android.content.BroadcastReceiver 和 android.os.Handler。
自己下载 Demo 调试一下~
下载 Demo(国外网站,网络不好的多刷新或者设置dl)
更多 Demo
环境
- Windows 2008 R2 64 位
- Eclipse ADT V22.6.2,Android 4.4.2(API 19)
- SAMSUNG GT-8618,Android OS 4.1.2
项目结构
图 1 项目结构
图 2 主程序
图 2 主程序
图 3 下载
(注意:顶部通知栏,是有下载图标的~)
package com.example.download.ui;
import java.io.File; import java.text.DecimalFormat; import com.example.download.R; import com.example.download.utils.DownloadManagerPro; import com.example.download.utils.PreferencesUtils; import android.annotation.SuppressLint; import android.app.Activity; import android.app.DownloadManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; /** * DownloadManagerDemo * * @author LN * @since 2014-1-8 * @version 1.0 */ public class DownloadManagerDemo extends Activity { public static final String DOWNLOAD_FOLDER_NAME = "Trinea"; public static final String DOWNLOAD_FILE_NAME = "MeiLiShuo.apk"; public static final String APK_URL = "http://img.meilishuo.net/css/images/AndroidShare/Meilishuo_3.6.1_10006.apk"; public static final String KEY_NAME_DOWNLOAD_ID = "downloadId"; private Button downloadButton; private ProgressBar downloadProgress; private TextView downloadTip; private TextView downloadSize; private TextView downloadPrecent; private Button downloadCancel; private DownloadManager downloadManager; private DownloadManagerPro downloadManagerPro; private long downloadId = 0; private MyHandler handler; private DownloadChangeObserver downloadObserver; private CompleteReceiver completeReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.download_manager_demo); handler = new MyHandler(); downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); downloadManagerPro = new DownloadManagerPro(downloadManager); // see android mainfest.xml, // accept minetype of cn.trinea.download.file Intent intent = getIntent(); if (intent != null) { /** * below android 4.2, intent.getDataString() is * file:///storage/sdcard1/Trinea/MeLiShuo.apk<br/> * equal or above 4.2 intent.getDataString() is * content://media/external/file/29669 */ Uri data = http://www.mamicode.com/intent.getData();>
以及自定义的 DownloadManagerPro 和 PreferencesUtils 类,代码如下所示:、
package com.example.download.utils; import java.lang.reflect.Method; import android.app.DownloadManager; import android.app.DownloadManager.Request; import android.database.Cursor; import android.net.Uri; import android.os.Build; /** * DownloadManagerPro */ public class DownloadManagerPro { public static final Uri CONTENT_URI = Uri .parse("content://downloads/my_downloads"); /** represents downloaded file above api 11 **/ public static final String COLUMN_LOCAL_FILENAME = "local_filename"; /** represents downloaded file below api 11 **/ public static final String COLUMN_LOCAL_URI = "local_uri"; public static final String METHOD_NAME_PAUSE_DOWNLOAD = "pauseDownload"; public static final String METHOD_NAME_RESUME_DOWNLOAD = "resumeDownload"; private static boolean isInitPauseDownload = false; private static boolean isInitResumeDownload = false; private static Method pauseDownload = null; private static Method resumeDownload = null; private DownloadManager downloadManager; public DownloadManagerPro(DownloadManager downloadManager) { this.downloadManager = downloadManager; } /** * get download status * * @param downloadId * @return */ public int getStatusById(long downloadId) { return getInt(downloadId, DownloadManager.COLUMN_STATUS); } /** * get downloaded byte, total byte * * @param downloadId * @return a int array with two elements * <ul> * <li>result[0] represents downloaded bytes, This will initially be * -1.</li> * <li>result[1] represents total bytes, This will initially be -1.</li> * </ul> */ public int[] getDownloadBytes(long downloadId) { int[] bytesAndStatus = getBytesAndStatus(downloadId); return new int[] { bytesAndStatus[0], bytesAndStatus[1] }; } /** * get downloaded byte, total byte and download status * * @param downloadId * @return a int array with three elements * <ul> * <li>result[0] represents downloaded bytes, This will initially be * -1.</li> * <li>result[1] represents total bytes, This will initially be -1.</li> * <li>result[2] represents download status, This will initially be * 0.</li> * </ul> */ public int[] getBytesAndStatus(long downloadId) { int[] bytesAndStatus = new int[] { -1, -1, 0 }; DownloadManager.Query query = new DownloadManager.Query() .setFilterById(downloadId); Cursor c = null; try { c = downloadManager.query(query); if (c != null && c.moveToFirst()) { bytesAndStatus[0] = c .getInt(c .getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)); bytesAndStatus[1] = c .getInt(c .getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)); bytesAndStatus[2] = c.getInt(c .getColumnIndex(DownloadManager.COLUMN_STATUS)); } } finally { if (c != null) { c.close(); } } return bytesAndStatus; } /** * pause download * * @param ids * the IDs of the downloads to be paused * @return the number of downloads actually paused, -1 if exception or * method not exist */ public int pauseDownload(long... ids) { initPauseMethod(); if (pauseDownload == null) { return -1; } try { return ((Integer) pauseDownload.invoke(downloadManager, ids)) .intValue(); } catch (Exception e) { /** * accept all exception, include ClassNotFoundException, * NoSuchMethodException, InvocationTargetException, * NullPointException */ e.printStackTrace(); } return -1; } /** * resume download * * @param ids * the IDs of the downloads to be resumed * @return the number of downloads actually resumed, -1 if exception or * method not exist */ public int resumeDownload(long... ids) { initResumeMethod(); if (resumeDownload == null) { return -1; } try { return ((Integer) resumeDownload.invoke(downloadManager, ids)) .intValue(); } catch (Exception e) { /** * accept all exception, include ClassNotFoundException, * NoSuchMethodException, InvocationTargetException, * NullPointException */ e.printStackTrace(); } return -1; } /** * whether exist pauseDownload and resumeDownload method in * {@link DownloadManager} * * @return */ public static boolean isExistPauseAndResumeMethod() { initPauseMethod(); initResumeMethod(); return pauseDownload != null && resumeDownload != null; } private static void initPauseMethod() { if (isInitPauseDownload) { return; } isInitPauseDownload = true; try { pauseDownload = DownloadManager.class.getMethod( METHOD_NAME_PAUSE_DOWNLOAD, long[].class); } catch (Exception e) { // accept all exception e.printStackTrace(); } } private static void initResumeMethod() { if (isInitResumeDownload) { return; } isInitResumeDownload = true; try { resumeDownload = DownloadManager.class.getMethod( METHOD_NAME_RESUME_DOWNLOAD, long[].class); } catch (Exception e) { // accept all exception e.printStackTrace(); } } /** * get download file name * * @param downloadId * @return */ public String getFileName(long downloadId) { return getString( downloadId, (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB ? COLUMN_LOCAL_URI : COLUMN_LOCAL_FILENAME)); } /** * get download uri * * @param downloadId * @return */ public String getUri(long downloadId) { return getString(downloadId, DownloadManager.COLUMN_URI); } /** * get failed code or paused reason * * @param downloadId * @return <ul> * <li>if status of downloadId is * {@link DownloadManager#STATUS_PAUSED}, return * {@link #getPausedReason(long)}</li> * <li>if status of downloadId is * {@link DownloadManager#STATUS_FAILED}, return * {@link #getErrorCode(long)}</li> * <li>if status of downloadId is neither * {@link DownloadManager#STATUS_PAUSED} nor * {@link DownloadManager#STATUS_FAILED}, return 0</li> * </ul> */ public int getReason(long downloadId) { return getInt(downloadId, DownloadManager.COLUMN_REASON); } /** * get paused reason * * @param downloadId * @return <ul> * <li>if status of downloadId is * {@link DownloadManager#STATUS_PAUSED}, return one of * {@link DownloadManager#PAUSED_WAITING_TO_RETRY}<br/> * {@link DownloadManager#PAUSED_WAITING_FOR_NETWORK}<br/> * {@link DownloadManager#PAUSED_QUEUED_FOR_WIFI}<br/> * {@link DownloadManager#PAUSED_UNKNOWN}</li> * <li>else return {@link DownloadManager#PAUSED_UNKNOWN}</li> * </ul> */ public int getPausedReason(long downloadId) { return getInt(downloadId, DownloadManager.COLUMN_REASON); } /** * get failed error code * * @param downloadId * @return one of {@link DownloadManager#ERROR_*} */ public int getErrorCode(long downloadId) { return getInt(downloadId, DownloadManager.COLUMN_REASON); } public static class RequestPro extends DownloadManager.Request { public static final String METHOD_NAME_SET_NOTI_CLASS = "setNotiClass"; public static final String METHOD_NAME_SET_NOTI_EXTRAS = "setNotiExtras"; private static boolean isInitNotiClass = false; private static boolean isInitNotiExtras = false; private static Method setNotiClass = null; private static Method setNotiExtras = null; /** * @param uri * the HTTP URI to download. */ public RequestPro(Uri uri) { super(uri); } /** * set noti class, only init once * * @param className * full class name */ public void setNotiClass(String className) { synchronized (this) { if (!isInitNotiClass) { isInitNotiClass = true; try { setNotiClass = Request.class.getMethod( METHOD_NAME_SET_NOTI_CLASS, CharSequence.class); } catch (Exception e) { // accept all exception e.printStackTrace(); } } } if (setNotiClass != null) { try { setNotiClass.invoke(this, className); } catch (Exception e) { /** * accept all exception, include ClassNotFoundException, * NoSuchMethodException, InvocationTargetException, * NullPointException */ e.printStackTrace(); } } } /** * set noti extras, only init once * * @param extras */ public void setNotiExtras(String extras) { synchronized (this) { if (!isInitNotiExtras) { isInitNotiExtras = true; try { setNotiExtras = Request.class .getMethod(METHOD_NAME_SET_NOTI_EXTRAS, CharSequence.class); } catch (Exception e) { // accept all exception e.printStackTrace(); } } } if (setNotiExtras != null) { try { setNotiExtras.invoke(this, extras); } catch (Exception e) { /** * accept all exception, include ClassNotFoundException, * NoSuchMethodException, InvocationTargetException, * NullPointException */ e.printStackTrace(); } } } } /** * get string column * * @param downloadId * @param columnName * @return */ private String getString(long downloadId, String columnName) { DownloadManager.Query query = new DownloadManager.Query() .setFilterById(downloadId); String result = null; Cursor c = null; try { c = downloadManager.query(query); if (c != null && c.moveToFirst()) { result = c.getString(c.getColumnIndex(columnName)); } } finally { if (c != null) { c.close(); } } return result; } /** * get int column * * @param downloadId * @param columnName * @return */ private int getInt(long downloadId, String columnName) { DownloadManager.Query query = new DownloadManager.Query() .setFilterById(downloadId); int result = -1; Cursor c = null; try { c = downloadManager.query(query); if (c != null && c.moveToFirst()) { result = c.getInt(c.getColumnIndex(columnName)); } } finally { if (c != null) { c.close(); } } return result; } }
package com.example.download.utils; import android.content.Context; import android.content.SharedPreferences; /** * PreferencesUtils, easy to get or put data */ public class PreferencesUtils { public static String PREFERENCE_NAME = "TrineaAndroidCommon"; /** * put string preferences * * @param context * @param key * The name of the preference to modify * @param value * The new value for the preference * @return True if the new values were successfully written to persistent * storage. */ public static boolean putString(Context context, String key, String value) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putString(key, value); return editor.commit(); } /** * get string preferences * * @param context * @param key * The name of the preference to retrieve * @return The preference value if it exists, or null. Throws * ClassCastException if there is a preference with this name that * is not a string * @see #getString(Context, String, String) */ public static String getString(Context context, String key) { return getString(context, key, null); } /** * get string preferences * * @param context * @param key * The name of the preference to retrieve * @param defaultValue * Value to return if this preference does not exist * @return The preference value if it exists, or defValue. Throws * ClassCastException if there is a preference with this name that * is not a string */ public static String getString(Context context, String key, String defaultValue) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getString(key, defaultValue); } /** * put int preferences * * @param context * @param key * The name of the preference to modify * @param value * The new value for the preference * @return True if the new values were successfully written to persistent * storage. */ public static boolean putInt(Context context, String key, int value) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putInt(key, value); return editor.commit(); } /** * get int preferences * * @param context * @param key * The name of the preference to retrieve * @return The preference value if it exists, or -1. Throws * ClassCastException if there is a preference with this name that * is not a int * @see #getInt(Context, String, int) */ public static int getInt(Context context, String key) { return getInt(context, key, -1); } /** * get int preferences * * @param context * @param key * The name of the preference to retrieve * @param defaultValue * Value to return if this preference does not exist * @return The preference value if it exists, or defValue. Throws * ClassCastException if there is a preference with this name that * is not a int */ public static int getInt(Context context, String key, int defaultValue) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getInt(key, defaultValue); } /** * put long preferences * * @param context * @param key * The name of the preference to modify * @param value * The new value for the preference * @return True if the new values were successfully written to persistent * storage. */ public static boolean putLong(Context context, String key, long value) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putLong(key, value); return editor.commit(); } /** * get long preferences * * @param context * @param key * The name of the preference to retrieve * @return The preference value if it exists, or -1. Throws * ClassCastException if there is a preference with this name that * is not a long * @see #getLong(Context, String, long) */ public static long getLong(Context context, String key) { return getLong(context, key, -1); } /** * get long preferences * * @param context * @param key * The name of the preference to retrieve * @param defaultValue * Value to return if this preference does not exist * @return The preference value if it exists, or defValue. Throws * ClassCastException if there is a preference with this name that * is not a long */ public static long getLong(Context context, String key, long defaultValue) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getLong(key, defaultValue); } /** * put float preferences * * @param context * @param key * The name of the preference to modify * @param value * The new value for the preference * @return True if the new values were successfully written to persistent * storage. */ public static boolean putFloat(Context context, String key, float value) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putFloat(key, value); return editor.commit(); } /** * get float preferences * * @param context * @param key * The name of the preference to retrieve * @return The preference value if it exists, or -1. Throws * ClassCastException if there is a preference with this name that * is not a float * @see #getFloat(Context, String, float) */ public static float getFloat(Context context, String key) { return getFloat(context, key, -1); } /** * get float preferences * * @param context * @param key * The name of the preference to retrieve * @param defaultValue * Value to return if this preference does not exist * @return The preference value if it exists, or defValue. Throws * ClassCastException if there is a preference with this name that * is not a float */ public static float getFloat(Context context, String key, float defaultValue) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getFloat(key, defaultValue); } /** * put boolean preferences * * @param context * @param key * The name of the preference to modify * @param value * The new value for the preference * @return True if the new values were successfully written to persistent * storage. */ public static boolean putBoolean(Context context, String key, boolean value) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = settings.edit(); editor.putBoolean(key, value); return editor.commit(); } /** * get boolean preferences, default is false * * @param context * @param key * The name of the preference to retrieve * @return The preference value if it exists, or false. Throws * ClassCastException if there is a preference with this name that * is not a boolean * @see #getBoolean(Context, String, boolean) */ public static boolean getBoolean(Context context, String key) { return getBoolean(context, key, false); } /** * get boolean preferences * * @param context * @param key * The name of the preference to retrieve * @param defaultValue * Value to return if this preference does not exist * @return The preference value if it exists, or defValue. Throws * ClassCastException if there is a preference with this name that * is not a boolean */ public static boolean getBoolean(Context context, String key, boolean defaultValue) { SharedPreferences settings = context.getSharedPreferences( PREFERENCE_NAME, Context.MODE_PRIVATE); return settings.getBoolean(key, defaultValue); } }
参考资料
- Trinea-common
在 android dialog中使用Autocompletetext
大型网站架构设计-Solr
mysql哈希索引
android学习笔记(32)网格视图(GridView )和图形切换器(ImageSwi...
android学习笔记(31)可展开的列表组件(ExpandableListView )
Android 演示 DownloadManager 下载
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。