今天做了自动更新功能,现在把趟过的坑介绍一下:
自动更新步骤:获取当前版本号,然后去和服务器版本号对比,如果不一样就说明有升级,提示用户升级,用户点击确定后自动后台下载新APK并且安装。听起来是不是很简单?做起来也很简单,只是有一些坑而已。
我是在LoginActivity()中写的自动更新功能,在用户准备登陆时判断一下是否有新版本,如果有的话就自动更新(我做的是强制性更新),没有不做处理,当然可以有更人性化的处理,给用户选择是否升级的权利
private int versionCode;//当前版本号
private String version_info;//版本信息
private Context mContext;
private int version_netcode;//服务端当前版本号
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_login); initView(); mContext = this; Log.e("tag", "11111111111111111111111"); // 获取当前版本号 try { getVersonCode();// } catch (Exception e) { e.printStackTrace(); } //获取服务端的版本号 getNetVersonCode();// } /** * 获取当前程序版本号// * * @return * @throws Exception */ private int getVersonCode() throws Exception { PackageManager packageManager = getPackageManager(); //getPackageName()是你当前类的包名,0代表是获取版本信息 PackageInfo packageInfo = packageManager.getPackageInfo(getPackageName(), 0); versionCode = packageInfo.versionCode;
Log.e(“TTTTTTT”, versionCode + “”);
return versionCode;
}
/**
* 获取服务端的版本号
*/
private void getNetVersonCode() {
String url = "http://crm.taxchina.com/wcm/inside/gkk/interface/AndroidUpdate.aspx ";//各自公司后台提供,里面存储APK基本信息
OkHttpUtils
.get()
.url(url)
.build()
.execute(new StringCallback() {
@Override
public void onError(Call call, Exception e) {
}
@Override
public void onResponse(String response) {
//请求网络成功解析数据
Log.e("888888888888888888888", "联网成功");
processData(response);
}
});
}
private void processData(String response) {
VersonModel versonModel = new Gson().fromJson(response, VersonModel.class);
version_netcode = Integer.parseInt(String.valueOf(versonModel.getVersion_code()));
version_info = versonModel.getVersion_info();
Log.e("tttttt", version_netcode + "");
//比较两个版本是否一致
CheckVersionTask();
}
private void CheckVersionTask() {
if (versionCode == version_netcode) {
Log.e("tagggggg", "版本号相同无需升级");
} else {
//提示用户升级
Message msg = Message.obtain();
msg.what = UPDATA_CLIENT;
handler.sendMessage(msg);
}
}
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case UPDATA_CLIENT:
//提示用户升级的对话框
showUpdataDialog();
break;
}
}
};
private void showUpdataDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("版本升级");
builder.setMessage(version_info);
//用户点击确定按钮下载新的apk
builder.setPositiveButton("确定", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.e("tag000000000", "下载apk,更新");
downLoadApk();
}
});
builder.show();
}
/**
* 从服务器中下载apk
*/
private void downLoadApk() {
final String path = "http://crm.taxchina.com/wcm/resource/UploadApk/taxSign.apk";//下载APK的路径也是公司后台服务端给接口
final ProgressDialog pd;
pd = new ProgressDialog(this);
pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
pd.setMessage("正在下载更新");
pd.show();
new Thread() {
@Override
public void run() {
super.run();
//下载安装apk
try {
Utils.getFileFromServer(mContext,path,pd);*强调内容*重点内容**
} catch (Exception e) {
e.printStackTrace();
}
}
}.start();
}
//下面放上utils工具包代码,也是核心代码
/**
* 从服务器下载apk:
*
* @param context
* @param path
* @param pd
* @throws Exception
*/
public static void getFileFromServer(Context context, String path,
ProgressDialog pd) throws Exception {
String downloadPath = Environment.getExternalStorageDirectory()
.getPath() + "/download_cache";
File file = new File(downloadPath);
if (!file.exists())
file.mkdir();
URL url = new URL(path);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(5 * 1000);
urlConnection.setRequestMethod("GET");
urlConnection.connect();
try {
if (urlConnection.getResponseCode() == 200) {
InputStream is = urlConnection.getInputStream();
// 开始下载apk文件
FileOutputStream fos = new FileOutputStream(downloadPath
+ "/action.apk");
BufferedInputStream bis = new BufferedInputStream(is);
byte[] buffer = new byte[5120];
int total = 0;
int count = 0;
while ((count = bis.read(buffer)) != -1) {
fos.write(buffer, 0, count);
total += count;
// 获取当前下载量
pd.setProgress(total);
}
fos.close();
bis.close();
is.close();
urlConnection.disconnect();
pd.dismiss();
// 安装 apk 文件
installApk(context, downloadPath + "/action.apk");
}
} catch (Exception e) {
pd.dismiss();
}
}
/**
* 安装apk
*
* @param context
* @param filename
*/
protected static void installApk(Context context, String filename) {
File file = new File(filename);
Intent intent = new Intent();
intent.setAction(Intent.ACTION_VIEW); // 浏览网页的Action(动作)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
String type = "application/vnd.android.package-archive";
intent.setDataAndType(Uri.fromFile(file), type); // 设置数据类型
context.startActivity(intent);
}
好了,到此为止自动更新功能就添加完成了,就会自动下载安装了。
此处有两个坑:1、 String type = “application/vnd.android.package-archive”; android必须都是小写
2、 intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);加上此句才会有安装运行新应用窗口提示
最后一个大坑是用真机测试的时候,却提示“未安装应用程序”。
说明:这里的要升级的文件已经正常下载到手机上了,权限也都加好了。
产生这种现象的原因就是:手机上已经安装好的apk和正在安装的apk包名都是一样的,可是签名不一样,所以它会提示你安装不成功。在服务器上的升级包是做好签名的,而我在测试的时候是用真机测试的,也就是说电脑上的android程序直接运行在了手机上,而没有经过打包签名,最后导致的结果就是文件正常下载到手机上,可是安装不成功。
其实解决方法也很简单了:把签名的安装包安装到手机上,再测试升级的功能,这样就没有问题了。
这是我的一些个人理解,由于水平有限,如果有问题我会及时改正,欢迎大家指正错误。