android 版本检测 Android程序的版本检测与更新实现介绍

做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能。

本来版本检测最好可以自动进行。但如果每次开启程序,都要先检测一轮,是一种浪费,毕竟版本更新是小概率的事情。或许可以程序开启的时候,判断一下时间,单日就检测,双日就不检测,或者随机什么的,降低一下检测的频率?

我采取的做法是将检测功能做到了菜单上,用户有需要,就手动打开自己检测一下。反正我们这个是网站客户端,有版本更新,在网站上发个通告就行了。

版本检测与更新有以下几个关键步骤:

1、检测有无新版本

2、下载新版本

3、安装替换新版本

我处理的方案是

1、在assets文件夹新增一个文件:ver.cfg,记录版本信息,纯文本格式,内容只有一句话:

复制代码 代码如下:

Version=1.0

这个会随安装包装到用户的手机上

然后在网站里面,设置一XML文件ver_apk.xml,内容也只有这么一点:

复制代码 代码如下:

<?xml version="1.0" encoding="utf-8" ?>

<string>1.0</string>

检测的时候,就先访问网站的这个XML,得到最新版本号,然后与手机上的ver.cfg文件里记录的进行比对,不同的话就可以认为存在新版本,提示进行更新。

2、下载的话就是直接下载的,我还不知道怎么弄断点续传

3、安装替换,关键在于签名。就是每个版本的签名要保持一致。否则新的无法替换旧的,提示安装未完成。

------------------- 天气太冷,咯咯咯 ------------------------------------

这个功能做在菜单上,触发代码如下:

复制代码 代码如下:

//==========================================================================

// 菜单

//==========================================================================

private static final String urlApk = "http://3g.***.com/tool/***.apk";

private static final String urlVer = "http://3g.***.com/tool/ver_apk.xml";

@Override

public boolean onCreateOptionsMenu(Menu menu) {

menu.add(Menu.NONE, Menu.FIRST + 1, 5, "检测更新").setIcon(

android.R.drawable.ic_menu_upload);

menu.add(Menu.NONE,Menu.FIRST+2,4,"退出").setIcon(android.R.drawable.ic_lock_power_off);

return true;

}

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

case Menu.FIRST + 1:

Toast.makeText(this, "正在检测版本", Toast.LENGTH_LONG).show();

UpdateVer uv = new UpdateVer(urlApk,urlVer,MainActivity.this);

uv.checkVer();

break;

case Menu.FIRST + 2:

confirmExit();

break;

}

return false;

}

检测更新因为代码比较多,写成一个类进行封装

UpdateVer.java

复制代码 代码如下:

package android.***;

import android.app.Activity;

import android.app.AlertDialog;

import android.app.Dialog;

import android.app.ProgressDialog;

import android.content.Context;

import android.content.DialogInterface;

import android.content.Intent;

import android.net.Uri;

import android.os.AsyncTask;

import android.util.Log;

import android.webkit.URLUtil;

import android.widget.Toast;

import java.io.File;

import java.io.FileNotFoundException;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.net.MalformedURLException;

import java.net.URL;

import java.net.URLConnection;

import java.util.Properties;

import org.xml.sax.InputSource;

import java.text.SimpleDateFormat;

import java.util.Date;

public class UpdateVer extends Activity{

private static final String TAG = "DOWNLOADAPK";

private String PastVersion;

private String NowVersion;

public ProgressDialog pBar;

private String currentFilePath = "";

private String fileEx="";

private String fileNa="";

private String strURL="";

private String VersionUri ="";

private Context mContext;

private final String fileVer = "ver.cfg";

public UpdateVer(String urlapk,String urlver,final Context context){

SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");

String ver = "?ver=" + df.format(new Date());//主要是避开手机的缓存

strURL = urlapk + ver;

VersionUri = urlver + ver;

mContext = context;

}

public void checkVer() {

// 解析Version网页,获取版本号

getVersionxml(VersionUri);

}

private void compareVer() {

load();

//当有最新版本的时候

if(PastVersion != null && !PastVersion.equals(NowVersion)){

Dialog dialog = new AlertDialog.Builder(mContext).setTitle("系统更新")

.setMessage(String.format("发现新版本%s,目前版本为%s,请更新!",NowVersion,PastVersion))// 设置内容

// 设置确定按钮

.setPositiveButton("确定"

,new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog,

int which) {

pBar = new ProgressDialog(mContext);

pBar.setTitle("正在下载");

pBar.setMessage("请稍候...");

pBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);

fileEx = strURL.substring(strURL.lastIndexOf(".") + 1,strURL.length()).toLowerCase();

fileEx = fileEx.substring(0,fileEx.lastIndexOf("?"));

fileNa = strURL.substring(strURL.lastIndexOf("/") + 1,strURL.lastIndexOf("."));

getFile(strURL);

}

}).setNegativeButton("取消",

new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog,

int whichButton) {

// 点击"取消"按钮之后退出程序

}

}).create();// 创建

// 显示对话框

dialog.show();

}

else{

Toast.makeText(mContext, String.format("当前为最新版本%s",PastVersion), Toast.LENGTH_LONG).show();

}

}

private void getFile(final String strPath)

{

pBar.show();

try{

if (strPath.equals(currentFilePath) ){

getDataSource(strPath);

}

currentFilePath = strPath;

Runnable r = new Runnable(){

@Override

public void run()

{

try{

getDataSource(strPath);

}

catch (Exception e){

Log.e(TAG, e.getMessage(), e);

}

}

};

new Thread(r).start();

}

catch(Exception e){

e.printStackTrace();

}

}

/*取得远程文件*/

private void getDataSource(String strPath) throws Exception {

if (!URLUtil.isNetworkUrl(strPath)) {

Log.d("Tag","error");

}

else {

/*取得URL*/

URL myURL = new URL(strPath);

/*建立联机*/

URLConnection conn = myURL.openConnection();

conn.connect();

/*InputStream 下载文件*/

InputStream is = conn.getInputStream();

if (is == null) {

Log.d("tag","error");

throw new RuntimeException("没有读取到文件内容");

}

/*建立临时文件*/

File myTempFile = File.createTempFile(fileNa, "." + fileEx);

myTempFile.getAbsolutePath();

/*将文件写入临时盘*/

FileOutputStream fos = new FileOutputStream(myTempFile);

byte buf[] = new byte[128];

do{

int numread = is.read(buf);

if (numread <= 0) {

break;

}

fos.write(buf, 0, numread);

}while (true);

/*打开文件进行安装*/

openFile(myTempFile);

try {

is.close();

}

catch (Exception ex){

Log.d("Tag","error");

Log.e(TAG, "error: " + ex.getMessage(), ex);

}

}

}

/* 在手机上打开文件 */

private void openFile(File f) {

pBar.cancel();

Intent intent = new Intent();

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setAction(android.content.Intent.ACTION_VIEW);

/* 调用getMIMEType()来取得MimeType */

String type = getMIMEType(f);

/* 设定intent的file与MimeType */

intent.setDataAndType(Uri.fromFile(f),type);

mContext.startActivity(intent);

}

/* 判断文件MimeType的method */

private String getMIMEType(File f) {

String type = "";

String fName = f.getName();

/* 取得扩展名 */

String end = fName.substring(fName.lastIndexOf(".")+1,fName.length()).toLowerCase();

/* 按扩展名的类型决定MimeType */

if(end.equals("m4a")

|| end.equals("mp3")

|| end.equals("mid")

|| end.equals("xmf")

|| end.equals("ogg")

|| end.equals("wav")){

type = "audio";

}

else if(end.equals("3gp") || end.equals("mp4")){

type = "video";

}

else if(end.equals("jpg")

|| end.equals("gif")

|| end.equals("png")

|| end.equals("jpeg")

|| end.equals("bmp")){

type = "image";

}

else if(end.equals("apk")){

/* android.permission.INSTALL_PACKAGES */

type = "application/vnd.android.package-archive";

}

else{

type = "*";

}

/*如果无法直接打开,就跳出软件清单给使用者选择 */

if(!end.equals("apk")){

type += "/*";

}

return type;

}

private void getVersionxml(String resourceUrl){

GetVer gv = new GetVer();

gv.execute(resourceUrl);

}

private boolean load(){

Properties properties = new Properties();

try{

InputStream stream = mContext.getAssets().open(fileVer);

//FileInputStream stream = mContext.openFileInput(fileVer);

//读取文件内容

properties.load(stream);

}

catch (FileNotFoundException e){

return false;

}

catch(IOException e){

return false;

}

catch(Exception e){

return false;

}

PastVersion = String.valueOf(properties.get("Version").toString());

return true;

}

//==========================================================================

// GetVer

//==========================================================================

class GetVer extends AsyncTask<String, Integer, String> {

@Override

protected String doInBackground(String... urlVer) {

String db = null;

URL url = null;

try {

url = new URL(urlVer[0]);

}

catch (MalformedURLException e) {

e.printStackTrace();

}

InputSource is = null;

try {

is = new InputSource(url.openStream());

is.setEncoding("UTF-8");

db = SAXGetVersionService.readRssXml(is);

}

catch (Exception e) {

e.printStackTrace();

}

return db;

}

@Override

protected void onCancelled() {

super.onCancelled();

}

@Override

protected void onPostExecute(String result) {

NowVersion = result;

compareVer();

}

}

}

AndroidManifest.xml要加上几句

复制代码 代码如下:

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

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

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

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

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

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

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

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

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

时间: 2024-11-05 22:38:24

android 版本检测 Android程序的版本检测与更新实现介绍的相关文章

android 版本检测 Android程序的版本检测与更新实现介绍_Android

做个网站的安卓客户端,用户安装到自己手机上,如果我出了新版本怎么办呢?要有版本更新功能. 本来版本检测最好可以自动进行.但如果每次开启程序,都要先检测一轮,是一种浪费,毕竟版本更新是小概率的事情.或许可以程序开启的时候,判断一下时间,单日就检测,双日就不检测,或者随机什么的,降低一下检测的频率? 我采取的做法是将检测功能做到了菜单上,用户有需要,就手动打开自己检测一下.反正我们这个是网站客户端,有版本更新,在网站上发个通告就行了. 版本检测与更新有以下几个关键步骤: 1.检测有无新版本 2.下载

Android服务器——使用TomCat实现软件的版本检测,升级,以及下载更新进度!

Android服务器--使用TomCat实现软件的版本检测,升级,以及下载更新进度! 算下来,TomCat服务器已经写了很长一段时间了,一直说拿他来搞点事 情,也一直没做,今天刚好有空,交流群还有人请教,就寻思着把一些相关性的原理和基础操作写下来,虽然我网络这一块还是不怎么扎实,嘿嘿,还记得我们怎么搭建的服务器吗? 地址:Android服务器--TomCat服务器的搭建 我们新建一个项目TomCatVersion 这边先来说一下原理,我们做的小例子也是十分的简单,一个首页,我们用Handler实

android 当后台程序全部退出后 重新打开软件时 如何进行软件更新提示

问题描述 android 当后台程序全部退出后 重新打开软件时 如何进行软件更新提示 android 当软件第一次被打开时会进行版本检测 弹出新版本更新提示对话框 点击cancel暂不升级 会在sharedpreferences中set一个boolean值为false(一开始默认为true) 当后台程序全部退出后 重新打开软件时 这个boolean值貌似还是false 这个情况如何进行软件更新提示 这个值怎么设 或者换一种方法也可以 解决方案 你为什么要通过sharedpreferences中的

Android程序版本更新之通知栏更新下载安装_Android

Android应用检查版本更新后,在通知栏下载,更新下载进度,下载完成自动安装,效果图如下: •检查当前版本号 AndroidManifest文件中的versionCode用来标识版本,在服务器放一个新版本的apk,versioncode大于当前版本,下面代码用来获取versioncode的值 PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0); int

在IBM Rational Performance Tester中录制Android客户端应用程序测试脚本

编写本文的背景 随着智能电话使用率的增长,越来越多的基于 Web 的应用程序开始提供从移动客 户端访问的能力,无论该客户端是浏览器还是原生应用程序.在这两种情况下,这些客户端都可以使用 HTTP 作为网络协议,在理论上,可以使用主要的负载测试工具对它们进行测试.但另一方面,目前的大多数可用产 品(包括 IBM Rational Performance Tester)都没有内置的功能来录制对移动客户端应用程序的测试. 本文将介绍如何使用 Android 模拟器,设置一个简单框架,在 Rationa

如何构建Android MVVM应用程序

1.概述 Databinding 是一种框架,MVVM是一种模式,两者的概念是不一样的.我的理解DataBinding是一个实现数据和UI绑定的框架,只是一个实现MVVM模式的工具.ViewModel和View可以通过DataBinding来实现单向绑定和双向绑定,这套UI和数据之间的动态监听和动态更新的框架Google已经帮我们做好了.在MVVM模式中ViewModel和View是用绑定关系来实现的,所以有了DataBinding 使我们构建Android MVVM 应用程序成为可能. 之前看

为您的Android移动应用程序添加导航风格

如今移动设备的功能已经强大到难以置信,比众多http://www.aliyun.com/zixun/aggregation/7155.html">开发人员用来编写首个程序的桌面计算机还要强大得多.因此,大家很容易忘记移动设备仍然属于资源有限的环境.开发移动应用程序时,决不能忘记运行应用程序的环境所具有的局限性.尤其是当应用程序要与其他应用程序竞争系统资源时 - 其中有些应用程序对于用户的日常行为而言比您的应用程序更加重要. 确保应用程序广受欢迎的途径之一是保证它节省系统资源.在 Andro

Android获取应用程序大小和缓存的实例代码_Android

info package com.qin.appsize; import android.content.Intent; import android.graphics.drawable.Drawable; //Model类 ,用来存储应用程序信息 public class AppInfo { private String appLabel; //应用程序标签 private Drawable appIcon ; //应用程序图像 private Intent intent ; //启动应用程序

图片-用Android之前做程序都做的好好的 今天做了一半突然出现了 求解这是什么情况

问题描述 用Android之前做程序都做的好好的 今天做了一半突然出现了 求解这是什么情况 ![ Android @Override not applicable to method 以前做程序都做的好好的 今天做了一半突然遮掩了 求解这是什么情况 解决方案 更新一下android studio1.5吧,我之前用1.4老出问题 解决方案二: gradle编译出错了 解决方案三: 应该是你升级SDK了. actionbarActivity 是 @Deprecated