由于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.  
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.  
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.    


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.      
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.    
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安装体验一下版本升级。









alert.jpg (428.74 KB, 下载次数: 0)