1.DownloadManager介绍

DownloadManger是android 2.3(api level 9)开始 提供的用于优化处理长时间的下载操作。DownloadManager 处理Http/Https连接并监控连接中的状态变化及系统重启来确保每一个下载任务顺利完成。大多数涉及到下载的情况中使用DownloadManager都是很好的选择,尤其是后台继续下载,下载状态回调,断点续传,下载环境设置,下载文件的操作等方面,支持的很好。

DownloadManager是系统开放给第三方应用使用的类,包含两个静态内部类DownloadManager.Query和DownloadManager.Request。DownloadManager.Request用来请求一个下载,DownloadManager.Query用来查询下载信息,具体接口信息可参看最后的api说明。

2.DownloadManager使用

DownloadManager主要对外提供了以下接口:

  • public long enqueue(Request request)执行下载,返回downloadId,downloadId可用于后面查询下载信息。若网络不满足条件、Sdcard挂载中、超过最大并发数等异常会等待下载,正常则直接下载。

  • int remove(long… ids) 删除下载,若下载中取消下载。会同时删除下载文件和记录。

  • Cursor query(Query query) 查询下载信息。

  • getMaxBytesOverMobile(Context context) 返回移动网络下载的最大值

  • rename(Context context, long id, String displayName) 重命名已下载项的名字

  • getRecommendedMaxBytesOverMobile(Context context) 获取建议的移动网络下载的大小

  • 其它:通过查看代码我们可以发现还有个CursorTranslator私有静态内部类。这个类主要对Query做了一层代理。将DownloadProvider和DownloadManager之间做个映射。将DownloadProvider中的十几种状态对应到了DownloadManager中的五种状态,DownloadProvider中的失败、暂停原因转换为了DownloadManager的原因。

  • 3.DownloadManager实现下载代码

3.1下载需要的权限

<uses-permission android:name="android.permission.INTERNET" />;

< uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>;

3.2 自定义下载线程

package com.tt.travel_and.Util;import android.app.DownloadManager;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.Process;/*** Created by Summer on 2017/9/8.*/public class DownLoadRunnable implements Runnable {private String url;private Handler handler;private Context mContext;private long requestId;public DownLoadRunnable(Context context, String url, Handler handler) {this.mContext = context;this.url = url;this.handler = handler;}@Overridepublic void run() {//设置线程优先级为后台,这样当多个线程并发后很多无关紧要的线程分配的CPU时间将会减少,有利于主线程的处理Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);startDownload();}private long startDownload() {//获得DownloadManager对象DownloadManager downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);//获得下载id,这是下载任务生成时的唯一id,可通过此id获得下载信息requestId = downloadManager.enqueue(CreateRequest(url));//查询下载信息方法queryDownloadProgress(requestId, downloadManager);return requestId;}private void queryDownloadProgress(long requestId, DownloadManager downloadManager) {DownloadManager.Query query = new DownloadManager.Query();//根据任务编号id查询下载任务信息query.setFilterById(requestId);try {boolean isGoging = true;while (isGoging) {Cursor cursor = downloadManager.query(query);if (cursor != null && cursor.moveToFirst()) {//获得下载状态int state = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));switch (state) {case DownloadManager.STATUS_SUCCESSFUL://下载成功isGoging = false;Bundle bundle = new Bundle();bundle.putString("path", downloadManager.getUriForDownloadedFile(requestId).toString());Message msg = handler.obtainMessage(downloadManager.STATUS_SUCCESSFUL);msg.setData(bundle);msg.sendToTarget();//发送到主线程,更新uibreak;case DownloadManager.STATUS_FAILED://下载失败isGoging = false;handler.obtainMessage(downloadManager.STATUS_FAILED).sendToTarget();//发送到主线程,更新uibreak;case DownloadManager.STATUS_RUNNING://下载中/*** 计算下载下载率;*/int totalSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));int currentSize = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR));int progress = (int) (((float) currentSize) / ((float) totalSize) * 100);handler.obtainMessage(downloadManager.STATUS_RUNNING, progress).sendToTarget();//发送到主线程,更新uibreak;case DownloadManager.STATUS_PAUSED://下载停止handler.obtainMessage(DownloadManager.STATUS_PAUSED).sendToTarget();break;case DownloadManager.STATUS_PENDING://准备下载handler.obtainMessage(DownloadManager.STATUS_PENDING).sendToTarget();break;}}if (cursor != null) {cursor.close();}}} catch (Exception e) {e.printStackTrace();}}private DownloadManager.Request CreateRequest(String url) {if(url==null || url.equals("")){return null;}DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN);// 隐藏notificationrequest.setAllowedNetworkTypes(request.NETWORK_WIFI);//设置下载网络环境为wifirequest.setTitle("天津出行版本更新");request.setDescription("正在下载");request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "/tjcx/tianjintrek.apk");//指定apk缓存路径,默认是在SD卡中的Download文件夹return request;}}

3.3Activity中实现下载功能

    Handler handler = new Handler() {@Overridepublic void handleMessage(final Message msg) {switch (msg.what) {case DownloadManager.STATUS_SUCCESSFUL://下载成功runOnUiThread(new Runnable() {@Overridepublic void run() {Toast.makeText(MainActivity.this, "下载任务已经完成!", Toast.LENGTH_SHORT).show();DownloadFinished();//下载完成安装apk}});break;case DownloadManager.STATUS_RUNNING://下载中final int progress = (int) msg.obj;runOnUiThread(new Runnable() {@Overridepublic void run() {upload_progress.setProgress(progress);tv_currentprogress.setText(progress + "%");if(progress==100){dialog_update.dismiss();}}});break;case DownloadManager.STATUS_FAILED://下载失败
//                    canceledDialog();break;case DownloadManager.STATUS_PENDING://准备下载
//                    showDialog();break;}}};/*** 下载完成安装apk*/private void DownloadFinished(){File mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/tjcx/tianjintrek.apk");if (mFile.getName().endsWith(".apk")) {Intent install = new Intent();install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);install.setAction(Intent.ACTION_VIEW);if (24 > Build.VERSION.SDK_INT) {install.setDataAndType(Uri.fromFile(mFile), "application/vnd.android.package-archive");} else {Uri apkUri =FileProvider.getUriForFile(MainActivity.this, "com.tt.travel_and.fileprovider", mFile);install.setDataAndType(apkUri, "application/vnd.android.package-archive");install.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);}startActivity(install);LocationApplication.setUserInfo(null, null, null);}}/*** 自定义的更新提示dialog*/private void showUpdateAppAlertDialogs() {LayoutInflater inflater = LayoutInflater.from(MainActivity.this);AutoLinearLayout layout = (AutoLinearLayout) inflater.inflate(R.layout.updateapp_dialogs, null);txt_title = (TextView) layout.findViewById(R.id.txt_title);txt_title.setText(getResources().getString(R.string.discovernewversion) + version_name);txt_msg = (TextView) layout.findViewById(R.id.txt_msg);txt_msg.setText(getResources().getString(R.string.app_name_cn)+version_name+getResources().getString(R.string.update_appcontent));//   txt_msg.setText(version_name);rl_update_unmust = (AutoLinearLayout) layout.findViewById(R.id.rl_update_unmust);rl_updates = (AutoRelativeLayout) layout.findViewById(R.id.rl_update);upload_progress = (ProgressBar) layout.findViewById(R.id.upload_progress);//更新进度条tv_currentprogress = (TextView) layout.findViewById(R.id.tv_currentprogress); //显示实时更新进度Button btn_updateapp = (Button) layout.findViewById(R.id.btn_updateapp);Button btn_updateappcancel = (Button) layout.findViewById(R.id.btn_updateappcancel);btn_updateappcancel.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {dialog_update.dismiss();}});
//点击更新按钮 btn_updateapp.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {// appupdate();rl_update_unmust.setVisibility(View.GONE);rl_updates.setVisibility(View.VISIBLE);download();//apk下载方法}});dialog_update = new AlertDialog.Builder(MainActivity.this,R.style.NoExitAnimDialog).create(); dialog_update.setCanceledOnTouchOutside(false);//dialog弹出后会点击屏幕,dialog不消失;点击物理返回键dialog消失  dialog_update.show();dialog_update.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); dialog_update.getWindow().setContentView(layout); dialog_update.getWindow().setBackgroundDrawableResource(R.color.transparent);}private void download() {//android6.0以后要动态申请权限if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&PackageManager.PERMISSION_GRANTED != ContextCompat.checkSelfPermission(MainActivity.this,"android.permission.WRITE_EXTERNAL_STORAGE")) {//判断当前系统的SDK版本是否大于23verifyStoragePermissions(MainActivity.this);//先去动态申请权限 通过用户同意权限 则开启下载线程return;}/*** 更新的时候先检查安装包在sd卡中是否存在,如果存在则直接安装,不存在开启下载线程进行下载*/File mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/tjcx/tianjintrek.apk");if (mFile.exists()) {//安装包存在,直接安装dialog_update.dismiss();DownloadFinished();//下载完成安装apk}else{//下载apk//最好是用单线程池,或者intentService取代new Thread(new DownLoadRunnable(this, url, handler)).start();//url换成你apk的下载地址就可以了}}/*** 运行时权限处理* 用户选择允许或拒绝后,会回调onRequestPermissionsResult方法, 该方法类似于onActivityResult  * @param requestCode  * @param permissions* @param grantResults  */@Overridepublic void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {super.onRequestPermissionsResult(requestCode, permissions, grantResults);if (grantResults.length > 0&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
//          Log.i("CMCC", "权限被允许");/*** 更新的时候先检查安装包在sd卡中是否存在,如果存在则直接安装,不存在开启下载线程进行下载*/File mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/tjcx/tianjintrek.apk");if (mFile.exists()) {//安装包存在,直接安装dialog_update.dismiss();DownloadFinished();}else{//下载apk//最好是用单线程池,或者intentService取代new Thread(new DownLoadRunnable(this, url, handler)).start();}} else {finish();Toast.makeText(this, "同意权限后才能进行更新,请手动进入设置打开手机读取sd卡权限", Toast.LENGTH_LONG).show();}}

3.4 在res节点下创建xml文件夹,在xml文件夹下新建update_path.xml文件(文件内容如下)

<?xml version="1.0" encoding="utf-8"?>
<paths><external-pathname="localApk"path="Download/tjcx/" /><external-path path="" name="image" />
</paths>

3.5 在Androidmanifest配置清单中声明provider,引用上面创建的update_path.xml文件

<provider android:name="android.support.v4.content.FileProvider" android:authorities="com.tt.travel_and.fileprovider" android:exported="false" android:grantUriPermissions="true"> <!--元数据--> <meta-data android:name="android.support.FILE_PROVIDER_PATHS" android:resource="@xml/update_path" /> </provider>

通过以上代买就可以实现app的版本更新功能了

4 apk安装成功后删除安装包

4.1Android 应用程序的安装和卸载事件,是由系统进行监听并全局广播的,支持1.5(android 3)以上因此,如果想要监听获取应用的安装和卸载事件,只需要自定义一个BroadcastReceiver,来对系统广播进行监听和处理

4.2自定义广播InitApkBroadCastReceiver

package com.tt.travel_and.service;import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Environment;
import android.util.Log;
import android.widget.Toast;import java.io.File;/*** Created by Summer on 2017/10/10.*/public class InitApkBroadCastReceiver extends BroadcastReceiver {@Overridepublic void onReceive(Context context, Intent intent) {Log.e("-------------",intent.getData().getSchemeSpecificPart());if (context.getPackageName().equals(intent.getData().getSchemeSpecificPart())) {File mFile = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath() + "/tjcx/tianjintrek.apk");if (mFile.exists()) {mFile.delete();//app替换成功以后直接删除安装包Toast.makeText(context, "已删除安装包", Toast.LENGTH_SHORT).show();}}}
}

4.3在AndroidManifest中注册广播

<receiver android:name=".service.InitApkBroadCastReceiver"><intent-filter><!-- 一个新版本的应用安装到设备,替换之前已经存在的版本  替换时会先收到卸载的再收到替换的, 替换自身也能收到--> <action android:name="android.intent.action.PACKAGE_REPLACED" />
<data android:scheme="package" /></intent-filter></receiver>

好了到这通过DownloadManager实现app的版本更新和apk安装完成后删除安装包都已经说完了,希望对大家的学习和工作有所帮助。

Android通过DownloadManager实现App的版本更新功能相关推荐

  1. android动画送礼物,Android仿直播类app赠送礼物功能

    直播界面 实现的是播放本地的视频文件: /** * 直播界面,用于对接直播功能 */ public class LiveFrag extends Fragment { private ImageVie ...

  2. android 升级代码,一句代码实现Android版本更新功能

    自从友盟关闭了版本更新功能后,安卓的版本更新只能自己来撸了,结合之前友盟的版本更新,其实实现起来也简单,这里简单说说版本更新实现的思路: 第一步,通过接口获取更新信息(版本号.更新内容.apk下载地址 ...

  3. 安卓开发实战之app之版本更新升级(DownloadManager和http下载)完整实现

    前言 本文将讲解app的升级与更新.一般而言用户使用App的时候升级提醒有两种方式获得: 一种是通过应用市场 获取 一种是打开应用之后提醒用户更新升级 而更新操作一般是在用户点击了升级按钮之后开始执行 ...

  4. Android实现跳转版本更新功能

    最近需要做应用版本更新功能,因为之前已经写过一篇版本更新的功能了,虽然请求接口还是用的HttpUrlConnection,想着改改现在应用使用的请求方式也挺快的嘛,心里开始暗喜,可以偷偷懒了,哈哈哈. ...

  5. android拍照功能编程,android实现手机App实现拍照功能示例

    实现手机App实现拍照功能结果如下 第一步: activity_takephoto.xml布局用SurfaceView xmlns:tools="http://schemas.android ...

  6. android php实时聊天工具,Android_Android 应用APP加入聊天功能,简介 自去年 LeanCloud 发布实时 - phpStudy...

    Android 应用APP加入聊天功能 简介 自去年 LeanCloud 发布实时通信(IM)服务之后,基于用户反馈和工程师对需求的消化和对业务的提炼,上周正式发布了「实时通信 2.0 」.设计理念依 ...

  7. Android App接入支付功能

    微信支付,请参考我另一篇:Android App接入支付功能--微信篇 因为项目中用到支付功能,而且支付宝文档和微信文档写的很简洁,不仔细研究,真的无法集成成功 老样子,上效果图由于涉及到输入密码,我 ...

  8. android 短信打开APP功能及注意事项

    android 短信打开APP 1.FirstActivity配置intent-filter 2.H5提供重定向 3.Activity解析参数 4.APP退到后台无法跳转问题解决 项目APP使用的是D ...

  9. android文件下载功能实现,Android中DownloadManager实现文件下载实例详解

    Android中DownloadManager实现文件下载 下载 创建下载链接 DownloadManager.Request request = new DownloadManager.Reques ...

最新文章

  1. logistic loss公式的由来 xgboost 雪伦的推导中使用了该公式
  2. 企业设置“蜜罐”的五大理由
  3. mysql 按小时分组统计_PowerBI业务分析:按排名分组统计
  4. SQL注入思维导图【新手全面非详细】
  5. JVM调优:打印所有-XX非标参数命令
  6. RHEL5.8安装Oracle10g
  7. 在Hotspot JVM中跟踪过多的垃圾回收
  8. python rtf转txt_将DOC、RTF格式文件批量转为TXT格式文件
  9. Linux在U盘安装python的过程详解
  10. GPU基准测试显示:苹果A15芯片比A14芯片快13.7%
  11. Express框架学习笔记-get请求中参数的获取
  12. ssm mysql项目实战_ssm项目实战_ssm项目实战教程_ssm项目实战视频教程 _课课家
  13. 027. 从从门槛和可复制性聊聊生意模式
  14. 教程丨键盘上的各按键的作用与常用办公快捷键大全
  15. 基于学习的方法决定在哪些分支节点上运行heuristic算法
  16. python图片提取文字
  17. html中网站小图标,HTML网站图标favicon
  18. AppStore 算法更新,ASO优化师新建议:如何快速上榜,避免掉词?
  19. 递归_青蛙跳台阶(进阶版)
  20. 微信信息回复 java,微信公众平台开发中使用Java如何实现一个消息回复功能

热门文章

  1. 前谷歌员工推Cuil 获3300万风投对战老东家
  2. 激光SLAM保存pcd点云地图
  3. 请解析IP地址和对应的掩码,进行分类识别。要求按照A/B/C/D/E类地址归类,不合法的地址和掩码单独归类。
  4. vue显示农历_vue中通过时间转换农历得方法封装
  5. RNA-seq:转录组数据分析处理(上)
  6. vs2019添加文件夹到到现有项目
  7. SolidWorks装配体及约束快速导入Adams
  8. 【课内学习】数字电路Flip-Flop
  9. 机器学习和深度学习资料
  10. 机器学习----维数灾难