具体思路为:调用接口与服务器版本对比,当服务器版本号大于本地的,调用DownloadManager进行下载,之前也试过很多方法,但是兼容性都不是很好,还有一点要注意的是,在这里我并没有设置固定的下载路径,最初设置之后华为某手机上直接闪退,原因是找不到路径:

与服务器上版本号对比就不写了,最简单的是app上写个常量,与获取的版本号比较就行,每次更新修改工程里的这个常量。

附上下载方法:

/**
* 版本更新Dialog
* */
private void showUpdateDialog(final String downPath) {
new AlertDialog.Builder(this).setTitle("提示").setMessage("发现新版本,是否更新?")
.setPositiveButton("马上更新", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int arg1) {
//使用系统下载类
DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
Uri uri = Uri.parse(downPath);
DownloadManager.Request request = new DownloadManager.Request(uri);
// 设置自定义下载路径和文件名,该方法可能在某些机型不兼容
// String apkName = "yourName" + DateUtils.getCurrentMillis() + ".apk";
// request.setDestinationInExternalPublicDir(yourPath, apkName);
// MyApplication.getInstance().setApkName(apkName);
//设置允许使用的网络类型,这里是移动网络和wifi都可以
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);

//禁止发出通知,既后台下载,如果要使用这一句必须声明一个权限:android.permission.DOWNLOAD_WITHOUT_NOTIFICATION
//request.setShowRunningNotification(false);

//不显示下载界面
request.setVisibleInDownloadsUi(false);
// 设置为可被媒体扫描器找到
request.allowScanningByMediaScanner();
// 设置为可见和可管理
request.setVisibleInDownloadsUi(true);
request.setMimeType("application/cn.trinea.download.file");
/*设置下载后文件存放的位置,如果sdcard不可用,那么设置这个将报错,因此最好不设置如果sdcard可用,下载后的文件
在/mnt/sdcard/Android/data/packageName/files目录下面,如果sdcard不可用,设置了下面这个将报错,不设置,下载后的文件在/cache这个 目录下面*/
//request.setDestinationInExternalFilesDir(this, null, "tar.apk");
long id = downloadManager.enqueue(request);//TODO 把id保存好,在接收者里面要用,最好保存在Preferences里面
MyApplication.getInstance().setApkId(Long.toString(id));//TODO 把id存储在Preferences里面
dialog.dismiss();
}
})
.setNegativeButton("下次再说", new DialogInterface.OnClickListener() {

@Override
public void onClick(DialogInterface dialog, int arg1) {
// TODO Auto-generated method stub
dialog.dismiss();
}

}).show();
}

》》MyApplication 类:

public class MyApplication extends Application {

public static Context applicationContext;
private static MyApplication instance;

private static final String APK_ID = "apk_id";
private String apk_id = null;

@Override
public void onCreate() {
super.onCreate();
applicationContext = this;
instance = this;
}

public static MyApplication getInstance() {

return instance;
}

/**
* 设置下载APK ID
* @param id
* @return
*/
public void setApkId(String id){

SharedPreferences preferences= PreferenceManager.getDefaultSharedPreferences(applicationContext);
SharedPreferences.Editor editor=preferences.edit();
if(editor.putString(APK_ID, id).commit()){
apk_id=id;
}
}
/**
* 获取下载APK ID
* @return
*/
public String getApkId(){
apk_id = null;
if(apk_id==null){
SharedPreferences preferences=PreferenceManager.getDefaultSharedPreferences(applicationContext);
apk_id=preferences.getString(APK_ID, null);
}
return apk_id;
}
}

》》广播CompleteReceiver 类:

public class CompleteReceiver extends BroadcastReceiver {
private DownloadManager downloadManager;

@Override
public void onReceive(Context context, Intent intent) {

String action = intent.getAction();
if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
Toast.makeText(context, "下载完成!", Toast.LENGTH_LONG).show();

long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);//TODO 判断这个id与之前的id是否相等,如果相等说明是之前的那个要下载的文件

DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(id);
downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Cursor cursor = downloadManager.query(query);
int columnCount = cursor.getColumnCount();
String path = null;//TODO 这里把所有的列都打印一下,有什么需求,就怎么处理,文件的本地路径就是path
while (cursor.moveToNext()) {
for (int j = 0; j < columnCount; j++) {
String columnName = cursor.getColumnName(j);
String string = cursor.getString(j);
if (columnName.equals("local_uri")) {
path = string;
}
if (string != null) {
System.out.println(columnName + ": " + string);
} else {
System.out.println(columnName + ": null");
}
}
}
cursor.close();

//如果sdcard不可用时下载下来的文件,那么这里将是一个内容提供者的路径,这里打印出来,有什么需求就怎么样处理 if(path.startsWith("content:")) {
if(path.startsWith("content:")) {
System.out.println("-----------------------CompleteReceiver 下载完了----路径path = " + path.toString());
}

if(id == Long.parseLong(MyApplication.getInstance().getApkId())){//TODO 判断这个id与之前的id是否相等,如果相等说明是之前的那个要下载的文件
Intent install = new Intent(Intent.ACTION_VIEW);
// Uri downloadFileUri = downloadManager.getUriForDownloadedFile(id);
String uriString = getFilePathFromUri(context, Uri.parse(path));//TODO 转换path路径 否则报解析包错误
System.out.println("-----------------------CompleteReceiver 转换后----路径uriString = " + uriString);
install.setDataAndType(Uri.fromFile(new File(uriString)), "application/vnd.android.package-archive");
install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(install);
}
} else if (action.equals(DownloadManager.ACTION_NOTIFICATION_CLICKED)) {
Toast.makeText(context, "点击通知了....", Toast.LENGTH_LONG).show();
}
}

/**
* 转换 path路径
* */
public static String getFilePathFromUri(Context c, Uri uri) {
String filePath = null;
if ("content".equals(uri.getScheme())) {
String[] filePathColumn = { MediaStore.MediaColumns.DATA };
ContentResolver contentResolver = c.getContentResolver();

Cursor cursor = contentResolver.query(uri, filePathColumn, null,
null, null);

cursor.moveToFirst();

int columnIndex = cursor.getColumnIndex(filePathColumn[0]);
filePath = cursor.getString(columnIndex);
cursor.close();
} else if ("file".equals(uri.getScheme())) {
filePath = new File(uri.getPath()).getAbsolutePath();
}
return filePath;
}

}

<manifest 配置:

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

<application
android:name=".MyApplication"
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name=".MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<receiver android:name=".CompleteReceiver">
<intent-filter>
<action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>
<action android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"/>
</intent-filter>
</receiver>
</application>

</manifest>

app的自动更新(调用DownloadManager)的更多相关文章

  1. 如何实现已发布app的自动更新

    要实现app的自动更新,做两件事情就可以搞定 1.获取当前手机中的app版本号 我们可以通过查询mainbundle中的获取CFBundleVersion NSDictionary *infoDict ...

  2. Android App版本自动更新

    App在开发过程中,随着业务场景的不断增多,功能的不断完善,早期下载App的用户便无法体验最新的功能,为了能让用户更及时的体验App最新版本,在App开发过程加入App自动更新功能便显得尤为重要.更新 ...

  3. Android实现App版本自动更新

    现在很多的App中都会有一个检查版本的功能.例如斗鱼TV App的设置界面下: 当我们点击检查更新的时候,就会向服务器发起版本检测的请求.一般的处理方式是:服务器返回的App版本与当前手机安装的版本号 ...

  4. H5+app,自动更新后自动删除安装包

    H5+app 自动删除安装包 一.前言 之前做好的app自动更新,遗留下了一个问题,就是自动更新后安装包没有自行删除掉. 好像现在的手机的系统是有安装完自动清理安装包的.想我这个H5+的app安装完后 ...

  5. Android App自动更新解决方案(DownloadManager)

    一开始,我们先向服务器请求数据获取版本 public ObservableField<VersionBean> appVersion = new ObservableField<&g ...

  6. HBuilderX开发app实现自动更新版本

      需求说明:使用MUI+Vue等技术并且通过HBuilderX打包开发移动app,在有版本更新时需要自动提示用户有新版本,并且可以点击下载自动安装. 思路说明: 应用打开时(使用Vue的生命周期mo ...

  7. Android(2)—Mono For Android App版本自动更新

    0.前言 公司Android查询的项目已经开始,整体采用Java后台+App前台来实现,由于项目小,App这块就我一个人开发,首先需要研究的是:Android版本的更新升级问题:本人经过近一周的学习整 ...

  8. Android(3)—Mono For Android App版本自动更新(2)

    0.前言 这篇博文是上一篇的延续,主要是修改上一个版中的BUG和优化一些待完善的项,也算是结贴,当然还有需要完善的,等日后项目中用到的时候再单独写出来吧,本篇主要写升级改进的部分: 改进1.修复[BU ...

  9. Web APP自动更新

    我们的手机软件每天都要经营,经常需要更新,比如程序的Bug,好的功能,好的洁面... ... 这就需要我们的用户打开web app时候自动更新客户端程序,而不是再去应用程序商店从新下载.今天的笔记就是 ...

随机推荐

  1. Yii读取TXT文件数据插入到数据库

    个人平时会用到的方法,记录一下并分享给需要的朋友,Yii批量添加还需要clone一下model才可以,不然只会插入一条数据. 也可以把文件通过参数的方式调入到方法中. // 读取CVS文件 funct ...

  2. JSON格式化与serialize序列化

    一.JSON格式化 1. JSON是什么 JSON是一种数据的存储格式,用来沟通客户端Javascript和服务端PHP的交互.我们把用PHP生成JSON后的字符串传给前台Javascript,Jav ...

  3. Python笔记总结week1

    1. Python介绍: 发明者:Guido 应用范围:网络应用.科学运算.GUI程序.系统管理工具.其他程序 优势:简单易懂.开发效率高.高级语言.可移植性.可扩展性.可嵌入性. 缺点:速度慢,代码 ...

  4. javascript在IE/FF/Chrome的一些兼容问题

    1.获取滚动条高度 var top=document.body.scrollTop||document.documentElement.scrollTop; 2.事件监听 var addEvent = ...

  5. 安装VS 2013遇到的问题,及解决方案

    一.在启动调试时报错 Visual Studio 2013 虽然集成安装了 IIS Express 8.0,但是并未安装 WebMatrix ,第一个问题就是这个原因造成的. 解决方案: 1.下载最新 ...

  6. Debian/Ubuntu/CentOS VPS安装Net-Speeder并优化

    安装过程: CentOS安装 wget --no-check-certificate https://gist.github.com/LazyZhu/dc3f2f84c336a08fd6a5/raw/ ...

  7. EasyUI表单内容整理

    <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding= ...

  8. 100. Same Tree

    [题目] Given two binary trees, write a function to check if they are equal or not. Two binary trees ar ...

  9. 检索 COM 类工厂中 CLSID 为 {820280E0-8ADA-4582-A1D9-960A83CE8BB5} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))。

    检索 COM 类工厂中 CLSID 为 {820280E0-8ADA-4582-A1D9-960A83CE8BB5} 的组件失败,原因是出现以下错误: 80040154 没有注册类 (异常来自 HRE ...

  10. Switch图形练习

    //package IfAndSwitchs;import java.util.Scanner; public class Mianji { public static void main(Strin ...