具体思路为:调用接口与服务器版本对比,当服务器版本号大于本地的,调用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. python简介和入门

    一.什么是python? python是一种面向对象.解释型的计算机语言,它的特点是语法简洁.优雅.简单易学. 二.解释型语言和编译型语言 编译型语言--就是先把写好的程序翻译成计算机语言然后执行,就 ...

  2. C# DateTime 格式化 奇怪问题!

    使用 DateTime.Now.ToString("MM/dd") 本地显示 06/16 window sevcie 2003  显示是 06-16 解决方法: DateTime. ...

  3. [转载]ASP.NET中TextBox控件设立ReadOnly="true"后台取不到值

    原文地址:http://www.cnblogs.com/yxyht/archive/2013/03/02/2939883.html ASP.NET中TextBox控件设置ReadOnly=" ...

  4. Ext4 ComboBox组件使用

     先来看例子: Ext.define('schoolModel', { extend: 'Ext.data.Model', fields: [{ name: 'id', type: 'string' ...

  5. nano编辑器使用教程

    使用Linux VPS会经常和编辑器打交道,一般常用的是vi和nano,虽然vi功能强大,但是相对新手来要稍微难上手,GNU nano是一个体积小巧而功能强大的文本编辑器.这里就简单说一下nano的使 ...

  6. Jquery的各种验证

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  7. USACO 2014 JAN 滑雪录像

    2. 滑雪录像{silver题3} [问题描述] 冬奥会的电视时刻表包含N (1 <= N <= 150)个节目,每个节目都有开始和结束时间.农民约翰有两台录像机,请计算他最多可以录制多少 ...

  8. 深入replace

    replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串. stringObject.replace(reg/str,str/replacement); 这里主 ...

  9. Request和response的用法总结

    Request 个我总结:只要记住 只要是有关于客户端请求的信息,都可以藉由它来取得,例如请求标头.请求方法.请求参数.使用者IP等等信息. 3.什么情况下为响应?什么情况下为请求? 简单一句话,请求 ...

  10. code of C/C++(2)

    初学者学习构造函数和析构函数,面对如何构造的问题,会头大.这里提供了变量(int,double,string),char *,字符数组三个类型的私有成员初始化的方法 //char * 类型的成员,如何 ...