1、app升级下载现在不推荐使用downloadmanager下载:
原因有下面的几个方面:
(1)三星note系列部分手机需要手动打开这个权限才能用这个功能,而有些国产手机更加nb了直接个阉割了(downloadmanager),所以考虑到手机的适配性,最后自己编写app下载的后台代码
2、但是这里还是对downloadmanager下载进行一些详细的分析,很多下载的思路还是值得借鉴的
1、首先后台的apk的搭建
1、打开本地Tomcat服务器,放入一个Apk文件
apk存放在webapps/root目录下
// 首先确保浏览器能够访问http://localhost:8080/123456.apk
下面我将内容大致分为以下几个部分:
(1)App版本检测
(2)Apk下载
(3)Apk更新安装
(4)对以上功能进行封装
基于以上4部分,我们逐一展开。
1.App版本检测:
要实现App的更新下载,我们上面介绍了,前提是服务器要保存一个App的版本号(通常的方式是保存versionCode,当然你要对比versionName也没关系)。当用户去手动检测版本,或者进入首页自动检测时,第一步是需要请求服务器的版本号,拿到版本号之后与当前App版本号(当前版本号可通过PackageInfo获取)进行对比。服务器返回的版本号大于当前App版本号,证明App已经有更新,那么进入第2步。
2.Apk下载
Apk文件是保存在服务器的。我们可以通过Http流将其下载到本地手机,然后更新安装。Android中下载的方式很多种:HttpUrlConnection,Retrofit,okHttp,以及Android原生的下载工具类DownLoadManager 等等。我们采用的方式是Google推荐的下载工具类DownLoadManager。关于DownLoadManager的使用其实很简单,简单概括如下:
(1)通过getSystemService获取DownLoadManager。
(2)初始化DownLoadManager的Request,构建下载请求。
(3)调用DownLoadManager的enqueue异步发起请求,该方法返回值为标识当前下载任务的id,即downloadId。
(4)当下载完成后,系统会发出条件为android.intent.action.DOWNLOAD_COMPLETE的广播,我们可以自定义广播接受器,然后在onReceive中处理下载完成的逻辑即可。
详细使用方式大家可以参考网上的教程,此处就不再赘述。
上面通过下载啰嗦了一堆。此时我们要想一个问题:当我们下载完成后,并没有安装。当用户再次进入App时该如何操作?
有朋友会说,那就再去下载一次,然后继续执行更新安装呀!哈哈,这种方式是没有错误的,但是如果用户恶意行为,每次下载完成都不安装,那我们岂不是每次都要去下载100次,1000次。。(然后手机boom!!!)这种方式肯定是不能采用的。那么我们该如何解决呢?
很简单,当我们在下载之前,先去指定的文件夹下查看有木有已经下载好的Apk,并且该Apk的版本是高于本App的版本,此时我们就去执行安装操作。如果上面条件不成立,此时再去执行下载操作。
3.Apk更新安装
相信大家对于如何安装一个Apk都比较熟悉吧,原理也是比较简单的。
(1)通过downloadId获取下载的Uri。
(2)将Uri设置到Itent的setDataAndType作为启动条件。
(3)调用startActivity启动对应Intent即可。
以上3步,即可完成App的更新功能。
整体的流程很清晰:
版本检测 → Apk下载 (检查是否存在未安装的Apk) → Apk安装 → 完成更新
下面,通过代码来具体分析整个流程:
关于App版本检测其实就是一个Http请求,不再多说。我们从Apk下载开始:
上面我们提到,在下载之前需要去检测是否存在已经下载的Apk。通过什么获取呢?没错,肯定是downloadId了。
1> 如果存在downloadId,那么我们通过downloadId获取当前下载的状态status。status分为成功,失败两种状态。
(1)当status为成功状态时,即已经下载完成,我们就通过downloadId获取下载文件的Uri。然后可以通过Uri获取PackageInfo,与当前App进行包名和版本号的对比,当包名相同,并且当前版本号是小于下载的Apk版本号两个条件同时成立时,直接执行安装操作。否则,执行remove,通过downloadId删除下载任务以及文件,继续执行下载。
(2)当status为失败状态时,即下载未完成,我们就直接执行重新下载即可。
2> 如果不存在downloadId,即没有下载过Apk,执行下载即可。
下载完成后,系统会发出广播,在广播中,我们对比downloadId是否相同,相同情况下,直接通过downloadId获取Uri,然后跳转到安装界面,提示用户安装即可:
所以,别忘了在下载之前要先将该大喇叭(广播接受器)注册。
最后,当我们安装完成后,再次进入App,就将其已下载的Apk文件进行删除(将该方法放在onCreate生命周期中即可):
上面通过downloadApk获取下载文件的地址。downloadApk地址是在下载完成后广播接收器中保存的。
通过上面的步骤,我们就完成了App更新下载安装的全部工作。相信大家也有了更深的认识和理解。
下面博客:
http://chuansong.me/n/1090429551927
http://chuansong.me/n/1090429551927
也是对downloadManger做了详细的解释
接下来我们看下代码
程序的框架如下所示:
package co.huiqu.webapp;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.View;
import co.huiqu.webapp.download.DownLoadUtils;
import co.huiqu.webapp.download.DownloadApk;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
//1.注册下载广播接收器
DownloadApk.registerBroadcast(this);
//2.apk按照成功之后再次进场到app删除已存在的Apk
DownloadApk.removeFile/**/(this);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
/* String packageName = "com.android.providers.downloads";
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + packageName));
startActivity(intent);*/
//3.如果手机已经启动下载程序,执行downloadApk。否则跳转到设置界面
if (DownLoadUtils.getInstance(getApplicationContext()).canDownload()) {
//DownloadApk.downloadApk(getApplicationContext(), "http://www.huiqu.co/public/download/apk/huiqu.apk", "Hobbees更新", "Hobbees");
DownloadApk.downloadApk(getApplicationContext(), "http://10.12.8.13:8080/123456.apk", "酷狗更新", "Hobbees下载");
} else {
DownLoadUtils.getInstance(getApplicationContext()).skipToDownloadManager();
}
}
});
}
@Override
protected void onDestroy() {
//4.反注册广播接收器
DownloadApk.unregisterBroadcast(this);
super.onDestroy();
}
}
sharePrefer的工具类代码:
package co.huiqu.webapp.config;
import java.util.Set;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
/**
*
* 保存系统信息
* @author song
* @date 2015年11月4日
*/
public class SystemParams {
private static SystemParams instance;
private static SharedPreferences sharedPrederences = null;
private SystemParams() {
}
//在Application初始化
public static void init(Context context) {
sharedPrederences = context.getSharedPreferences("hobbees", Context.MODE_PRIVATE);
}
public static SystemParams getInstance() {
if(instance == null) {
synchronized (SystemParams.class) {
if(instance == null) {
instance = new SystemParams();
}
}
}
return instance;
}
/**get**/
public int getInt(String key){
return sharedPrederences.getInt(key, 0);
}
public int getInt(String key,int defValue){
return sharedPrederences.getInt(key, defValue);
}
public float getFloat(String key){
return sharedPrederences.getFloat(key, 0);
}
public float getFloat(String key,float defValue) {
return sharedPrederences.getFloat(key, defValue);
}
public long getLong(String key){
return sharedPrederences.getLong(key, 0);
}
public long getLong(String key,long defValue) {
return sharedPrederences.getLong(key, defValue);
}
public String getString(String key){
return sharedPrederences.getString(key, null);
}
public String getString(String key,String defValue) {
return sharedPrederences.getString(key, defValue);
}
public boolean getBoolean(String key){
return sharedPrederences.getBoolean(key, false);
}
public boolean getBoolean(String key,boolean defValue) {
return sharedPrederences.getBoolean(key, defValue);
}
/**set**/
public void setInt(String key,int value) {
Editor editor = sharedPrederences.edit();
editor.putInt(key, value);
editor.commit();
}
public void setFloat(String key,float value) {
Editor editor = sharedPrederences.edit();
editor.putFloat(key, value);
editor.commit();
}
public void setLong(String key,long value) {
Editor editor = sharedPrederences.edit();
editor.putLong(key, value);
editor.commit();
}
public void setString(String key,String value) {
Editor editor = sharedPrederences.edit();
editor.putString(key, value);
editor.commit();
}
public void setBoolean(String key,boolean value) {
Editor editor = sharedPrederences.edit();
editor.putBoolean(key, value);
editor.commit();
}
public void setSetString(String key,Set<String> values) {
Editor editor = sharedPrederences.edit();
editor.putStringSet(key, values);
editor.commit();
}
public void remove(String key) {
Editor editor = sharedPrederences.edit();
editor.remove(key);
editor.commit();
}
public void clear() {
Editor editor = sharedPrederences.edit();
editor.clear().commit();
}
}
package co.huiqu.webapp.download;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.widget.Toast;
import co.huiqu.webapp.config.SystemParams;
/**
* Created by Song on 2016/11/2.
*/
public class ApkInstallReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
long downloadApkId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
if(intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
Toast.makeText(context,"收到apk下载完成的广播",Toast.LENGTH_LONG).show();
int status = DownLoadUtils.getInstance(context).checkStatus(downloadApkId);
switch (status) {
//下载暂停
case DownloadManager.STATUS_PAUSED:
//获得下载暂停的原因等信息
Toast.makeText(context,"暂停下载"+DownLoadUtils.getInstance(context).getPausedReason(downloadApkId),Toast.LENGTH_LONG).show();
break;
//下载延迟
case DownloadManager.STATUS_PENDING:
//获得下载延迟的原因
break;
//正在下载
case DownloadManager.STATUS_RUNNING:
break;
//下载完成
case DownloadManager.STATUS_SUCCESSFUL:
//下载完成安装APK
installApk(context, downloadApkId);
break;
//下载失败
case DownloadManager.STATUS_FAILED:
// 获得下载失败的原因
Toast.makeText(context,"暂停下载"+DownLoadUtils.getInstance(context).getFailedReason(downloadApkId),Toast.LENGTH_LONG).show();
break;
}
}else if(DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(intent.getAction())){
//点击通知栏取消下载
Toast.makeText(context,"通知栏被点击",Toast.LENGTH_LONG).show();
}
}
/**
* 安装apk
*/
private void installApk(Context context,long downloadId) {
long downId = SystemParams.getInstance().getLong(DownloadManager.EXTRA_DOWNLOAD_ID, -1L);
if(downloadId == downId) {
DownloadManager downManager= (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Uri downloadUri = downManager.getUriForDownloadedFile(downloadId);
SystemParams.getInstance().setString("downloadApk",downloadUri.getPath());
if (downloadUri != null) {
Intent install= new Intent(Intent.ACTION_VIEW);
install.setDataAndType(downloadUri, "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
} else {
Toast.makeText(context, "下载失败", Toast.LENGTH_SHORT).show();
}
}
}
}
package co.huiqu.webapp.download;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import co.huiqu.webapp.config.SystemParams;
/**
* Apk下载
* Created by Song on 2016/11/2.
*/
public class DownloadApk {
private static ApkInstallReceiver apkInstallReceiver;
/**
* 下载APK文件
* @param context
* @param url
* @param title
* @param appName
*/
public static void downloadApk(Context context, String url, String title,final String appName) {
//获取存储的下载ID
long downloadId = SystemParams.getInstance().getLong(DownloadManager.EXTRA_DOWNLOAD_ID,-1L);
if(downloadId != -1) {
//存在downloadId
DownLoadUtils downLoadUtils = DownLoadUtils.getInstance(context);
//获取当前状态
int status = downLoadUtils.getDownloadStatus(downloadId);
if(DownloadManager.STATUS_SUCCESSFUL == status) {
//状态为下载成功
//获取下载路径URI
Uri downloadUri = downLoadUtils.getDownloadUri(downloadId);
if(null != downloadUri) {
//存在下载的APK,如果两个APK相同,启动更新界面。否之则删除,重新下载。
if(compare(getApkInfo(context,downloadUri.getPath()),context)) {
startInstall(context, downloadUri);
return;
} else {
//删除下载任务以及文件
downLoadUtils.getDownloadManager().remove(downloadId);
}
}
start(context, url, title,appName);
} else if(DownloadManager.STATUS_FAILED == status) {
//下载失败,重新下载
start(context, url, title,appName);
}else {
Log.d(context.getPackageName(), "apk is already downloading");
}
} else {
//不存在downloadId,没有下载过APK
start(context, url, title,appName);
}
}
/**
* 开始下载
* @param context
* @param url
* @param title
* @param appName
*/
private static void start(Context context, String url, String title,String appName) {
if(hasSDKCard()) {
long id = DownLoadUtils.getInstance(context).download(url,
title, "下载完成后点击打开", appName);
SystemParams.getInstance().setLong(DownloadManager.EXTRA_DOWNLOAD_ID,id);
} else {
Toast.makeText(context,"手机未安装SD卡,下载失败",Toast.LENGTH_LONG).show();
}
}
public static void registerBroadcast(Context context) {
apkInstallReceiver = new ApkInstallReceiver();
context.registerReceiver(apkInstallReceiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
context.registerReceiver(apkInstallReceiver, new IntentFilter(DownloadManager.ACTION_NOTIFICATION_CLICKED));
}
public static void unregisterBroadcast(Context context) {
if(null != apkInstallReceiver) {
context.unregisterReceiver(apkInstallReceiver);
}
}
/**
* 跳转到安装界面
* @param context
* @param uri
*/
private static void startInstall(Context context, Uri uri) {
Intent install = new Intent(Intent.ACTION_VIEW);
install.setDataAndType(uri, "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
/**
* 获取APK程序信息
* @param context
* @param path
* @return
*/
private static PackageInfo getApkInfo(Context context, String path) {
PackageManager pm = context.getPackageManager();
PackageInfo pi = pm.getPackageArchiveInfo(path, PackageManager.GET_ACTIVITIES);
if(null != pi) {
return pi;
}
return null;
}
/**
* 比较两个APK的信息
* @param apkInfo
* @param context
* @return
*/
private static boolean compare(PackageInfo apkInfo,Context context) {
if(null == apkInfo) {
return false;
}
String localPackageName = context.getPackageName();
if(localPackageName.equals(apkInfo.packageName)) {
try {
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(localPackageName, 0);
//比较当前APK和下载的APK版本号
if (apkInfo.versionCode > packageInfo.versionCode) {
//如果下载的APK版本号大于当前安装的APK版本号,返回true
return true;
}
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
}
return false;
}
/**
* 是否存在SD卡
*/
private static boolean hasSDKCard() {
return Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
}
/**
* 删除已下载的文件
*/
public static void removeFile(Context context) {
String filePath = SystemParams.getInstance().getString("downloadApk",null);
if(null != filePath) {
File downloadFile = new File(filePath);
if(null != downloadFile && downloadFile.exists()) {
//删除之前先判断用户是否已经安装了,安装了才删除。
if(!compare(getApkInfo(context,filePath),context)) {
downloadFile.delete();
Log.e("----", "已删除");
}
}
}
}
}
package co.huiqu.webapp.download;
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.Uri;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;
import java.io.File;
import co.huiqu.webapp.config.SystemParams;
/**
* 封装 DownLoadManager 下载
* Created by Song on 2016/11/2.
*/
public class DownLoadUtils {
private Context mContext;
private DownloadManager mDownloadManager;
private static volatile DownLoadUtils instance;
private DownLoadUtils(Context context) {
this.mContext = context.getApplicationContext();
mDownloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
}
/**
* 获取单例对象
*
* @param context
* @return
*/
public static DownLoadUtils getInstance(Context context) {
if (instance == null) {
synchronized (DownLoadUtils.class) {
if (instance == null) {
instance = new DownLoadUtils(context);
return instance;
}
}
}
return instance;
}
/**
* 下载
*
* @param uri
* @param title
* @param description
* @param appName
* @return downloadId
*/
public long download(String uri, String title, String description, String appName) {
//1.构建下载请求
DownloadManager.Request downloadRequest = new DownloadManager.Request(Uri.parse(uri));
downloadRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
downloadRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
/**设置漫游状态下是否可以下载*/
downloadRequest.setAllowedOverRoaming(false);
/**如果我们希望下载的文件可以被系统的Downloads应用扫描到并管理,
我们需要调用Request对象的setVisibleInDownloadsUi方法,传递参数true.*/
downloadRequest.setVisibleInDownloadsUi(true);
//文件保存位置
//file:///storage/emulated/0/Android/data/your-package/files/Download/appName.apk
downloadRequest.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, appName + ".apk");
// 设置一些基本显示信息
downloadRequest.setTitle(title);
downloadRequest.setDescription(description);
//req.setMimeType("application/vnd.android.package-archive");
return mDownloadManager.enqueue(downloadRequest);//异步请求
}
/**
* 获取文件下载路径
*
* @param downloadId
* @return
*/
public String getDownloadPath(long downloadId) {
DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
Cursor c = mDownloadManager.query(query);
if (c != null) {
try {
if (c.moveToFirst()) {
return c.getString(c.getColumnIndexOrThrow(DownloadManager.COLUMN_LOCAL_URI));
}
} finally {
c.close();
}
}
return null;
}
/**
* 获取文件保存的地址
*
* @param downloadId
* @return
*/
public Uri getDownloadUri(long downloadId) {
return mDownloadManager.getUriForDownloadedFile(downloadId);
}
public DownloadManager getDownloadManager() {
return mDownloadManager;
}
/**
* 获取下载状态
*
* @param downloadId
* @return
*/
public int getDownloadStatus(long downloadId) {
DownloadManager.Query query = new DownloadManager.Query().setFilterById(downloadId);
Cursor c = mDownloadManager.query(query);
if (c != null) {
try {
if (c.moveToFirst()) {
return c.getInt(c.getColumnIndexOrThrow(DownloadManager.COLUMN_STATUS));
}
} finally {
c.close();
}
}
return -1;
}
/**
* 判断下载管理程序是否可用
*
* @return
*/
public boolean canDownload() {
try {
int state = mContext.getPackageManager().getApplicationEnabledSetting("com.android.providers.downloads");
if (state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED
|| state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
|| state == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/**
* 进入 启用/禁用 下载管理程序界面
*/
public void skipToDownloadManager() {
String packageName = "com.android.providers.downloads";
Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
intent.setData(Uri.parse("package:" + packageName));
mContext.startActivity(intent);
}
/**
* 进入 启用/禁用 下载管理程序界面
*/
public int checkStatus(long downloadId) {
DownloadManager.Query query = new DownloadManager.Query();
//通过下载的id查找
query.setFilterById(downloadId);
Cursor c = mDownloadManager.query(query);
int status = -1;
if (c.moveToFirst()) {
status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
}
return status;
}
/**
* 查询当前下载暂停失败的原因
*/
public String getPausedReason(long downloadId) {
DownloadManager.Query query = new DownloadManager.Query();
//通过下载的id查找
query.setFilterById(downloadId);
query.setFilterByStatus(DownloadManager.STATUS_PAUSED);
// Query the Download Manager for paused downloads.
Cursor pausedDownloads = mDownloadManager.query(query);
// Find the column indexes for the data we require.
int reasonIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_REASON);
int titleIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TITLE);
int fileSizeIdx =
pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int bytesDLIdx =
pausedDownloads.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
// Iterate over the result Cursor.
while (pausedDownloads.moveToNext()) {
// Extract the data we require from the Cursor.
String title = pausedDownloads.getString(titleIdx);
int fileSize = pausedDownloads.getInt(fileSizeIdx);
int bytesDL = pausedDownloads.getInt(bytesDLIdx);
// Translate the pause reason to friendly text.
int reason = pausedDownloads.getInt(reasonIdx);
String reasonString = "Unknown";
switch (reason) {
case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
reasonString = "Waiting for WiFi";
break;
case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
reasonString = "Waiting for connectivity";
break;
case DownloadManager.PAUSED_WAITING_TO_RETRY:
reasonString = "Waiting to retry";
break;
default:
break;
}
// Construct a status summary
StringBuilder sb = new StringBuilder();
sb.append(title).append("\n");
sb.append(reasonString).append("\n");
sb.append("Downloaded ").append(bytesDL).append(" / ").append(fileSize);
return sb.toString();
}
return "";
}
/**
* 查询当前下载暂停失败的原因
*/
public String getFailedReason(long downloadId) {
DownloadManager.Query query = new DownloadManager.Query();
//通过下载的id查找
query.setFilterById(downloadId);
query.setFilterByStatus(DownloadManager.STATUS_FAILED);
// Query the Download Manager for paused downloads.
Cursor pausedDownloads = mDownloadManager.query(query);
// Find the column indexes for the data we require.
int reasonIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_REASON);
int titleIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TITLE);
int fileSizeIdx =
pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
int bytesDLIdx =
pausedDownloads.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
// Iterate over the result Cursor.
while (pausedDownloads.moveToNext()) {
// Extract the data we require from the Cursor.
String title = pausedDownloads.getString(titleIdx);
int fileSize = pausedDownloads.getInt(fileSizeIdx);
int bytesDL = pausedDownloads.getInt(bytesDLIdx);
// Translate the pause reason to friendly text.
int reason = pausedDownloads.getInt(reasonIdx);
String reasonString = "Unknown";
switch (reason) {
case DownloadManager.ERROR_HTTP_DATA_ERROR:
reasonString = "服务器异常";
break;
case DownloadManager.ERROR_INSUFFICIENT_SPACE:
reasonString = "存储空间不足";
break;
case DownloadManager.ERROR_FILE_ERROR:
reasonString = "找不到该文件";
break;
default:
break;
}
// Construct a status summary
StringBuilder sb = new StringBuilder();
sb.append(title).append("\n");
sb.append(reasonString).append("\n");
sb.append("Downloaded ").append(bytesDL).append(" / ").append(fileSize);
return sb.toString();
}
return "";
}
}
清单文件:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="co.huiqu.webapp">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
<uses-permission android:name="android.permission.INTERNET"></uses-permission>
<application
android:name=".A"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".download.ApkInstallReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE" />
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
</intent-filter>
</receiver>
</application>
<!--在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 从SDCard读取数据权限 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- 访问网络权限 -->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>