Downloadmanager实现app实现的升级下载使用
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>
Downloadmanager实现app实现的升级下载使用的更多相关文章
- 安卓开发实战之app之版本更新升级(DownloadManager和http下载)完整实现
转载: https://blog.csdn.net/u013278099/article/details/52692008 前言 本文将讲解app的升级与更新.一般而言用户使用App的时候升级提醒有两 ...
- 微信扫描二维码安卓弹出默认浏览器(苹果打开App Store)打开下载链接
使用微信推广的用户经常都会遇到推广链接被拦截导致无法下载app的情况,此时用户在微信中打开会提示“ 已停止访问该网页 ”.这对于使用微信营销的商家来说就很不友好且损失非常大,因为用户是不知道为什么打不 ...
- js判断是否安装某个android app,没有安装下载该应用(websocket通信,监听窗口失去焦点事件)
现在经常有写场景需要提示用户下载app, 但是如果用户已经安装,我们希望是直接打开app. 实际上,js是没有判断app是否已经安装的方法的,我们只能曲线救国. 首先,我们需要有call起app的sc ...
- Vuejs 高仿饿了么外卖APP 百度云视频教程下载
Vuejs 高仿饿了么外卖APP 百度云视频教程下载 链接:https://pan.baidu.com/s/1KPbKog0qJqXI-2ztQ19o7w 提取码: 关注公众号[GitHubCN]回复 ...
- ios系统App Store安装包下载链接获取
今天将自己开发的Android版本和ios版本的安装包通过生成二维码的方式展示在H5页面上,Android版的比较简单,但是ios的安装包用户必须从App Store(苹果应用市场)中下载安装,所以获 ...
- 如何从google play下载app应用,直接下载apk
如何从google play直接下载apk by fly2004jun 2013-10-05 转载请附出处 由于某些原因,大天朝局域网访问google很多服务不能用,其中就包括google ...
- 《Android Studio开发实战 从零基础到App上线》资源下载和内容勘误
转载于:https://blog.csdn.net/aqi00/article/details/73065392 资源下载 下面是<Android Studio开发实战 从零基础到App上线&g ...
- 混合APP开发-hybrid 升级流程
本文来自网易云社区 作者:王贝 目前大多数APP已经应用hybrid进混合开发,这不,我们的gacha APP这个版本已经开始使用hybrid来开发了,hybrid的优势这里就不多说了,这里主要讲一下 ...
- Android 升级下载 它们的定义Updates 兼容版本
Android 更新模块 它们的定义Update 写这个总结是由于在项目中碰到了Android系统兼容的BUG Android项目原本使用的是API提供的下载方法 例如以下: Download ...
随机推荐
- [JavaWeb基础] 013.Struts2 自定义类型转换器
很多时候,我们在做web开发的时候经常要用到时间的转换器,Struts2给我们提供了一种类型转换器的接口.下面我们讲讲怎么实现吧. 1.首先我们要定义一个类型转换的类,继承自com.babybus.s ...
- (一)DAO设计及BaseDAO和BookDAO的实现
1.总体架构 MVC 设计模式:Model:POJO(Plain Old Java Object) Controller:ServletView:JSP + EL + JSTL 2.技术选型 数据库: ...
- Springboot 内置tomcat 基本配置收集整理
配置一: server:# tomcat 配置 tomcat: # 接收队列长度 accept-count: 1000 # 最小空闲线程数 min-spare-threads ...
- Rocket - devices - TLBusBypass
https://mp.weixin.qq.com/s/WviVHxlZvsNm8mea2VpfTw 简单介绍TLBusBypass的实现. 1. TLBypassNode TLBypassNode定义 ...
- Chisel3 - bind - Op, ReadOnly, 左值
https://mp.weixin.qq.com/s/F_08jKFMoX9Gf_J_YpsDpg 两个数据变量进行某个操作(op),产生一个输出,这个输出存在一个匿名变量中.这个匿名变量就是以O ...
- DDD之3实体和值对象
图中是一个别墅的模型,代表实体,可以真实的看得到.那么在DDD设计方法论中,实体和值对象是什么呢? 背景 实体和值对象是领域模型中的领域对象,是组成领域模型的基础单元,一起实现实体最基本的核心领域逻辑 ...
- Java实现 蓝桥杯 算法训练 排序
算法训练 排序 时间限制:1.0s 内存限制:512.0MB 问题描述 编写一个程序,输入3个整数,然后程序将对这三个整数按照从大到小进行排列. 输入格式:输入只有一行,即三个整数,中间用空格隔开. ...
- Java实现 蓝桥杯 历届真题 稍大的串
串可以按照字典序进行比较.例如: abcd 小于 abdc 如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些.科学地说:它是大于已知串 ...
- jmeter怎么衡量tps的值
jmeter也没有tps这么个报告数据,后来又翻了翻loadrunner关于tps的定义 1.TPS:Trasaction per second也就是事务数/秒.它是软件测试结果的测量单位.一个事务是 ...
- STL中常用算法
一.排序 sort sort(first_pointer,first_pointer+n,cmp) 默认为升序 若要使用降序,自行写cmp 函数 bool cmp(int a,int b){ retu ...