android 实现检测版本,下载apk更新(附源码)
其实这不是什么难事了,都有热更新的技术了,只是记录一下,大神勿嘲笑。
先说下思路,首先要有更新的接口,只要进入app,就监测一下接口,是否更新,更新的话,检测本地版本是否低于接口返回的版本,低的话,就根据返回的路径下载apk更新。接口返回的字段起码有 更新标志、更新版本,更新描述,apk下载地址。
更新标志应该有三种状态,更新,询问更新,强制更新,可以启动一个Service(不要忘记在清单文件中注册)来进行检查更新以及下载的工作;
这下面就是 Service里的全部代码,也不是很难理解,重要的地方都有注释。写好Service后,在代码中 startService()启动就可以了。
这里面弹出了一个讯问框,需要在清单文件中 加入权限, <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />,这是弹出全局讯问框的权限。
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.Service;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.graphics.Color;
import android.net.Uri;
import android.os.Environment;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.WindowManager;
import android.widget.ProgressBar;
import android.widget.TextView; import com.example.sdtz.wenmingweifang.R;
import com.example.sdtz.wenmingweifang.Tool.OkHttpUtil;
import com.example.sdtz.wenmingweifang.Util.App;
import com.example.sdtz.wenmingweifang.Util.MyUrl; import org.json.JSONException;
import org.json.JSONObject; import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; /**
* Created by sdtz on 2017/7/1.
*/
public class UpdateService extends Service {
private ProgressBar mProgressBar;//进度条
private TextView tv1;
private TextView tv2;
private String url = MyUrl.Httpurl;
private String VersionCode;
private String result;
private App app;
private String mSavePath;//apk保存地址
private String mVersion_path;
private String mVersion_name = "app.apk";//apk名
private float length;
private Dialog mDownloadDialog;//对话框
private int mProgress;//进度值
private static final int DOWNLOADING = 1;//apk下载中
private static final int DOWNLOAD_FINISH = 2;//apk下载完毕
private boolean mIsCancel = false;//是否取消下载标示符 @Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
} private Handler mUpdateProgressHandler = new Handler(){
public void handleMessage(Message msg) {
switch (msg.what){
case DOWNLOADING:
// 设置进度条
mProgressBar.setProgress(mProgress);
tv1.setText( mProgress + "/100");
float len = length/1024/1024;//将length转换为M单位
float b = (float)(Math.round(len*100))/100;//保留两位小数点
tv2.setText( b+"M");
break;
case DOWNLOAD_FINISH:
// 隐藏当前下载对话框
mDownloadDialog.dismiss();
// 安装 APK 文件
installAPK();
break;
default:
break;
}
};
};
@Override
public int onStartCommand(Intent intent, int flags, int startId) { try {
VersionCode = getVersionName();
/* getJsonReuslt();*/
new OkHttpUtil().getJson(MyUrl.appdown, new OkHttpUtil.HttpCallBack() {
@Override
public void onSusscess(String data) throws JSONException {
JSONObject jo1 = new JSONObject(data);
app = new App();
app.setVersion(jo1.getString("version").toString());
app.setDescription(jo1.getString("description").toString());
app.setUrl(MyUrl.Httpurl+jo1.getString("url").toString());
app.setUpdate_flag(jo1.getString("update_flag").toString()); mVersion_path = app.getUrl();
//手机当前版本
String phoneVersion = VersionCode.substring(0,VersionCode.lastIndexOf("."));
Double jiekou = Double.parseDouble(app.getVersion());
Double bendi = null;
try {
bendi = Double.parseDouble(getVersionName());
} catch (Exception e) {
e.printStackTrace();
}
Log.d("==","接口:"+jiekou+"本地:"+bendi+"::"+app.toString());
//本地版本 与 接口返回版本 不一致,并且 更新标志为1 ,则更新
if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("1")){
Log.d("==","::进入");
showDialog(app.getDescription());
}else if( !VersionCode.equals(app.getVersion()) && (jiekou>bendi) && app.getUpdate_flag().equals("2")){
showDownloadDialog();
}
}
});
} catch (Exception e) {
e.printStackTrace();
} catch (Throwable throwable) {
throwable.printStackTrace();
} return super.onStartCommand(intent, flags, startId);
} /*
* 获取当前程序的版本号
*/
private String getVersionName() throws Exception{
//获取packagemanager的实例
PackageManager packageManager = getPackageManager();
//getPackageName()是你当前类的包名,0代表是获取版本信息
PackageInfo packInfo = packageManager.getPackageInfo(getPackageName(), 0);
return packInfo.versionName;
} private void showDialog(String drc) {
final AlertDialog.Builder builder = new AlertDialog.Builder(this,AlertDialog.THEME_HOLO_LIGHT);
builder.setMessage(drc); builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
showDownloadDialog();
}
}); builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
dialogInterface.dismiss();
}
}); AlertDialog alertDialog = builder.create();
alertDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
alertDialog.setCanceledOnTouchOutside(true); alertDialog.show(); alertDialog.getButton(alertDialog.BUTTON_POSITIVE).setTextColor(Color.GREEN);
alertDialog.getButton(alertDialog.BUTTON_NEGATIVE).setTextColor(Color.RED); } /*
* 开启新线程下载文件
*/
private void downloadAPK() { new Thread(new Runnable() {
@Override
public void run() {
try{//检查sd是否挂载
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
String sdPath = Environment.getExternalStorageDirectory() + "/";
mSavePath = sdPath + "WenmingDownload"; File dir = new File(mSavePath);
if (!dir.exists())
dir.mkdir();
// 下载文件
HttpURLConnection conn = (HttpURLConnection) new URL(mVersion_path).openConnection();
conn.connect();
InputStream is = conn.getInputStream();
length = conn.getContentLength();
File apkFile = new File(mSavePath, mVersion_name);
FileOutputStream fos = new FileOutputStream(apkFile); int count = 0;
byte[] buffer = new byte[1024];
while (!mIsCancel){
int numread = is.read(buffer);
count += numread;
// 计算进度条的当前位置
mProgress = (int) ((count/length) * 100);
// 更新进度条
mUpdateProgressHandler.sendEmptyMessage(DOWNLOADING); // 下载完成
if (numread < 0){
mUpdateProgressHandler.sendEmptyMessage(DOWNLOAD_FINISH);
break;
}
fos.write(buffer, 0, numread);
}
fos.close();
is.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}).start();
} /*
* 下载到本地后执行安装
*/
protected void installAPK() {
File apkFile = new File(mSavePath, mVersion_name);
if (!apkFile.exists())
return; Intent intent = new Intent(Intent.ACTION_VIEW);
Uri uri = Uri.parse("file://" + apkFile.toString());
intent.setDataAndType(uri, "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
this.startActivity(intent); }
/*
* 显示正在下载对话框
*/
protected void showDownloadDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("版本更新,下载中。。。");
View view = LayoutInflater.from(this).inflate(R.layout.dialog_progress, null);
mProgressBar = (ProgressBar) view.findViewById(R.id.id_progress);
tv1 = (TextView) view.findViewById(R.id.tv1);
tv2 = (TextView) view.findViewById(R.id.tv2);
builder.setView(view);
mDownloadDialog = builder.create();
mDownloadDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
mDownloadDialog.show(); // 下载文件
downloadAPK();
} }
android 实现检测版本,下载apk更新(附源码)的更多相关文章
- 转载—— android 瀑布流的实现详解,附源码
介绍 参考自:https://github.com/dodola/android_waterfall,因为原来的代码封装不好,所以,我根据源码的思路,重新写了一遍,所以有了现在这个项目:https:/ ...
- [BOT]自己动手实现android 饼状图,PieGraphView,附源码解析
本文要介绍的是一个参照手机支付宝app里面记账本功能里的"饼状图"实现的控件.通常app中可能的数据展示控件有柱状图,折线图,饼状图等,如果需要一个包含多种View控件的库,那么 ...
- wpf 模拟抖音很火的罗盘时钟,附源码,下载就能跑
wpf 模拟抖音很火的罗盘时钟,附源码 前端时间突然发现,抖音火了个壁纸,就是黑底蕾丝~~~ 错错错,黑底白字的罗盘时钟! 作为程序员的我,也觉得很新颖,所以想空了研究下,这不,空下来了就用wpf, ...
- Android自动检测版本及自动升级
步骤: 1.检测当前版本的信息AndroidManifest.xml-->manifest-->android:versionName. 2.从服务器获取版本号(版本号存在于xml文件中) ...
- Android中Canvas绘图基础详解(附源码下载) (转)
Android中Canvas绘图基础详解(附源码下载) 原文链接 http://blog.csdn.net/iispring/article/details/49770651 AndroidCa ...
- 【流媒体开发】VLC Media Player - Android 平台源码编译 与 二次开发详解 (提供详细800M下载好的编译源码及eclipse可调试播放器源码下载)
作者 : 韩曙亮 博客地址 : http://blog.csdn.net/shulianghan/article/details/42707293 转载请注明出处 : http://blog.csd ...
- 【转】可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
原文地址:http://www.cnblogs.com/justnow/p/3382160.html (最新版本:V6.0,2017.12.11 .即将推出Xamarin移动端版本,包括 Androi ...
- 可在广域网部署运行的即时通讯系统 -- GGTalk总览(附源码下载)
(最新版本:V6.2,2019.01.03 .Xamarin移动端版本已经推出,包括 Android 和 iOS) GGTalk开源即时通讯系统(简称GG)是QQ的高仿版,同时支持局域网和广域网, ...
- 分享一组很赞的 jQuery 特效【附源码下载】
作为最优秀的 JavaScript 库之一,jQuery 不仅使用简单灵活,同时还有许多成熟的插件可供选择,它可以帮助你在项目中加入漂亮的效果.这篇文章挑选了8个优秀的 jQuery 实例教程,这些 ...
- Cesium专栏-雷达遮罩动态扫描(附源码下载)
Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精度,渲染质量以 ...
随机推荐
- 05.深入理解JMM和Happens-Before
大家好,我是王有志. JMM都问啥? 最近沉迷P5R,所以写作的进度很不理想,但不得不说高卷杏YYDS.话不多说,开始今天的主题,JMM和Happens-Before. 关于它们的问题并不多,基本上只 ...
- win10 WSL2问题解决“WslRegisterDistribution failed with error: 0x800701bc”
win10安装wsl过程报错信息如下: 造成该问题的原因是WSL版本由原来的WSL1升级到WSL2后,内核没有升级,前往微软WSL官网下载安装适用于 x64 计算机的最新 WSL2 Linux 内核更 ...
- 纸张尺寸【第十三届蓝桥杯省赛C++C组】
纸张尺寸 在 ISO 国际标准中定义了 \(A0\) 纸张的大小为 \(1189mm×841mm\),将 \(A0\) 纸沿长边对折后为 \(A1\) 纸,大小为 \(841mm×594mm\) ,在 ...
- 初始化一个GCP项目并用gcloud访问操作
1 简介 谷歌云GCP(Google Cloud Platform)是由Google提供的云平台,还是为用户提供了许多免费的产品,还是可以尝试一下的.对于学习或者小项目,都可以使用. 2 创建一个新项 ...
- 近邻取样插值方法缩放BGRA图片数据
近邻取样插值原理: 对于缩放后图片中的某点 (Dx, Dy) 对应于原图片中的点 (Sx, Sy),它们之间存在如下的比例关系: (Sx-0)/(SW-0)=(Dx-0)/(DW-0) (Sy-0)/ ...
- SQL中常用函数操作
--在SQL SERVER中批量替换字符串的方法 update [Table] set [Field] = REPLACE([Field],'被替换的原内容','要替换的内容') update HBb ...
- Apache RocketMQ 5.0 笔记
RocketMQ 5.0:云原生"消息.事件.流"实时数据处理平台,覆盖云边端一体化数据处理场景. 核心特性 云原生:生与云,长与云,无限弹性扩缩,K8s友好 高吞吐:万亿级吞吐保 ...
- do while 出口條件循環
- flutter 2.X报错 Bad state: Insecure HTTP is not allowed by platform:
flutter2.x开发遇到的问题 Bad state: Insecure HTTP is not allowed by platform: 翻译过来就是:错误状态:平台不允许不安全的HTTP: 产生 ...
- XAMPP-Apache-解决跨域
很 意外啊,我这篇文章竟然说因为有广告,所以审核不通过.牛逼,我接着发,我看哪来的广告.审核有广告是NT技术写的逻辑,还是没脑子的审核员审核的. 因为在做项目的时候,会有很多项目要进行热更测试,可有些 ...