Android App 自动更新版本
2016-07-16 00:00
459 查看
摘要: 写App以来,一直有统一的版本命名规则,之所以这样做的目的是为了App自动更新。今天看了别人怎么实现的博客,然后自己总结了一些,能力有限,不喜勿喷哦,希望大家看见有错的地方还请多多指教。kensoon918@163.com only for feedback.
#概述
其实Android App自动更新这个功能是很重要的,原因就在于Android 是开源的,所以国内出现了很多Android 的应用市场,所以如果你的一个App在一个AppStore里面上线了,然后你又有一个新的版本出来了的话,如果不写自动更新的话就得一个应用市场一个应用市场的发布,是不是感觉心很累,所以自动更新版本,还是很重要的。
#服务器数据
当然为了能够让你的App知道是否该更新了,所以得有一个固定的服务器,以便于你得到更新的数据。我设计的包括以下数据(可能有不足的地方,具体情况因人而异):
1.最新版本名称
2.最新版本号
3.更新内容
4.下载地址
为了方便我用的是Json来传这几个数据,像下面这样的:
#Android代码
###1. 首先得写一个判断网络链接的Util类
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
/**
Created by ken on 16-7-15.
<p/>
这个类主要是用来判断网络链接的,是否链接,是否是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;
}
}
}
#概述
其实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.
<p/>
这个类主要是用来判断网络链接的,是否链接,是否是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()); } }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件
- SourceProvider.getJniDirectories