zoukankan      html  css  js  c++  java
  • android 在线升级借助开源中国App源码

    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

  • 相关阅读:
    SQL Server 2005中 with as 使用介绍
    论信息系统项目的整体管理
    自定义控件的使用以及与用户控件的区别
    Sql Server2005 TransactSQL 新兵器学习总结之DDL触发器
    我的大学系分之路
    C#序列化与反序列化(Serializable and Deserialize)
    父子节点树形数据输出
    自定义枚举类型注释属性,并在程序中获取
    SSAS没有注册类别 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)) 解决办法
    对ASP.NET网站的服务器端压缩
  • 原文地址:https://www.cnblogs.com/luomingui/p/3949429.html
Copyright © 2011-2022 走看看