Android App 自动更新版本

简介: 写App以来,一直有统一的版本命名规则,之所以这样做的目的是为了App自动更新。今天看了别人怎么实现的博客,然后自己总结了一些,能力有限,不喜勿喷哦,希望大家看见有错的地方还请多多指教。kensoon918@163.com only for feedback.

概述

其实Android App自动更新这个功能是很重要的,原因就在于Android 是开源的,所以国内出现了很多Android 的应用市场,所以如果你的一个App在一个AppStore里面上线了,然后你又有一个新的版本出来了的话,如果不写自动更新的话就得一个应用市场一个应用市场的发布,是不是感觉心很累,所以自动更新版本,还是很重要的。

服务器数据

当然为了能够让你的App知道是否该更新了,所以得有一个固定的服务器,以便于你得到更新的数据。我设计的包括以下数据(可能有不足的地方,具体情况因人而异):

1.最新版本名称
2.最新版本号
3.更新内容
4.下载地址

为了方便我用的是Json来传这几个数据,像下面这样的:

{"Version_Name":"cybercar1.2.0","Version_Code":"24","Version_Update_Content":"重要更新","Version_Update_Address":"http://www.baidu.com/Apps/cybercar1.2.0.apk"}

Android代码

1. 首先得写一个判断网络链接的Util类

import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**

  • Created by ken on 16-7-15.
  • 这个类主要是用来判断网络链接的,是否链接,是否是wi-fi链接,是否是移动网络链接
    */

public class ConnectivityUtils {

/**
 * 判断是否链接网络
 */
public static boolean isConnected(Context context) {
    try {
        ConnectivityManager connMgr =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
        //返回链接状态
        if (activeInfo != null && activeInfo.isConnected()) {
            return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}
//判断是否是wifi链接
public static boolean isWifiConnected(Context context) {
    try {
        ConnectivityManager connMgr =
                (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo activeInfo = connMgr.getActiveNetworkInfo();
        //返回链接状态
        if (activeInfo != null && activeInfo.isConnected()
                && activeInfo.getType() == ConnectivityManager.TYPE_WIFI) {
           return true;
        } else {
            return false;
        }
    } catch (Exception e) {
        return false;
    }
}

}



###2.然后写一个自动更新的类

>```java
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Handler;
import android.os.Message;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.fat246.cybercar.BuildConfig;
import com.fat246.cybercar.R;
import com.fat246.cybercar.application.MyApplication;
import com.fat246.cybercar.utils.ConnectivityUtils;
import com.fat246.cybercar.utils.PreferencesUtility;
import org.json.JSONObject;
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;
/**
 * Created by ken on 16-7-15.
 * 自动更新App
 */
public class AutoUpdateManager implements DialogInterface.OnClickListener, Runnable {
    //服务器地址
    private static final String AUTO_UPDATE_SERVER_ADDRESS = "http://www.baidu.com/autoupdate";
    //数据key
    private static final String VERSION_NAME = "Version_Name";
    private static final String VERSION_CODE = "Version_Code";
    private static final String VERSION_UPDATE_CONTENT = "Version_Update_Content";
    private static final String VERSION_UPDATE_ADDRESS = "Version_Update_Address";
    //数据 包括 1.版本名称 2.版本号 3.版本更新内容 4.版本地址
    private String Version_Name;
    private int Version_Code;
    private String Version_Upadte_Content;
    private String Version_Update_Address;
    //上下文
    private Context context;
    //接口
    private AfterUpdate afterUpdate;
    //下载进度
    private int mProgress;
    private boolean mInteruptFlag;
    private static final int DOWN_UPDATE = 0;
    private static final int DOWN_OVER = 1;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case DOWN_UPDATE:
                    mProgressDialog.setProgress(mProgress);
                    break;
                case DOWN_OVER:
                    installApk();
                    break;
            }
        }
    };
    private ProgressDialog mProgressDialog;
    public AutoUpdateManager(Context context) {
        this.context = context;
    }
    //开始更新
    public void beginUpdate(AfterUpdate afterUpdate) {
        this.afterUpdate = afterUpdate;
        //判断是否有网络链接
        if (ConnectivityUtils.isConnected(context)) {
            //向服务器拉取数据
            pullUpdateInfo();
        } else {
            afterUpdate.toDoAfterUpdate();
        }
    }
    //拉取服务器的信息
    private void pullUpdateInfo() {
        //用Volley请求服务器最新的版本信息
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(AUTO_UPDATE_SERVER_ADDRESS, null, new Response.Listener<JSONObject>() {
            @Override
            public void onResponse(JSONObject jsonObject) {
                paserJsonData(jsonObject);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError volleyError) {
                volleyError.printStackTrace();
                afterUpdate.toDoAfterUpdate();
            }
        });
        //设置Tag
        jsonObjectRequest.setTag(AUTO_UPDATE_SERVER_ADDRESS);
        //添加到请求队列里面
        MyApplication.getRequestQueue().add(jsonObjectRequest);
    }
    //解析 Json数据
    private void paserJsonData(JSONObject json) {
        try {
            //版本名称
            Version_Name = json.getString(VERSION_NAME);
            //版本号
            Version_Code = json.getInt(VERSION_CODE);
            //版本更新内容
            Version_Upadte_Content = json.getString(VERSION_UPDATE_CONTENT);
            //版本地址
            Version_Update_Address = json.getString(VERSION_UPDATE_ADDRESS);
            //判断是否要提醒用户更新
            if (isNeedUpdate()) {
                //显示提示Dialog
                showUpdateDialog();
            } else {
                afterUpdate.toDoAfterUpdate();
            }
        } catch (Exception e) {
            e.printStackTrace();
            afterUpdate.toDoAfterUpdate();
        }
    }
    //判断是否需要更新
    private boolean isNeedUpdate() {
        try {
            //判断服务器最新的版本号是否大于当前版本号
            if (Version_Code > BuildConfig.VERSION_CODE) {
                //首先得到跳过的版本号
                int jump_code = PreferencesUtility.getInstance(context).getJumpVersionCode();
                //判断跳过的版本号是否大于当前服务器版本号
                if (Version_Code > jump_code) {
                    return true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return false;
    }
    //显示更新提示
    private void showUpdateDialog() {
        try {
            //builder
            AlertDialog.Builder builder = new AlertDialog.Builder(context);
            //设置标题
            builder.setTitle("版本更新");
            //更新内容
            builder.setMessage(Version_Upadte_Content);
            //设置图标
            builder.setIcon(R.mipmap.ic_launcher);
            //设置以后更新
            builder.setPositiveButton("以后更新", this);
            //设置立即更新
            builder.setNegativeButton("立即更新", this);
            //设置跳过当前版本
            builder.setNeutralButton("跳过版本", this);
            //创建Dialog 并展示
            AlertDialog dialog = builder.create();
            //设置点击外面不消失
            dialog.setCanceledOnTouchOutside(false);
            dialog.show();
        } catch (Exception e) {
            e.printStackTrace();
            afterUpdate.toDoAfterUpdate();
        }
    }
    //当更新完成后要做的事情
    public interface AfterUpdate {
        void toDoAfterUpdate();
    }
    //Dialog的点击事件
    @Override
    public void onClick(DialogInterface dialog, int which) {
        switch (which) {
            case AlertDialog.BUTTON_POSITIVE:
                afterUpdate.toDoAfterUpdate();
                break;
            case AlertDialog.BUTTON_NEGATIVE:
                toUpdateUtils();
                break;
            case AlertDialog.BUTTON_NEUTRAL:
                //设置跳过版本               PreferencesUtility.getInstance(context).setJumpVersionCode(Version_Code);
                afterUpdate.toDoAfterUpdate();
                break;
        }
    }
    //点击立即更新按钮
    public void toUpdateUtils() {
        //判断是否是wifi链接
        if (ConnectivityUtils.isWifiConnected(context)) {
            toDownlaodApk();
        } else {
            //友情提示用户
            showOurFriendly();
        }
    }
    //友情提示用户
    private void showOurFriendly() {
        AlertDialog.Builder builder = new AlertDialog.Builder(context);
        builder.setTitle("友情提示");
        builder.setMessage("亲,你用的不是Wifi,是否继续下载?");
        builder.setPositiveButton("是", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                toDownlaodApk();
                afterUpdate.toDoAfterUpdate();
            }
        });
        builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                afterUpdate.toDoAfterUpdate();
            }
        });
        AlertDialog alertDialog = builder.create();
        alertDialog.setCanceledOnTouchOutside(false);
        alertDialog.show();
    }
    //去下载
    private void toDownlaodApk() {
        Thread update = new Thread(this);
        showDownlaodProgressBar();
        update.start();
    }
    //显示下载ProgressBar
    private void showDownlaodProgressBar() {
        mProgressDialog = new ProgressDialog(context);
        mProgressDialog.setMessage("正在下载...");
        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mProgressDialog.setButton("取消下载", new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                mProgressDialog.dismiss();
                mInteruptFlag = true;
                afterUpdate.toDoAfterUpdate();
            }
        });
        mProgressDialog.setCanceledOnTouchOutside(false);
        mProgressDialog.setProgress(0);
        mProgressDialog.setMax(100);
        mProgressDialog.show();
    }
    @Override
    public void run() {
        //判空
        if (Version_Update_Address == null) {
            return;
        }
        FileOutputStream fos = null;
        InputStream is = null;
        try {
            URL url = new URL(Version_Update_Address);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            int length = conn.getContentLength();
            is = conn.getInputStream();
            //保存到的文件夹
            File file = new File(MyApplication.SAVE_PATH + "/Apk/");
            if (!file.exists()) {
                file.mkdir();
            }
            File apkFile = new File(MyApplication.SAVE_PATH + "/Apk/" + Version_Name + ".apk");
            fos = new FileOutputStream(apkFile);
            int count = 0;
            byte buf[] = new byte[1024];
            do {
                int len = is.read(buf);
                if (len != -1) {
                    count += len;
                    mProgress = (int) (((float) count / length) * 100);
                    mHandler.sendEmptyMessage(DOWN_UPDATE);
                } else {
                    mHandler.sendEmptyMessage(DOWN_OVER);
                    break;
                }
                fos.write(buf, 0, len);
            } while (!mInteruptFlag);
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            mProgressDialog.dismiss();
            if (null != is) {
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (null != fos) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    //安装下载好的版本
    private void installApk() {
        File apkFile = new File(MyApplication.SAVE_PATH + "/Apk/" + Version_Name + ".apk");
        if (!apkFile.exists()) {
            return;
        }
        //开启安装界面
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setDataAndType(Uri.parse("file://" + apkFile.toString()), "application/vnd.android.package-archive");
        context.startActivity(i);
        //如果不杀进程不会跳到安装后打开的页面
        android.os.Process.killProcess(android.os.Process.myPid());
    }
}
目录
相关文章
|
3月前
|
Android开发 开发者 iOS开发
APP开发后如何上架,上架Android应用市场前要准备什么
移动应用程序(APP)的开发已经成为现代企业和开发者的常见实践。然而,开发一个成功的APP只是第一步,将其上架到应用商店让用户下载和使用是实现其潜力的关键一步。
|
3月前
|
数据安全/隐私保护 iOS开发 开发者
hbuilderx打包应用上传到app store构建版本的教程
hbuilderx打包应用上传到app store构建版本的教程
31 0
|
3月前
|
存储 算法 Android开发
AVB校验微观版本:android avb(Android Verified Boot)验证
AVB校验微观版本:android avb(Android Verified Boot)验证
210 0
|
27天前
|
运维 监控 Java
应用研发平台EMAS产品常见问题之安卓构建版本失败如何解决
应用研发平台EMAS(Enterprise Mobile Application Service)是阿里云提供的一个全栈移动应用开发平台,集成了应用开发、测试、部署、监控和运营服务;本合集旨在总结EMAS产品在应用开发和运维过程中的常见问题及解决方案,助力开发者和企业高效解决技术难题,加速移动应用的上线和稳定运行。
|
1月前
|
监控 安全 Android开发
安卓发展历程和主要版本的简要介绍
安卓发展历程和主要版本的简要介绍
30 1
|
1月前
|
前端开发
最新版本create-react-app 如何使用css-module
最新版本create-react-app 如何使用css-module
15 0
|
1月前
|
设计模式 测试技术 数据库
基于Android的食堂点餐APP的设计与实现(论文+源码)_kaic
基于Android的食堂点餐APP的设计与实现(论文+源码)_kaic
|
2月前
|
安全 Java 数据挖掘
当 App 有了系统权限,真的可以为所欲为? Android Performance Systrace
当 App 有了系统权限,真的可以为所欲为? Android Performance Systrace 转载自: https://androidperformance.com/2023/05/14/bad-android-app-with-system-permissions/#/0-Dex-%E6%96%87%E4%BB%B6%E4%BF%A1%E6%81%AF
30 0
|
2月前
|
移动开发 开发工具 数据安全/隐私保护
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?
iOS APP 版本更新升级教程:如何打包上架新的 APP 版本?