由于Android项目开源所致,市面上出现了N多安卓软件市场。为了让我们开发的软件有更多的用户使用,我们需要向N多市场发布,软件升级后,我们也必须到安卓市场上进行更新,给我们增加了工作量。因此我们有必要给我们的Android应用增加自动更新的功能。而用户一键就可以完成软件的升级更新。得益于Android系统的软件包管理和安装机制。
实现思路:
从服务器获取版本号(版本号存在于xml文件中)并与当前检测到的版本进行匹配,如果不匹配,提示用户进行升级,如果匹配则进入程序主界面。
一.服务器xml自定义信息
1. <?xml version="1.0" encoding="UTF-8"?>
2. <update>
3. <version>1.0.2</version>
4. <versionCode>2</versionCode>
5. <updateTime>20120515</updateTime>
6. <apkName>sems_02_20120425.apk</apkName>
7. <downloadURL>http://192.168.2.57:95/updater/sems.apk</downloadURL>
8. <displayMessage>新版本发布,赶紧下载吧 ## 1.地图模式 ## 2.列表模式## 3.自动更新</displayMessage>
9. </update>
复制代码
version标签为当前版本号
versionCode用来对比是否需要升级
updateTime用来显示更新的时间
displayMessage 版本更新的信息
二.客户端定时检查(或自定义触发检查)是否需要更新
1. /**
2. * 方法描述 检查是否有更新的版本发布
3. * @author hechuan
4. * @createTime 2012-5-3
5. */
6. public void checkUpdateInfo(int type) {
7. // TODO check是否需要更新
8. PreferenceManager.getDefaultSharedPreferences(mContext);
9. connect();//与服务端交互获取版本信息
10. try {
11. pi = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), PackageManager.GET_CONFIGURATIONS);//获取当前包信息
12. } catch (NameNotFoundException e) {
13. e.printStackTrace();
14. }
15. versionCode = pi.versionCode;//获取当前的版本号
16. if(versionCode>=info.getVersionCode()){
17. if(type == ConstanseUtils.UPDATE_TYPE_SELF){
18. DialogUtil.showNoNeedUpdate(mContext);
19. }
20. return;
21. }else{
22. showNoticeDialog();//弹出提示更新框
23. }
24. }
复制代码
-
1. /**
2. * 方法描述 与服务端交互,获取更新版本的信息
3. * @author hechuan
4. * @createTime 2012-5-3
5. */
6. private void connect() {
7. URL url = null;
8. try {
9. // 构造一个URL对象
10. url = new URL(ConstanseUtils.COMMON_URL_START + PreferencesUtils.getServer()
11. + ConstanseUtils.UPDATE_URL_END);
12. } catch (MalformedURLException e) {
13. Log.e("debug", "MalformedURLException");
14. }
15. if (url != null) {
16. try {
17. // 使用HttpURLConnection打开连接
18. HttpURLConnection urlConn = (HttpURLConnection) url
19. .openConnection();
20. // 得到读取的内容(流)
21. info = XMLParserUtils.getUpdateInfo(urlConn.getInputStream());
22. urlConn.disconnect();
23. // 设置显示取得的内容
24. } catch (IOException e) {
25. Log.e("debug", "IOException");
26. } catch (Exception e) {
27. e.printStackTrace();
28. }
29. } else {
30. Log.e("DEBUG_TAG", "Url NULL");
31. }
32. }
复制代码
xml解析代码片段
-
1. case XmlPullParser.START_TAG:
2. if ("version".equals(parser.getName())) {
3. info.setVersion(parser.nextText());
4. } else if ("updateTime".equals(parser.getName())) {
5. info.setUpdateTime(parser.nextText());
6. } else if ("downloadURL".equals(parser.getName())) {
7. info.setDownloadURL(parser.nextText());
8. } else if ("displayMessage".equals(parser.getName())) {
9. info.setDisplayMessage(parseTxtFormat(parser.nextText()));
10. } else if ("apkName".equals(parser.getName())) {
11. info.setApkName(parser.nextText());
12. } else if ("versionCode".equals(parser.getName())) {
13. info.setVersionCode(Integer.parseInt(parser.nextText()));
14. }
复制代码
三.如果检查到有新的版本需要更新,弹出下载框,提示用户下载。点击下载后,界面动态显示下载进度
-
1. /**
2. * 方法描述 弹出下载apk框
3. * @author hechuan
4. * @createTime 2012-5-3
5. */
6. private void showDownloadDialog() {
7. final Resources r = mContext.getResources();
8. AlertDialog.Builder builder = new Builder(mContext);
9. builder.setTitle(r.getString(R.string.update_downapk_title));
10. 11. final LayoutInflater inflater = LayoutInflater.from(mContext);
12. View v = inflater.inflate(R.layout.update_progress, null);
13. mProgress = (ProgressBar) v.findViewById(R.id.pb_update_progress);
14. 15. builder.setView(v);
16. builder.setNegativeButton(r.getString(R.string.common_cancle), new OnClickListener() {
17. @Override
18. public void onClick(DialogInterface dialog, int which) {
19. dialog.dismiss();
20. interceptFlag = true;//点击取消后,停止下载
21. }
22. });
23. downloadDialog = builder.create();
24. downloadDialog.show();
25. 26. downloadApk();//下载apk
27. }
复制代码
动态更新进度
1. private Runnable mdownApkRunnable = new Runnable() {
2. @Override
3. public void run() {
4. try {
5. if (!android.os.Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)){
6. DialogUtil.showSDCARDNotSupport(mContext);
7. return;
8. }else{
9. URL url = new URL(ConstanseUtils.COMMON_URL_START + PreferencesUtils.getServer()
10. + ConstanseUtils.APK_URL_END);
11. HttpURLConnection conn = (HttpURLConnection) url
12. .openConnection();
13. conn.connect();
14. int length = conn.getContentLength();
15. InputStream is = conn.getInputStream();
16. File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ ConstanseUtils.UPDATE_SAVE_PATH);
17. if (!file.exists()) {
18. file.mkdir();
19. }
20. String apkFile = Environment.getExternalStorageDirectory().getAbsolutePath()+ ConstanseUtils.UPDATE_SAVE_PATH+info.getApkName();
21. File ApkFile = new File(apkFile);
22. FileOutputStream fos = new FileOutputStream(ApkFile);
23. 24. int count = 0;
25. byte buf[] = new byte[1024];
26. 27. do {
28. int numread = is.read(buf);
29. count += numread;
30. progress = (int) (((float) count / length) * 100);
31. // 更新进度
32. mHandler.sendEmptyMessage(DOWN_UPDATE);
33. if (numread <= 0) {
34. // 下载完成通知安装
35. mHandler.sendEmptyMessage(DOWN_OVER);
36. break;
37. }
38. fos.write(buf, 0, numread);
39. } while (!interceptFlag);// 点击取消就停止下载.
40. 41. fos.close();
42. is.close();
43. }
44. } catch (MalformedURLException e) {
45. e.printStackTrace();
46. } catch (IOException e) {
47. e.printStackTrace();
48. }
49. }
50. };
复制代码
四.接收到下载完成的信息后,卸载旧版本,安装新版本
利用android 里面的handle来处理接收消息
-
1. private Handler mHandler = new Handler() {
2. public void handleMessage(Message msg) {
3. switch (msg.what) {
4. case DOWN_UPDATE:
5. mProgress.setProgress(progress);//更新进度情况
6. break;
7. case DOWN_OVER:
8. mProgress.setVisibility(View.INVISIBLE);
9. installApk();//安装apk文件
10. break;
11. default:
12. break;
13. }
14. };
15. };
复制代码
安装apk
-
1.
2. /**
3. * 方法描述 安装下载的apk文件
4. * @author hechuan
5. * @createTime 2012-5-3
6. */
7. private void installApk() {
8. File apkfile = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+ ConstanseUtils.UPDATE_SAVE_PATH+info.getApkName());//获取当前sdcard存储路径
9. if (!apkfile.exists()) {
10. return;
11. }
12. Intent i = new Intent(Intent.ACTION_VIEW);
13. i.setDataAndType(Uri.fromFile(new File(apkfile.getAbsolutePath())),
14. "application/vnd.android.package-archive"); //安装 如果签名不一致,可能出现程序未安装提示
15. mContext.startActivity(i);
16. }
复制代码
附:我们平时在anroid应用商店里面更新升级版本后,很多apk会提示程序未安装,导致升级失败,只是下载下来了最新的apk。
主要原因是apk签名不一致造成的。出现这种情况,直接在sdcard(下载保存地址)安装下载好的apk包即可。
路灯android版本最近即将推出,届时大家可以下载apk安装体验一下版本升级。
|