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

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

上一篇:图解集合6:LinkedHashMap


下一篇:Intellij IDEA 使用jrebel运行spring-boot并实现自动编译进行热部署