java程序远程自动更新,Android软件的自动更新【demo】

1、之前写过一篇说版本升级的,用到广播。感觉乱用,搞的有点复杂,且混乱。现在又用到了版本升级功能,然后梳理下思路,使用回调接口重新写了个。

3、增加了点小功能:

1>、可以手动检查升级;

2>、显示升级日志;

3>、修改上篇博客潜在问题:

问题:后台查询到更新,提示更新的AlertDialog只能在启动更新的页面弹出;如果离开此页面,抛异常。

解决:在app的所有页面顶层弹出,参考代码://设置dialog

dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);

//加入权限

4、截图如下:

b0d5f2ab93de8a9b7a811b59d7c8be44.png

c4f7ab9b29c7d257d0cf1792141a3562.png

5、上代码(代码才能说明一切):

(1)、DownloadCallback.java/**

* 下载数据接口

* @author: aokunsang

* @date: 2012-12-17

*/

public interface DownloadCallback {

/**

* 下载前准备

*/

public void onDownloadPreare();

/**

* 下载进度更新

* @param progress 进度值

*/

public void onChangeProgress(int progress);

/**

* 下载完成

* @param success 下载成功标示

* @param errorMsg 下载失败显示内容

*/

public void onCompleted(boolean success,String errorMsg);

/**

* 取消下载

*/

public boolean onCancel();

}

(2)、DownloadInstall.java/**

* @author: aokunsang

* @date: 2012-12-18

*/

public class DownloadInstall implements DownloadCallback {

private Context mContext;

private String apkPath,apkVersion;

private int apkCode;

private LayoutInflater inflater;

private TextView textView;

private ProgressBar progressView;

private AlertDialog downloadDialog; //下载弹出框

private boolean interceptFlag = false; //是否取消下载

public DownloadInstall(Context mContext,String apkPath,String apkVersion,int apkCode) {

this.mContext = mContext;

this.apkCode = apkCode;

this.apkPath = apkPath;

this.apkVersion = apkVersion;

inflater = LayoutInflater.from(mContext);

}

@Override

public boolean onCancel() {

return interceptFlag;

}

@Override

public void onChangeProgress(int progress) {

progressView.setProgress(progress); //设置下载进度

textView.setText("进度:"+progress+"%");

}

@Override

public void onCompleted(boolean success, String errorMsg) {

if(downloadDialog!=null){

downloadDialog.dismiss();

}

if(success){ //更新成功

alearyUpdateSuccess();

installApk();

}else{

Toast.makeText(mContext, errorMsg, Toast.LENGTH_SHORT).show();

}

}

@Override

public void onDownloadPreare() {

if(IntentUtil.checkSoftStage(mContext)){

File file = new File(Const.apkSavepath);

if(!file.exists()){

file.mkdir();

}

Builder builder = new AlertDialog.Builder(mContext);

builder.setIcon(R.drawable.upgrade).setTitle("正在更新版本");

//---------------------------- 设置在对话框中显示进度条 --------------------

View view = inflater.inflate(R.layout.upgrade_apk, null);

textView = (TextView)view.findViewById(R.id.progressCount_text);

textView.setText("进度:0");

progressView = (ProgressBar)view.findViewById(R.id.progressbar);

builder.setView(view);

builder.setNegativeButton("取消", new DialogInterface.OnClickListener(){

@Override

public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

interceptFlag = true;

}

});

downloadDialog = builder.create();

downloadDialog.show();

}

}

/**

* 升级成功,更新升级日期和版本号,和版本code

*/

private void alearyUpdateSuccess(){

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0);

sharedPreference.edit().putString(UpdateShared.UPDATE_DATE, sdf.format(new Date()))

.putString(UpdateShared.APK_VERSION, apkVersion).putInt(UpdateShared.APK_VERCODE, apkCode).commit();

}

/**

* 安装apk

*/

private void installApk(){

File file = new File(apkPath);

if(!file.exists()){

return;

}

Intent intent = new Intent(Intent.ACTION_VIEW);

intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");

mContext.startActivity(intent);

}

}

(3)、DownloadAsyncTask.java/**

* 异步下载数据

* @author: aokunsang

* @date: 2012-12-17

*/

public class DownloadAsyncTask extends AsyncTask {

private DownloadCallback downCallBack;

private HttpURLConnection urlConn;

public DownloadAsyncTask(DownloadCallback downloadCallback){

this.downCallBack = downloadCallback;

}

@Override

protected void onPreExecute() {

downCallBack.onDownloadPreare();

super.onPreExecute();

}

@Override

protected String doInBackground(String... args) {

String apkDownloadUrl = args[0]; //apk下载地址

String apkPath = args[1]; //apk在sd卡中的安装位置

String result = "";

if(!IntentUtil.checkURL(apkDownloadUrl)){

result = "netfail";

}else{

InputStream is = null;

FileOutputStream fos = null;

try {

URL url = new URL(apkDownloadUrl);

urlConn = (HttpURLConnection)url.openConnection();

is = urlConn.getInputStream();

int length = urlConn.getContentLength(); //文件大小

fos = new FileOutputStream(apkPath);

int count = 0,numread = 0;

byte buf[] = new byte[1024];

while(!downCallBack.onCancel()&& (numread = is.read(buf))!=-1){

count+=numread;

int progressCount =(int)(((float)count / length) * 100);

publishProgress(progressCount);

fos.write(buf, 0, numread);

}

fos.flush();

result = "success";

} catch (Exception e) {

e.printStackTrace();

result = "fail";

}finally{

try {

if(fos!=null)

fos.close();

if(is!=null)

is.close();

} catch (IOException e) {

e.printStackTrace();

result = "fail";

}

}

}

return result;

}

@Override

protected void onProgressUpdate(Integer... values) {

downCallBack.onChangeProgress(values[0]);

super.onProgressUpdate(values);

}

@Override

protected void onPostExecute(String result) {

if(downCallBack.onCancel()){

downCallBack.onCompleted(false, "版本更新下载已取消。");

}else if("success".equals(result)){

downCallBack.onCompleted(true, null);

}else if("netfail".equals(result)){

downCallBack.onCompleted(false, "连接服务器失败,请稍后重试。");

}else{

downCallBack.onCompleted(false, "版本更新失败,请稍后重试。");

}

super.onPostExecute(result);

}

@Override

protected void onCancelled() {

if(urlConn!=null){

urlConn.disconnect();

}

super.onCancelled();

}

}

(4)、DownloadManager.java/**

* 下载管理

* @author: aokunsang

* @date: 2012-12-18

*/

public class DownloadManager{

private Context mContext;

final static int CHECK_FAIL = 0;

final static int CHECK_SUCCESS = 1;

final static int CHECK_NOUPGRADE = 2;

final static int CHECK_NETFAIL = 3;

private ApkInfo apkinfo;

private AlertDialog noticeDialog; //提示弹出框

private ProgressDialog progressDialog;

private boolean isAccord; //是否主动检查软件升级

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

public DownloadManager(Context mContext,boolean isAccord){

this.mContext = mContext;

this.isAccord = isAccord;

}

Handler handler = new Handler(){

public void handleMessage(android.os.Message msg) {

if(progressDialog!=null){

progressDialog.dismiss();

}

switch(msg.what){

case CHECK_SUCCESS:{

showNoticeDialog();

break;

}

case CHECK_NOUPGRADE:{ //不需要更新

if(isAccord) Toast.makeText(mContext, "当前版本是最新版。", Toast.LENGTH_SHORT).show();

break;

}

case CHECK_NETFAIL:{

if(isAccord) Toast.makeText(mContext, "网络连接不正常。", Toast.LENGTH_SHORT).show();

break;

}

case CHECK_FAIL:{

if(isAccord) Toast.makeText(mContext, "从服务器获取更新数据失败。", Toast.LENGTH_SHORT).show();

break;

}

}

};

};

/* 检查下载更新 [apk下载入口] */

public void checkDownload(){

if(isAccord) progressDialog = ProgressDialog.show(mContext, "", "请稍后,正在检查更新...");

new Thread() {

@Override

public void run() {

if(!IntentUtil.isConnect(mContext)){ //检查网络连接是否正常

handler.sendEmptyMessage(CHECK_NETFAIL);

}else if(checkTodayUpdate() || isAccord){//判断今天是否已自动检查过更新 ;如果手动检查更新,直接进入

String result = HttpRequestUtil.getSourceResult(Const.apkCheckUpdateUrl, null, mContext);

try {

//从服务器下载数据有中文,所以服务器对数据进行了编码;在这里需要解码

result = Escape.unescape(result);

JSONObject obj = new JSONObject(result);

String apkVersion = obj.getString("apkVersion");

int apkCode = obj.getInt("apkVerCode");

String apkSize = obj.getString("apkSize");

String apkName = obj.getString("apkName");

String downloadUrl = obj.getString("apkDownloadUrl");

String apkLog = obj.getString("apklog");

apkinfo = new ApkInfo(downloadUrl, apkVersion, apkSize, apkCode, apkName, apkLog);

if(apkinfo!=null && checkApkVercode()){ //检查版本号

alreayCheckTodayUpdate(); //设置今天已经检查过更新

handler.sendEmptyMessage(CHECK_SUCCESS);

}else{

handler.sendEmptyMessage(CHECK_NOUPGRADE);

}

} catch (Exception e) {

e.printStackTrace();

handler.sendEmptyMessage(CHECK_FAIL);

}

}

}

}.start();

}

/* 弹出软件更新提示对话框*/

private void showNoticeDialog(){

StringBuffer sb = new StringBuffer();

sb.append("版本号:"+apkinfo.getApkVersion()+"\n")

.append("文件大小:"+apkinfo.getApkSize()+"\n")

.append("更新日志:\n"+apkinfo.getApkLog());

Builder builder = new AlertDialog.Builder(mContext);

builder.setIcon(R.drawable.upgrade).setTitle("版本更新").setMessage(sb.toString());

builder.setPositiveButton("下载", new DialogInterface.OnClickListener(){

@Override

public void onClick(DialogInterface dialog, int which) {

String apkPath = Const.apkSavepath + apkinfo.getApkName();

DownloadCallback downCallback = new DownloadInstall(mContext, apkPath, apkinfo.getApkVersion(), apkinfo.getApkCode());

DownloadAsyncTask request = new DownloadAsyncTask(downCallback);

request.execute(apkinfo.getDownloadUrl(),apkPath);

dialog.dismiss();

}

});

builder.setNegativeButton("以后再说", new DialogInterface.OnClickListener(){

@Override

public void onClick(DialogInterface dialog, int which) {

dialog.dismiss();

}

});

noticeDialog = builder.create();

noticeDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT); //设置最顶层Alertdialog

noticeDialog.show();

}

/**

* 根据日期检查是否需要进行软件升级

* @throws Exception

*/

private boolean checkTodayUpdate() {

SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0);

String checkDate = sharedPreference.getString(UpdateShared.CHECK_DATE, "");

String updateDate = sharedPreference.getString(UpdateShared.UPDATE_DATE, "");

if("".equals(checkDate) && "".equals(updateDate)){ //刚安装的新版本,设置详细信息

int verCode = IntentUtil.getCurrentVersionCode(mContext);

String versionName = IntentUtil.getCurrentVersionName(mContext);

String dateStr = sdf.format(new Date());

sharedPreference.edit().putString(UpdateShared.CHECK_DATE, dateStr)

.putString(UpdateShared.UPDATE_DATE, dateStr)

.putString(UpdateShared.APK_VERSION, versionName)

.putInt(UpdateShared.APK_VERCODE, verCode).commit();

return true;

}

try {

//判断defaultMinUpdateDay天内不检查升级

if((new Date().getTime()-sdf.parse(updateDate).getTime())/1000/3600/24

return false;

}else if(checkDate.equalsIgnoreCase(sdf.format(new Date()))){//判断今天是否检查过升级

return false;

}

} catch (Exception e) {

e.printStackTrace();

return false;

}

return true;

}

/**

* 设置今天已经检查过升级

* @return

*/

private void alreayCheckTodayUpdate(){

String date = sdf.format(new Date());

SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0);

sharedPreference.edit().putString(UpdateShared.CHECK_DATE, date).commit();

}

/**

* 检查版本是否需要更新

* @return

*/

private boolean checkApkVercode(){

SharedPreferences sharedPreference = mContext.getSharedPreferences(UpdateShared.SETTING_UPDATE_APK_INFO, 0);

int verCode = sharedPreference.getInt(UpdateShared.APK_VERCODE, 0);

if(apkinfo.getApkCode()>verCode){

return true;

}else{

return false;

}

}

static interface UpdateShared{

String SETTING_UPDATE_APK_INFO = "cbt_upgrade_setting";

String UPDATE_DATE = "updatedate";

String APK_VERSION = "apkversion";

String APK_VERCODE = "apkvercode";

String CHECK_DATE = "checkdate";

}

}

代码内容我不讲解,使用的是回调接口。

(5)、其他操作类:

a、Const.java是一个常量存储类,保存检查更新地址等;

b、Escape.java是个URL解码编码类;

c、HttpRequestUtil.java获取远程数据类;

d、IntentUtil.java工具类,如:检查网络连接状态等。

(以上类参考附件源码)/**

* apk更新信息

* @author: aokunsang

* @date: 2012-12-18

*/

public class ApkInfo implements Serializable {

/**

*

*/

private static final long serialVersionUID = 1L;

private String downloadUrl; //下载地址

private String apkVersion; //apk版本

private String apkSize; //apk文件大小

private int apkCode; //apk版本号(更新必备)

private String apkName; //apk名字

private String apkLog; //apk更新日志

setter and getter...

}

(6)、服务器代码(这里的apklog可以是个txt文档,在UI上下载展示,我做的比较简单):/**

* 获取apk更新信息

* {apkVersion:'1.10',apkSize:'36K',apkVerCode:2,apkName:'1.1.apk',apkDownloadUrl:'http://localhost:8080/myapp/1.1.apk',apklog:'1、修改页面;\n2、修改字体'}

*/

@Action(value="checkUpdateApk")

public String updateApk(){

ResourceLoader loader = new DefaultResourceLoader();

Properties pp = null;

try {

InputStream is = loader.getResource("classpath:config/sysconf.properties").getInputStream();

pp = new Properties();

pp.load(new InputStreamReader(is, "utf-8"));

} catch (Exception e) {

e.printStackTrace();

}

if(pp!=null){

String apkVersion = pp.getProperty("apkVersion");

String apkDownloadUrl = pp.getProperty("apkDownloadUrl");

String apkName = pp.getProperty("apkName");

int apkVerCode = NumberUtils.toInt(pp.getProperty("apkVerCode"),0);

String apklog = pp.getProperty("apkLog");

String apkSize = pp.getProperty("apkSize");

Httptear.ResponseResultByEscape("{apkVersion:'"+apkVersion+"',apkSize:'"+apkSize+"',apkVerCode:"+apkVerCode+",apkName:'"+apkName+"',apkDownloadUrl:'"+apkDownloadUrl+"',apklog:'"+apklog+"'}");

}else{

Httptear.ResponseResultByEscape("{}");

}

return NONE;

}

6、upgrade_apk.xml<?xml version="1.0" encoding="utf-8"?>

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

>

android:id="@+id/progressCount_text"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

android:textColor="@color/white"

android:textSize="14dip"

/>

android:id="@+id/progressbar"

style="?android:attr/progressBarStyleHorizontal"

android:layout_width="fill_parent"

android:layout_height="wrap_content"

/>

7、需要加入以下权限:

8、启动更新检查代码:/* 升级程序[主动] (因为会弹出一个ProgressDialog窗口,不能使用getApplicationContext())*/

DownloadManager downManger = new DownloadManager(this,true);

downManger.checkDownload();/* 升级程序启动[被动](使用this引用会导致:如在1页面启动升级,当前页面为2页面,此时弹出Dialog抛异常)*/

DownloadManager downManger = new DownloadManager(getApplicationContext(),false);

downManger.checkDownload();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值