app的自动更新(调用DownloadManager)
具体思路为:调用接口与服务器版本对比,当服务器版本号大于本地的,调用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)的更多相关文章
- 如何实现已发布app的自动更新
要实现app的自动更新,做两件事情就可以搞定 1.获取当前手机中的app版本号 我们可以通过查询mainbundle中的获取CFBundleVersion NSDictionary *infoDict ...
- Android App版本自动更新
App在开发过程中,随着业务场景的不断增多,功能的不断完善,早期下载App的用户便无法体验最新的功能,为了能让用户更及时的体验App最新版本,在App开发过程加入App自动更新功能便显得尤为重要.更新 ...
- Android实现App版本自动更新
现在很多的App中都会有一个检查版本的功能.例如斗鱼TV App的设置界面下: 当我们点击检查更新的时候,就会向服务器发起版本检测的请求.一般的处理方式是:服务器返回的App版本与当前手机安装的版本号 ...
- H5+app,自动更新后自动删除安装包
H5+app 自动删除安装包 一.前言 之前做好的app自动更新,遗留下了一个问题,就是自动更新后安装包没有自行删除掉. 好像现在的手机的系统是有安装完自动清理安装包的.想我这个H5+的app安装完后 ...
- Android App自动更新解决方案(DownloadManager)
一开始,我们先向服务器请求数据获取版本 public ObservableField<VersionBean> appVersion = new ObservableField<&g ...
- HBuilderX开发app实现自动更新版本
需求说明:使用MUI+Vue等技术并且通过HBuilderX打包开发移动app,在有版本更新时需要自动提示用户有新版本,并且可以点击下载自动安装. 思路说明: 应用打开时(使用Vue的生命周期mo ...
- Android(2)—Mono For Android App版本自动更新
0.前言 公司Android查询的项目已经开始,整体采用Java后台+App前台来实现,由于项目小,App这块就我一个人开发,首先需要研究的是:Android版本的更新升级问题:本人经过近一周的学习整 ...
- Android(3)—Mono For Android App版本自动更新(2)
0.前言 这篇博文是上一篇的延续,主要是修改上一个版中的BUG和优化一些待完善的项,也算是结贴,当然还有需要完善的,等日后项目中用到的时候再单独写出来吧,本篇主要写升级改进的部分: 改进1.修复[BU ...
- Web APP自动更新
我们的手机软件每天都要经营,经常需要更新,比如程序的Bug,好的功能,好的洁面... ... 这就需要我们的用户打开web app时候自动更新客户端程序,而不是再去应用程序商店从新下载.今天的笔记就是 ...
随机推荐
- JavaScipt 事件体系
事件机制 jQuery对事件的绑定分别有几个API .bind()/.live()/.delegate()/.on() 不管是用什么方式绑定,归根到底还是用addEventListener/attac ...
- phpize建立php扩展 Cannot find config.m4
centos php 安装 memcache 扩展的时候 爆 Cannot find config.m4 错误 解决方案参考以下文章 参考文章 http://blog.csdn.net/wgl ...
- winform flash
1.开发工具:VS2013 2.开发环境:win 10 64位 3.添加控件: 打开VS,点击工具箱--常规--右键--“选择项”---“Com组件”--MacroMedia Flash Factor ...
- HDU 3033 分组背包变形(每种至少一个)
I love sneakers! Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) ...
- 几个实用的mysql函数
在工作中,处理数据时候往往使用php要废很多脑筋和写很多东西,如果不考虑代码的阅读性试试几个mysql的函数可以解决许多常见需求: 1.截取字符串函数: left() 从左开始截取字符串 right ...
- twrp编译步骤 (CWM也差不多)
1.源码的跟目录执行:. build/envsetup.sh,构建编译环境 2.执行 make -j4 otatools,生成后面编译需要的工具 3.把boot或recovery放到home目录,执行 ...
- 获取当前时间UTC时间的下一个15分钟时间点
ZonedDateTime zdt = ZonedDateTime.now(ZoneOffset.UTC); int now15Minute = zdt.getMinute() / P15MINUTE ...
- Bootstrap<基础二十七> 多媒体对象(Media Object)
Bootstrap 中的多媒体对象(Media Object).这些抽象的对象样式用于创建各种类型的组件(比如:博客评论),我们可以在组件中使用图文混排,图像可以左对齐或者右对齐.媒体对象可以用更少的 ...
- 【67测试20161116】【数论】【DP】【思维】
第一题: LGTB 得到了一个序列,他想在这个序列中选择一个最长的连续子序列,使得这个子序列的最大公约数等于1.请告诉他他能得到的最大长度,如果没有这样的序列,输出-1. 对于50% 的数据,1 &l ...
- wordpress 打开卡在1.gravatar.com
grevatar.com打不开,涉及到加载头像的地方都会变慢. 可以使用https的头像链接代替http链接 官方Gravatar头像调用ssl头像链接 进入wordpress后台->外观-&g ...