新闻动态   News
联系我们   Contact
你的位置:首页 > 新闻动态

AppCan移动应用_客户端升级方案概述

2014-12-17

当开发者开发完一个应用,打成安装包发布出去后,如果有改动就涉及到软件的更新。Appcan平台的软件升级交由开发者主导,平台只提供相关的接口调用。针对Android,可以通过检查更新接口,获取apk更新包的url,再通过uexDownloaderMgr下载apk包,通过uexWidget.installApp安装;而针对ios,如果是appstore上的软件,可以通过检查更新接口,获取appstore的更新url,再通过uexWidget.loadApp方法加载浏览器,从而跳转到appstore。

客户端与服务器端通讯示意图:

app can 客户端更新
app can 客户端更新
 











 实现分析:

客户端方面

需要在config.xml中加入<updateurl>升级接口</updateurl>节点。实例如下:<updateurl>http://discuz.3g2win.com/source/plugin/zywx/rpc/widget_upgrade.php</updateurl>
appcan平台方面

当应用启动后,调用uexWidget.checkUpdate()升级接口。平台在升级接口中会追加两个参数:ver 和 platform
ver : 版本号
platform:0是IOS, 1是Android, 2是IDE(无升级机制),3是symbian(目前暂不支持升级)
服务器处理

总体思想:
灵活控制客户端升级,避免连续打包给用户带来的不良体验。应用所有者可以手动更新指定的xml文件,将随时提醒已经安装的应用进行升级。

实现方式:
服务器通过升级接口,接收平台传过来的ver和platform。升级接口将当前版本号和最新版本进行比较,如果没有新版本返回空,如果有新版本则返回平台对应的xml格式数据。

有新版本返回:
<?xml version="1.0" encoding="utf-8" ?><results><updateFileName>discuz</updateFileName><updateFileUrl>http://www.chunai.us/source/plugin/zywx/chunai_iPhone_0.4.ipa</updateFileUrl><fileSize>3130851</fileSize><version>0.4</version></results>

无新版本返回: 空

实例代码段:
Widget.xml
<?xml version="1.0" encoding="utf-8" ?>
<results>
<iphone_filename>Iphone.ipa</iphone_filename>
<android_filename>Android.apk</android_filename>
<version>1.0</version>
</results>

应用所有者可以更改widget.xml文件的相关数据,版本号大于当前版本号才会有升级提醒
  PHP 解析处理

RPC_DIR : 文件路径
$_G : $_GET[''] 封装版
updateFileUrl: 最终的地址是http://.....
$version = $_G['gp_ver'];
$platform = $_G['gp_platform'];
if(empty($version) || !isset($platform)) return;
$filename = str_replace('rpc', '', RPC_DIR).'./widget.xml';
if(file_exists($filename)) {
  $c = file_get_contents($filename);
  preg_match('/<version>(.*?)<\/version>/', $c, $matches);
  $newver = $matches[1];
  preg_match('/<iphone_filename>(.*?)<\/iphone_filename>/', $c, $matches);
  $iphone_filename = $matches[1];
  preg_match('/<android_filename>(.*?)<\/android_filename>/', $c, $matches);
  $android_filename = $matches[1];
  if($newver > $version) {
    if($platform == '0') { //iphone
      $fileurl = $iphone_filename;
    } elseif($platform == '1') { //android
      $fileurl = $android_filename;
    }
    $filesize = filesize(DISCUZ_ROOT.'./source/plugin/zywx/'.$fileurl);
    if(empty($filesize)) exit;
      echo '<?xml version="1.0" encoding="utf-8" ?><results><updateFileName>discuz</updateFileName><updateFileUrl>'.$_G['siteurl'].'source/plugin/zywx/'.$fileurl.'</updateFileUrl><fileSize>'.$filesize.'</fileSize><version>'.$newver.'</version></results>';
  }
}

  Android& ios升级js代码示例[参考官方推出的DZ项目的login.html]

<script>
  var flag_sdcard = 1;
  var filepath = "wgt://data/data.txt";
  var updateurl = '';
  var filepath2 = "/sdcard/android.apk";
  var savePath = '';
  var platform = null;
  function ConfirmSuccess(opId,dataType,data) {
   if (data == 0) {
     ;
   } else {
     if (platform == 0) {
       uexWidget.loadApp("", "", updateurl);//通过浏览器加载appstore路径
     } else if (platform == 1) {
       uexDownloaderMgr.createDownloader("14");
     } else {
       ;
     }
   }
  }
  function checkSuc(opCode,dataType,jsonData) {
   var obj = eval('(' + jsonData + ')');
   if (obj.result == 0) {
     //tips = "更新地址是:" + obj.url + "<br>文件名:" + obj.name + "<br>文件大小:" + obj.size + 
     //"<br>版本号:" + obj.version;
     updateurl = obj.url;
     savePath = obj.name;
     var value = "稍后;更新";
     var mycars = value.split(";");
     uexWindow.confirm('', '当前有新版本,是否更新?', mycars);
   } else if (obj.result == 1) {
     ;//tips = "当前版本是最新的";alert(tips);
   } else if (obj.result == 2) {
     ;//tips = "未知错误";alert(tips);
   } else if (obj.result == 3) {
     ;//tips = "参数错误";alert(tips);
   }
  }
  function pageonload() {
   uexFileMgr.cbIsFileExistByPath = function(opCode, dataType, data) {
     if (flag_sdcard == 0) {
       if (data == 0) {
         log('sdcard不存在');
       } else {
         uexWidget.checkUpdate();
       }
       flag_sdcard = 1;
     } else {
       if (data == 0) {
         //creatFile(filepath);
       } else {
         //readFile(filepath, '-1');
       }
     }
   }
   uexDownloaderMgr.cbCreateDownloader = function(opId, dataType, data) {
     if (data == 0) {
       uexDownloaderMgr.download('14', updateurl, filepath2, '0');
     } else if (data == 1) {
       ;
     } else {
       ;
     }
   }
   uexDownloaderMgr.onStatus = function(opId, fileSize, percent, status) {
     if (status == 0) {//下载中...
       uexWindow.toast('1', '5', '下载进度:' + percent + '%', '');
     } else if (status == 1) {//下载完成.
       uexWindow.closeToast();
       uexDownloaderMgr.closeDownloader('14');
       uexWidget.installApp(filepath2);//安装下载apk文件
     } else {
       ;
     }
   }
   uexWindow.cbConfirm = ConfirmSuccess;
   uexWidget.cbCheckUpdate = checkSuc;
   uexWidgetOne.cbGetPlatform = function(opId, dataType, data) {
     platform = data;
     if (data == 0) {
       //是iphone
       uexWidget.checkUpdate();//同样的根据返回路径,可以通过uexWidget.loadApp()方法开启appstore的路径
     } else if (data == 1) {
       //是android
       flag_sdcard = 0;
       uexFileMgr.isFileExistByPath('/sdcard/');
       //uexWidget.checkUpdate();
     } else {
       //是平台
       ;
     }
   }
   uexWidgetOne.getPlatform();
  }
  zy_fix('header', '', null, pageonload);
</script>