android 在线升级借助开源中国App源码

http://www.cnblogs.com/luomingui/p/3949429.html

android 在线升级借助开源中国App源码分析如下:

1: checkAppUpdate 检查是或需要升级

// 网络连接判断         if (appContext.isNetworkConnected()) {             // 检查新版本             if (appContext.isCheckUp()) {                    UpdateManager.getUpdateManager().checkAppUpdate(this, false);             }         }

2: UpdateManager类

package lcl.android.core;

import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.text.DecimalFormat;

import lcl.android.R; import lcl.android.api.ApiClient; import android.app.AlertDialog; import android.app.AlertDialog.Builder; import android.app.Dialog; import android.app.ProgressDialog; import android.content.Context; import android.content.DialogInterface; import android.content.DialogInterface.OnCancelListener; import android.content.DialogInterface.OnClickListener; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageManager.NameNotFoundException; import android.net.Uri; import android.os.Environment; import android.os.Handler; import android.os.Message; import android.view.LayoutInflater; import android.view.View; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast;

/**  * 应用程序更新工具包 *  */ public class UpdateManager {     private static final int DOWN_NOSDCARD = 0;     private static final int DOWN_UPDATE = 1;     private static final int DOWN_OVER = 2;     private static final int DIALOG_TYPE_LATEST = 0;     private static final int DIALOG_TYPE_FAIL = 1;

private static UpdateManager updateManager;

private Context mContext;     // 通知对话框     private Dialog noticeDialog;     // 下载对话框     private Dialog downloadDialog;     // '已经是最新' 或者 '无法获取最新版本' 的对话框     private Dialog latestOrFailDialog;     // 进度条     private ProgressBar mProgress;     // 显示下载数值     private TextView mProgressText;     // 查询动画     private ProgressDialog mProDialog;     // 进度值     private int progress;     // 下载线程     private Thread downLoadThread;     // 终止标记     private boolean interceptFlag;     // 提示语     private String updateMsg = "";     // 返回的安装包url     private String apkUrl = "";     // 下载包保存路径     private String savePath = "";     // apk保存完整路径     private String apkFilePath = "";     // 临时下载文件路径     private String tmpFilePath = "";     // 下载文件大小     private String apkFileSize;     // 已下载文件大小     private String tmpFileSize;

private String curVersionName = "";     private int curVersionCode;     private Update mUpdate;

//单利模式

public static UpdateManager getUpdateManager() {         if (updateManager == null) {             updateManager = new UpdateManager();         }         updateManager.interceptFlag = false;         return updateManager;     }

private Handler mHandler = new Handler() {         public void handleMessage(Message msg) {             switch (msg.what) {             case DOWN_UPDATE:                 mProgress.setProgress(progress);                 mProgressText.setText(tmpFileSize + "/" + apkFileSize);                 break;             case DOWN_OVER:                 downloadDialog.dismiss();                 installApk();                 break;             case DOWN_NOSDCARD:                 downloadDialog.dismiss();                 Toast.makeText(mContext, "无法下载安装文件,请检查SD卡是否挂载", 3000).show();                 break;             }         };     };

/**      * 获取当前客户端版本信息      */     private void getCurrentVersion() {         try {             PackageInfo info = mContext.getPackageManager().getPackageInfo(                     mContext.getPackageName(), 0);             curVersionName = info.versionName;             curVersionCode = info.versionCode;         } catch (NameNotFoundException e) {             e.printStackTrace(System.err);         }     }

/**      * 检查App更新      *      * @param context      * @param isShowMsg      *            是否显示提示消息      */     public void checkAppUpdate(Context context, final boolean isShowMsg) {         this.mContext = context;         getCurrentVersion();         if (isShowMsg) {             if (mProDialog == null)                 mProDialog = ProgressDialog.show(mContext, null, "正在检测,请稍后...",                         true, true);             else if (mProDialog.isShowing()                     || (latestOrFailDialog != null && latestOrFailDialog                             .isShowing()))                 return;         }         final Handler handler = new Handler() {             public void handleMessage(Message msg) {                 // 进度条对话框不显示 - 检测结果也不显示                 if (mProDialog != null && !mProDialog.isShowing()) {                     return;                 }                 // 关闭并释放释放进度条对话框                 if (isShowMsg && mProDialog != null) {                     mProDialog.dismiss();                     mProDialog = null;                 }                 // 显示检测结果                 if (msg.what == 1) {                     mUpdate = (Update) msg.obj;                     if (mUpdate != null) {                         if (curVersionCode < mUpdate.getVersionCode()) {                             apkUrl = mUpdate.getDownloadUrl();                             updateMsg = mUpdate.getUpdateLog();                             showNoticeDialog();                         } else if (isShowMsg) {                             showLatestOrFailDialog(DIALOG_TYPE_LATEST);                         }                     }                 } else if (isShowMsg) {                     showLatestOrFailDialog(DIALOG_TYPE_FAIL);                 }             }         };         new Thread() {             public void run() {                 Message msg = new Message();                 try {                     Update update = ApiClient                             .checkVersion((AppContext) mContext                                     .getApplicationContext());                     msg.what = 1;                     msg.obj = update;                 } catch (Exception e) {                     e.printStackTrace();                 }                 handler.sendMessage(msg);             }         }.start();     }

/**      * 显示版本更新通知对话框      */     private void showNoticeDialog() {         AlertDialog.Builder builder = new Builder(mContext);         builder.setTitle("软件版本更新");         builder.setMessage(updateMsg);         builder.setPositiveButton("立即更新", new OnClickListener() {             @Override             public void onClick(DialogInterface dialog, int which) {                 dialog.dismiss();                 showDownloadDialog();             }         });         builder.setNegativeButton("以后再说", new OnClickListener() {             @Override             public void onClick(DialogInterface dialog, int which) {                 dialog.dismiss();             }         });         noticeDialog = builder.create();         noticeDialog.show();     }

/**      * 显示下载对话框      */     private void showDownloadDialog() {         AlertDialog.Builder builder = new Builder(mContext);         builder.setTitle("正在下载新版本");

final LayoutInflater inflater = LayoutInflater.from(mContext);         View v = inflater.inflate(R.layout.update_progress, null);         mProgress = (ProgressBar) v.findViewById(R.id.update_progress);         mProgressText = (TextView) v.findViewById(R.id.update_progress_text);

builder.setView(v);         builder.setNegativeButton("取消", new OnClickListener() {             @Override             public void onClick(DialogInterface dialog, int which) {                 dialog.dismiss();                 interceptFlag = true;             }         });         builder.setOnCancelListener(new OnCancelListener() {             @Override             public void onCancel(DialogInterface dialog) {                 dialog.dismiss();                 interceptFlag = true;             }         });         downloadDialog = builder.create();         downloadDialog.setCanceledOnTouchOutside(false);         downloadDialog.show();

downloadApk();     }

/**      * 显示'已经是最新'或者'无法获取版本信息'对话框      */     private void showLatestOrFailDialog(int dialogType) {         if (latestOrFailDialog != null) {             // 关闭并释放之前的对话框             latestOrFailDialog.dismiss();             latestOrFailDialog = null;         }         AlertDialog.Builder builder = new Builder(mContext);         builder.setTitle("系统提示");         if (dialogType == DIALOG_TYPE_LATEST) {             builder.setMessage("您当前已经是最新版本");         } else if (dialogType == DIALOG_TYPE_FAIL) {             builder.setMessage("无法获取版本更新信息");         }         builder.setPositiveButton("确定", null);         latestOrFailDialog = builder.create();         latestOrFailDialog.show();     }

private Runnable mdownApkRunnable = new Runnable() {         @Override         public void run() {             try {                 String apkName = "OSChinaApp_" + mUpdate.getVersionName()                         + ".apk";                 String tmpApk = "OSChinaApp_" + mUpdate.getVersionName()                         + ".tmp";                 // 判断是否挂载了SD卡                 String storageState = Environment.getExternalStorageState();                 if (storageState.equals(Environment.MEDIA_MOUNTED)) {                     savePath = Environment.getExternalStorageDirectory()                             .getAbsolutePath() + "/OSChina/Update/";                     File file = new File(savePath);                     if (!file.exists()) {                         file.mkdirs();                     }                     apkFilePath = savePath + apkName;                     tmpFilePath = savePath + tmpApk;                 }

// 没有挂载SD卡,无法下载文件                 if (apkFilePath == null || apkFilePath == "") {                     mHandler.sendEmptyMessage(DOWN_NOSDCARD);                     return;                 }

File ApkFile = new File(apkFilePath);

// 是否已下载更新文件                 if (ApkFile.exists()) {                     downloadDialog.dismiss();                     installApk();                     return;                 }

// 输出临时下载文件                 File tmpFile = new File(tmpFilePath);                 FileOutputStream fos = new FileOutputStream(tmpFile);

URL url = new URL(apkUrl);                 HttpURLConnection conn = (HttpURLConnection) url                         .openConnection();                 conn.connect();                 int length = conn.getContentLength();                 InputStream is = conn.getInputStream();

// 显示文件大小格式:2个小数点显示                 DecimalFormat df = new DecimalFormat("0.00");                 // 进度条下面显示的总文件大小                 apkFileSize = df.format((float) length / 1024 / 1024) + "MB";

int count = 0;                 byte buf[] = new byte[1024];

do {                     int numread = is.read(buf);                     count += numread;                     // 进度条下面显示的当前下载文件大小                     tmpFileSize = df.format((float) count / 1024 / 1024) + "MB";                     // 当前进度值                     progress = (int) (((float) count / length) * 100);                     // 更新进度                     mHandler.sendEmptyMessage(DOWN_UPDATE);                     if (numread <= 0) {                         // 下载完成 - 将临时下载文件转成APK文件                         if (tmpFile.renameTo(ApkFile)) {                             // 通知安装                             mHandler.sendEmptyMessage(DOWN_OVER);                         }                         break;                     }                     fos.write(buf, 0, numread);                 } while (!interceptFlag);// 点击取消就停止下载

fos.close();                 is.close();             } catch (MalformedURLException e) {                 e.printStackTrace();             } catch (IOException e) {                 e.printStackTrace();             }         }     };

/**      * 下载apk      *      * @param url      */     private void downloadApk() {         downLoadThread = new Thread(mdownApkRunnable);         downLoadThread.start();     }

/**      * 安装apk      *      * @param url      */     private void installApk() {         File apkfile = new File(apkFilePath);         if (!apkfile.exists()) {             return;         }         Intent i = new Intent(Intent.ACTION_VIEW);         i.setDataAndType(Uri.parse("file://" + apkfile.toString()),                 "application/vnd.android.package-archive");         mContext.startActivity(i);     } }

3:应用程序更新实体类

package lcl.android.core;

import java.io.IOException; import java.io.InputStream; import java.io.Serializable;

import lcl.android.utility.StringUtils;

import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException;

import android.util.Xml;

/**  * 应用程序更新实体类 *  * @author liux (http://my.oschina.net/liux)  * @version 1.0  * @created 2012-3-21  */ public class Update implements Serializable {

private static final long serialVersionUID = -1356876892850891288L;     public final static String UTF8 = "UTF-8";     public final static String NODE_ROOT = "oschina";

private int versionCode;     private String versionName;     private String downloadUrl;     private String updateLog;

public int getVersionCode() {         return versionCode;     }

public void setVersionCode(int versionCode) {         this.versionCode = versionCode;     }

public String getVersionName() {         return versionName;     }

public void setVersionName(String versionName) {         this.versionName = versionName;     }

public String getDownloadUrl() {         return downloadUrl;     }

public void setDownloadUrl(String downloadUrl) {         this.downloadUrl = downloadUrl;     }

public String getUpdateLog() {         return updateLog;     }

public void setUpdateLog(String updateLog) {         this.updateLog = updateLog;     }

public static Update parse(InputStream inputStream) throws IOException,             Exception {         Update update = null;         // 获得XmlPullParser解析器         XmlPullParser xmlParser = Xml.newPullParser();         try {             xmlParser.setInput(inputStream, UTF8);             // 获得解析到的事件类别,这里有开始文档,结束文档,开始标签,结束标签,文本等等事件。             int evtType = xmlParser.getEventType();             // 一直循环,直到文档结束             while (evtType != XmlPullParser.END_DOCUMENT) {                 String tag = xmlParser.getName();                 switch (evtType) {                 case XmlPullParser.START_TAG:                     // 通知信息                     if (tag.equalsIgnoreCase("android")) {                         update = new Update();                     } else if (update != null) {                         if (tag.equalsIgnoreCase("versionCode")) {                             update.setVersionCode(StringUtils.toInt(                                     xmlParser.nextText(), 0));                         } else if (tag.equalsIgnoreCase("versionName")) {                             update.setVersionName(xmlParser.nextText());                         } else if (tag.equalsIgnoreCase("downloadUrl")) {                             update.setDownloadUrl(xmlParser.nextText());                         } else if (tag.equalsIgnoreCase("updateLog")) {                             update.setUpdateLog(xmlParser.nextText());                         }                     }                     break;                 case XmlPullParser.END_TAG:                     break;                 }                 // 如果xml没有结束,则导航到下一个节点                 evtType = xmlParser.next();             }         } catch (XmlPullParserException e) {

} finally {             inputStream.close();         }         return update;     } }

4:获取网络版本信息

/**  * API客户端接口:用于访问网络数据 *  * @author liux (http://my.oschina.net/liux)  * @version 1.0  * @created 2012-3-21  */ public class ApiClient {     /**      * 检查版本更新      *      * @param url      * @return      */     public static Update checkVersion(AppContext appContext) throws Exception {         try {             return Update.parse(HtmlRegexpUtil                     .GetInputStreamByUrl(“http://files.cnblogs.com/luomingui/MobileAppVersion.xml”));         } catch (Exception e) {             throw e;         }     } } 5:发布到网络

image

android 在线升级借助开源中国App源码的更多相关文章

  1. Android 轻量级ORM数据库开源框架ActiveAndroid 源码分析

    ActiveAndroid 项目地址在https://github.com/pardom/ActiveAndroid 关于他的详细介绍和使用步骤 可以看下面两篇文章: https://github.c ...

  2. Android之开源中国客户端源码分析(一)

    程序启动第一个界面类: net.oschina.app.AppStart功能描述:一张图片代码细节描述:一个透明度的动画效果,效果动画完成后自动启动新的Activity(Main) 基本BaseAct ...

  3. Android之开源中国客户端源码分析(二)

    1. 加载动画圈实现 <ProgressBar android:id="@+id/main_head_progress" style="@style/loading ...

  4. android动画源码合集、动态主题框架、社交app源码等

    Android精选源码 仿MIUI果冻视图-BouncingJellyView   一个快速易用的动态主题框架   android动画效果集合源码   android使用Kotlin开发的Dribbb ...

  5. 优化Recorder H5录音:可边录边转码上传服务器,支持微信提供Android IOS Hybrid App源码

    Recorder H5 GitHub开源库随着支持功能的增多,音频转码处理效率渐渐的跟不上需求了,近期抽时间对音频转码部分进行了升级优化,以支持更多实用的功能. 另外IOS的Hybrid App也完成 ...

  6. 140款Android开源优秀项目源码

    BeautifulRefreshLayout-漂亮的美食下拉刷新 https://github.com/android-cjj/BeautifulRefreshLayout/tree/Beautifu ...

  7. 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新

    [原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...

  8. 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新

    上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...

  9. 基于Android开发的天气预报app(源码下载)

    原文:基于Android开发的天气预报app(源码下载) 基于AndroidStudio环境开发的天气app -系统总体介绍:本天气app使用AndroidStudio这个IDE工具在Windows1 ...

随机推荐

  1. Nginx系列3之Nginx+tomcat

    preface 公司部分应用跑得的tomcat,众所周知,tcomat高并发性能很弱,所以在处理静态请求的时候,我们就把他抛给Nginx处理,而Tomcat专门处理动态请求.所以在这里说说Nginx+ ...

  2. e_msg_c_as_register_req-注册存储过程

    TOP:BEGIN #Routine body goes here... IF EXISTS ( SELECT * FROM `global_account` WHERE `plantform_id` ...

  3. 脚本放在 <body> 元素的底部

    建议把脚本放在 <body> 元素的底部. 这会提高网页加载速度,因为 HTML 加载不受制于脚本加载.

  4. 安装vim的ycm

    环境centos 6.7 vim 7.3 安装vundle Vundle(Vim bundle)是一个Vim的插件管理器.它是把git操作整合进去,用户需要做的只是去GitHub上找到自己想要的插件的 ...

  5. Windows Platform Predefined Macros

    https://msdn.microsoft.com/en-us/library/b0084kay.aspx

  6. ecshop去掉“云服务中心”或者是“模板堂知识库”

    ECSHOP开发中心(www.68ecshop.com)教程介绍一下如何去除后台云服务中心菜单: 打开admin/templates/menu.htm,把415行的 document.getEleme ...

  7. Visual Studio无法查找或打开 PDB 文件解决办法

    Visual Studio无法查找或打开 PDB 文件解决办法 用VS调试程序时,有时会在VS底部的“输出”框中提示“无法查找或打开 PDB 文件”.这该怎么解决呢? 下面,我们以VS2013为例,来 ...

  8. jsp简单标签开发(一)

    孤傲苍狼 @Override22 public void doTag() throws JspException, IOException {23 //得到代表jsp标签体的JspFragment24 ...

  9. Memcached【Magent+Memcached】集群

    Memcached介绍  事件处理libevent是个程序库,它将Linux的epoll.BSD类操作系统的kqueue等事件处理功能封装成统一的接口.即使对服务器的连接数增加,也能发挥O(1)的性能 ...

  10. jQuery监听键盘事件及相关操作使用教程

    一.首先需要知道的是: 1.keydown() keydown事件会在键盘按下时触发. 2.keyup() keyup事件会在按键释放时触发,也就是你按下键盘起来后的事件 3.keypress() k ...