Ionic Pro的deploy热更新简明介绍

Ionic框架是Hybrid App,通过嵌入Cordova可以用Html5的形式开发App。Hybrid App代码的更新分为两种,一种是Native的更新,比如Cordova添加插件,一种是Html5和JavaScript的更新。第一种更新需要重新安装App,而第二种更新可以无须重新安装,直接热更新。

Ionic Pro为Ionic框架提供了及时更新App UI和业务逻辑的功能。

在Ionic Pro中创建应用

点击进入Ionic Pro的仪表盘,点击New App创建应用:

创建一个新的App

App关联Ionic Pro

情况一:还没创建对应的Ionic App,可以使用以下命令行创建相应的Ionic App。同时,Ionic会把创建的Ionic App与在Ionic Pro创建的应用关联:

ionic start --pro-id #你的App id#
cd cookies

情况二:已经存在Ionic App,可以使用以下命令把ionic App与Ionic Pro的应用关联

ionic link --pro-id #你的App id#
查看Appid.png

关联自己的git远程仓库

Ionic Pro不建议用户把代码存放在Ionic Pro中,因此还是需要有自己的git仓库,用于保存代码,等到某个阶段开发完毕,才把代码上传到App所属的Ionic Pro中。

使用下面的命令,为你的项目添加远程git仓库,并且上传代码到仓库:

git remote add origin [YOUR_REPOSITORY_URL]
git push -u origin master

把代码上传到Ionic Pro中

git push ionic master

添加Deploy插件

插件情况.png

Ionic Pro具体提供了三种更新情况,我这里选择手动更新啊,会控制更加方便。在项目目录下运行以下命令添加插件:

cordova plugin add cordova-plugin-ionic --save \
--variable APP_ID="2c4aab3e" \
--variable CHANNEL_NAME="Master" \
--variable UPDATE_METHOD="none"

下面提供了工具类IonicDeploy:

declare var IonicCordova;

@Injectable()
export class IonicDeploy{
  private isCordovaEnv: boolean = false;
  // 是否已经初始化
  private pluginWasInitialized: boolean = false;
  private _channel: string = 'Master';

  constructor(private platform: Platform,
              private zone: NgZone) {
    this.isCordovaEnv = platform.is('cordova');
  }

  // 初始化Deploy插件
  init() {
    this.onlyIfCordovaEnv();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.init({channel: this._channel}, () => {
        this.pluginWasInitialized = true;
        resolve(true);
      }, err => reject(err));
    });
  }

  // 检查是否有可用更新
  check() {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.check(result => resolve((result === 'true') ? true : false), err => reject(err));
    });
  }

  // 一个新版本可用下载
  download(onProgress) {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.download(result => {
        const percent = (result === 'true' || result === 100) ? 100 : result;
        this.zone.run(() => onProgress(percent));
        if (percent === 100) resolve();
      }, err => {
        reject(err);
      });
    });
  }

  // 解压最新版本
  extract(onProgress) {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.extract(result => {
        const percent = (result === 'done') ? 100 : result;
        this.zone.run(() => onProgress(percent));
        if (percent === 100) resolve();
      }, err => {
        reject(err);
      });
    });
  }

  // 加载最新版本
  load() {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.redirect(() => resolve(true), err => reject(err));
    });
  }

  // 获取该设备的当前版本信息
  info() {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.info(result => resolve(result), err => reject(err));
    });
  }

  // 获取该设备中已经下载的版本
  getVersions() {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.getVersions(result => resolve(result), err => reject(err));
    });
  }

  // 根据UUID删除该设备已经下载的版本
  deleteVersion(uuid) {
    this.onlyIfPluginInitialized();
    return new Promise((resolve, reject) => {
      IonicCordova.deploy.deleteVersion(uuid, () => resolve(true), err => reject(err));
    });
  }

  // 判断是否为Cordova环境
  private onlyIfCordovaEnv() {
    if (!this.isCordovaEnv) {
      console.error('IonicDeploy不能在非真实机器上运行!');
      return;
    }
  }

  // 检查插件是否已经初始化
  private onlyIfPluginInitialized() {
    if (!this.pluginWasInitialized) {
      console.error('IonicDeploy未被初始化, 你需要先执行init方法!');
      return;
    }
  }
}

调用上面的工具方法:

update(){
    if (this.platform.is('cordova')) {
      if (this.runningDeploy) return;

      let toast = this.toastCtrl.create({
        message: '下载中 ... 0%',
        position: 'top',
        showCloseButton: false,
        closeButtonText: '关闭'
      });

      this.ionicDeploy.init()
        .then(() => this.ionicDeploy.check())
        .then(snapshotAvailable => {
          toast.present();
          if (snapshotAvailable) {
            this.runningDeploy = true;
            return this.ionicDeploy.download(percent => toast.setMessage('下载中 ... ' + percent + '%'));
          }else{
            // 检查到没有更新,则中止下面的链式then
            return Promise.reject({
              snapshotAvailable: false
            });
          }
        })
        .then(() => this.ionicDeploy.extract(percent => toast.setMessage('解压中 ... ' + percent + '%')))
        .then(() => this.ionicDeploy.load())
        .then(() => toast.dismiss())
        .then(() => this.runningDeploy = false)
        .catch(ex => {
          if (!ex.snapshotAvailable){
            toast.setMessage('该版本已是最新版,不需要更新!');
            toast.setDuration(3000);
          }else{
            this.runningDeploy = false;
            toast.setMessage('对不起,由于网络问题更新失败, 请在次手动更新!');
            toast.setDuration(3000);
          }
        })
    }else{
      console.error('版本热更新不能在非真实机器上运行!')
    }
  }

上面提供了控制更新的方法。代码写完后,提交到Ionic Pro,触发update方法,App就会检测到更新,自动更新代码。

关于版本的控制

如何查看App壳的版本?我们可以打开项目根目录下的config.xml文件,version记录了当前App壳的版本号。

下图里,看到更新的记录,点击版本号进去,可以看到版本好设置:


更新记录.png

版本控制.png
  • Minium:允许更新的最小版本
  • Maximum:允许更新的最大版本
  • Equivalent:当App版本号等于此值时,不需要更新这个build
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,902评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,037评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,978评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,867评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,763评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,104评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,565评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,236评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,379评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,313评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,363评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,034评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,637评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,719评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,952评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,371评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,948评论 2 341

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,275评论 25 707
  • 富贵不足以平慰人生,贫穷并不都会落魄。怎样把小日子过好才是真本领。能把柴米油盐的平淡生活过得细腻有致就是一种体面。...
    淘砂阅读 1,021评论 1 5
  • 听Eason的十年,第一次听是因为校园流行音乐。课间休息时间,录音机哼唱的都是流行音乐。该死的温柔 江南 死了都要...
    青禾真实阅读 257评论 1 2
  • 文/连山蒂 一 “妈,我还是不放心,你给滢宝都带全没?保温杯、练习本、铅笔……” “林朝啊,昨天你打了两遍,今早晨...
    连山蒂阅读 5,886评论 85 177
  • Thinking Is Doing: Neurotechnology ① Brain scientists wan...
    新心断点阅读 327评论 0 0