iOS客戶端React-Native增量更新實踐
市場上現存方案:微軟的 CodePush 以及React-Native中文網的Pushy,大家可根據公司實際情況酌情選擇。
處於安全性的考慮,公司禁止向第三方平臺上傳原始碼相關檔案,所以要自己動手實現。
增量更新主要實現流程
1.使用react-native bundle 命令打包,壓縮打包檔案
2.使用bsdiff生成新舊RN版本壓縮檔案的差異化檔案patchFile
3.客戶端舊RN版本壓縮檔案合併下載的patchFile檔案,校驗檔案MD5值,解壓合併後的檔案,重新載入jsbundle,完成更新
4.增加版本控制,指令碼化1、2過程
$ cd bsdiff-4.3
2.修改makefile檔案格式如下,原檔案後三行縮排格式不對:
CFLAGS += -O3 -lbz2
PREFIX ?= /usr/local
INSTALL_PROGRAM ?= ${INSTALL} -c -s -m 555
INSTALL_MAN ?= ${INSTALL} -c -m 444
all: bsdiff bspatch
bsdiff: bsdiff.c
bspatch: bspatch.c
install:
${INSTALL_PROGRAM} bsdiff bspatch ${PREFIX}/bin
.ifndef WITHOUT_MAN
${INSTALL_MAN} bsdiff.1 bspatch.1 ${PREFIX}/man/man1
.endif
3.在bspatch.c檔案中加入標頭檔案
#include<sys/types.h>
4.終端執行make命令,生成bsdiff、bspatch檔案
$ make
5.將bsdiff、bspatch檔案拷貝到usr/local/bin 目錄下
6.使用方式:
//生成差異檔案
$ bsdiff oldFilePath newFilePath patchFilePath
//合併檔案
$ bspatch oldFilePath newFilePath patchFilePath
二、客戶端合併檔案,工程需要新增libbz2.tbd
1.bsdiff.h
#ifndef bsdiff_h
#define bsdiff_h
#define LBD_OK 0
#define LBD_ERR_OPEN 1000
#define LBD_ERR_CLOSE 1005
#define LBD_ERR_MALLOC 1010
#define LBD_ERR_SEEK 1015
#define LBD_ERR_TELL 1020
#define LBD_ERR_READ 1025
#define LBD_ERR_WRITE 1030
#define LBD_ERR_CORRUPT 1035
#define LBD_ERR_BZ 2000
#include <stdio.h>
int ff_patch(const char *oldf, const char *patchf, const char *newf);
#endif /* bsdiff_h */
2.bsdiff.c
#include "bsdiff.h"
#include <stdio.h>
#include <stdint.h>
#include <bzlib.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include<sys/types.h>
#define MIN(x,y) (((x)<(y)) ? (x) : (y))
static off_t offtin(u_char *buf) {
off_t y;
y=buf[7]&0x7F;
y=y*256;y+=buf[6];
y=y*256;y+=buf[5];
y=y*256;y+=buf[4];
y=y*256;y+=buf[3];
y=y*256;y+=buf[2];
y=y*256;y+=buf[1];
y=y*256;y+=buf[0];
if(buf[7]&0x80) y=-y;
return y;
}
#pragma mark - Public
int ff_patch(const char *oldf, const char *patchf, const char *newf) {
FILE *f, *cpf, *dpf, *epf;
BZFILE *cpfbz2, *dpfbz2, *epfbz2;
int cbz2err, dbz2err, ebz2err;
int fd;
ssize_t oldsize, newsize;
ssize_t bzctrllen, bzdatalen;
uint8_t header[32], buf[8];
uint8_t *old, *new;
off_t oldpos, newpos;
off_t ctrl[3];
off_t lenread;
off_t i;
if ((f = fopen(patchf, "r")) == NULL)
{
return LBD_ERR_OPEN;
}
/* Read header */
if (fread(header, 1, 32, f) < 32)
{
if (feof(f))
{
return LBD_ERR_CORRUPT;
}
return LBD_ERR_READ;
}
/* Check for appropriate magic */
// had to change this to use patches created with command line bsdiff
// if (memcmp(header, "LBDIFFXX", 8) != 0)
if (memcmp(header, "BSDIFF40", 8) != 0)
{
return LBD_ERR_CORRUPT;
}
/* Read lengths from header */
bzctrllen = offtin(header + 8);
bzdatalen = offtin(header + 16);
newsize = offtin(header + 24);
if ((bzctrllen < 0) || (bzdatalen < 0) || (newsize < 0))
{
return LBD_ERR_CORRUPT;
}
/* Close patch file and re-open it via libbzip2 at the right places */
if (fclose(f))
{
return LBD_ERR_CLOSE;
}
if ((cpf = fopen(patchf, "r")) == NULL)
{
return LBD_ERR_OPEN;
}
if (fseeko(cpf, 32, SEEK_SET))
{
return LBD_ERR_SEEK;
}
if ((cpfbz2 = BZ2_bzReadOpen(&cbz2err, cpf, 0, 0, NULL, 0)) == NULL)
{
return LBD_ERR_BZ;
}
if ((dpf = fopen(patchf, "r")) == NULL)
{
return LBD_ERR_OPEN;
}
if (fseeko(dpf, 32 + bzctrllen, SEEK_SET))
{
return LBD_ERR_SEEK;
}
if ((dpfbz2 = BZ2_bzReadOpen(&dbz2err, dpf, 0, 0, NULL, 0)) == NULL)
{
return LBD_ERR_BZ;
}
if ((epf = fopen(patchf, "r")) == NULL)
{
return LBD_ERR_OPEN;
}
if (fseeko(epf, 32 + bzctrllen + bzdatalen, SEEK_SET))
{
return LBD_ERR_SEEK;
}
if ((epfbz2 = BZ2_bzReadOpen(&ebz2err, epf, 0, 0, NULL, 0)) == NULL)
{
return LBD_ERR_BZ;
}
if (((fd = open(oldf, O_RDONLY, 0)) < 0) ||
((oldsize = lseek(fd, 0, SEEK_END)) == -1) ||
((old = malloc(oldsize + 1)) == NULL) ||
(lseek(fd, 0, SEEK_SET) != 0) ||
(read(fd, old, oldsize) != oldsize) ||
(close(fd) == -1))
{
return LBD_ERR_OPEN;
}
if ((new = malloc(newsize + 1)) == NULL)
return LBD_ERR_MALLOC;
oldpos = 0;
newpos = 0;
while (newpos < newsize)
{
/* Read control data */
for (i = 0;i <= 2; i++)
{
lenread = BZ2_bzRead(&cbz2err, cpfbz2, buf, 8);
if ((lenread < 8) || ((cbz2err != BZ_OK) &&
(cbz2err != BZ_STREAM_END)))
{
return LBD_ERR_CORRUPT;
}
ctrl[i] = offtin(buf);
}
/* Sanity-check */
if (newpos + ctrl[0] > newsize)
{
return LBD_ERR_CORRUPT;
}
/* Read diff string */
lenread = BZ2_bzRead(&dbz2err, dpfbz2, new + newpos, ctrl[0]);
if ((lenread < ctrl[0]) ||
((dbz2err != BZ_OK) && (dbz2err != BZ_STREAM_END)))
{
return LBD_ERR_CORRUPT;
}
/* Add old data to diff string */
for (i=0; i < ctrl[0]; i++)
if ((oldpos + i >= 0) && (oldpos + i < oldsize))
new[newpos + i] += old[oldpos + i];
/* Adjust pointers */
newpos += ctrl[0];
oldpos += ctrl[0];
/* Sanity-check */
if (newpos + ctrl[1] > newsize)
{
return LBD_ERR_CORRUPT;
}
/* Read extra string */
lenread = BZ2_bzRead(&ebz2err, epfbz2, new + newpos, ctrl[1]);
if ((lenread < ctrl[1]) ||
((ebz2err != BZ_OK) && (ebz2err != BZ_STREAM_END)))
{
return LBD_ERR_CORRUPT;
}
/* Adjust pointers */
newpos += ctrl[1];
oldpos += ctrl[2];
}
/* Clean up the bzip2 reads */
BZ2_bzReadClose(&cbz2err, cpfbz2);
BZ2_bzReadClose(&dbz2err, dpfbz2);
BZ2_bzReadClose(&ebz2err, epfbz2);
if (fclose(cpf) || fclose(dpf) || fclose(epf))
{
return LBD_ERR_CLOSE;
}
/* Write the new file */
if (((fd = open(newf, O_CREAT|O_TRUNC|O_WRONLY, 0666)) < 0) ||
(write(fd, new, newsize) != newsize) || (close(fd) == -1))
{
return LBD_ERR_OPEN;
}
free(new);
free(old);
return LBD_OK;
}
五、版本管理指令碼化 待更新
相關推薦
iOS客戶端React-Native增量更新實踐
市場上現存方案:微軟的 CodePush 以及React-Native中文網的Pushy,大家可根據公司實際情況酌情選擇。 處於安全性的考慮,公司禁止向第三方平臺上傳原始碼相關檔案,所以要自己動手實現。 增量更新主要實現流程 1.使用react-nativ
基於React Native封裝的資訊頻道TopBar,常見於新聞客戶端react-native-scrollable-topbar
react-native-scrollable-topbar 基於React Native封裝的資訊頻道TopBar,常見於新聞客戶端,具體實現功能如下: TopBar區域可手動滑動(Underline 聯動) 點選頻道實現內容區切換 根據內容區(this.p
58 同城 iOS 客戶端搜尋模組元件化實踐
【編者按】58 同城 App 自從 1.0 版本開始,便已經提供了搜尋功能。隨著版本的迭代、業務的複雜,搜尋框架也在不斷受到挑戰。諸如程式碼不能複用、耦合度高、業務功能接入成本高等問題日積月累,成為需要迫切解決的問題。本文從具體實際問題入手,詳述了利用元件
React Native入門——佈局實踐:開發京東客戶端首頁(二)TabBar的構建
上篇文章講到構建京東客戶端首頁的搜尋欄,本篇我們一起來學習TabBar的構建。根據之前的調研,在構建TabBar的方式上,我推薦使用國外大神James Ide(https://github.com/ide)釋出在Exponent上的react-native-tab-navig
React-Native 熱更新以及增量更新
不是增量更新,Rn的熱更新,流程是下載伺服器端上的一個解壓包到本地 解壓到應用的檔案目錄 這是一個打包後的apk檔案,在Rn中我們的js程式碼都是打包後存放在assets目錄中,其中index.android.bundle,可以理解我們js寫後打包
react native增量熱更新生成合並補丁檔案
這是一個node命令,有兩個命令可用,一是用於生成補丁檔案,一個是合併補丁生成新的檔案. 很多情況下我們需要生成補丁檔案,例如 react native 的熱更新,自建伺服器進行熱更新,不用codepush和pushy,需要生成bundle的補丁檔案,然後從伺服器下載下
[深入剖析React Native]熱更新之react-native-pushy使用指南(IOS)
本文使用RN版本:0.33.0 準備工作 首先你應該有一個基於React Native開發的應用,我們把具有package.json的目錄叫做你的”應用根目錄”。 如果你還沒有初始化應用,請參閱開始使用React Native。 所以我們也假
iOS 客戶端獲取七牛上傳token
生成 edi signed 解析 ring request self 在線 err 一、官方參考文檔: 1.上傳策略http://developer.qiniu.com/article/developer/security/put-policy.html 2.上傳憑證(即u
js判斷安卓客戶端或者是ios客戶端
終端 use navigator 判斷 com oca topic fun and 代碼: function xaizai() { var u = navigator.userAgent, app = navigator.appVersion; var isA
iOS客戶端節日換膚方案探究
named 普通模式 ani chang theme 1.5 static 解析 .json 轉自:https://www.ianisme.com的博客 一、前言: tip: 本來這篇文章在聖誕節就已經準備好了,但是由於種種原因一直沒有寫完,今天將它寫出來,也算是2018
要開始做博客園iOS客戶端了
2個 wid 原始的 註冊 網易 博客 可能 技術 內容 去年心血來潮做了一個dribbble客戶端,但是因為太忙又沒有發布,直到今年這時候準備回頭去整理一下然後上架,居然發現dribbble官方早在今年3月就把API權限收緊了,現在仍然開放的API和沒有差不多,真是欲
iOS客戶端的微信支付接入
對於一個iOS的APP,如果有一些虛擬的商品或者服務需要通過線上支付來收費的話,一般有幾種主流的選擇。 如果是通過APP呼叫支付平臺APP的思路的話,一個是調起支付寶客戶端,一個則是調起微信支付。 實際上,從程式碼的角度,調起支付APP就是把一些關鍵的引數通過一定方式打包成為一個訂單,
React Native熱更新(CodePush使用)
dfa epush nodejs 管理 push alpha 輸入 進制 通過 React Native熱更新(CodePush使用) 在移動應用開發過程中,應用的發布上線一直是個耗時且長時間沒有
一個資深iOS開發者對於React Native的看法
本文轉自:http://blog.csdn.net/zhe13/article/details/48439967?hmsr=toutiao.io&utm_medium=toutiao.io&utm_source=toutiao.io 當我第一次嘗試ReactNative的時候,我
react-native熱更新
一、全域性安裝 code-push-cli $ npm i -g code-push-cli 二、註冊 App Center 執行以下命令 $ code-push register 或直接開啟 https://appcenter.ms/ 註冊 三、登入
支付寶客戶端架構解析:iOS 客戶端啟動效能優化初探
前言 《支付寶客戶端架構解析》系列將從支付寶客戶端的架構設計方案入手,細分拆解客戶端在“容器化框架設計”、“網路優化”、“效能啟動優化”、“自動化日誌收集”、“RPC 元件設計”、“移動應用監控、診斷、定位”等具體實現,帶領大家進一步瞭解支付寶在客戶端架構上的迭代與優化歷程。 啟動應用是使用者使用任何一款
AJAX+Servlet實現客戶端無重新整理請求伺服器實踐
最近需要做一個在網頁中要不斷檢測伺服器端資料程式,當然最簡單的方法是在html頁面頭部加以下標籤 <META http-equiv=V="REFRESH" content="5;URL=本頁面url"> 實現將網頁設成每隔5秒鐘將自身頁面重新整理一次
react native 熱更新與程式簡單除錯
1.如何開啟Developer Menu 模擬器:ctrl+m 真機:搖一搖手機即可 2.除錯及熱更新準備工作:當真機使用資料線或者模擬器時可以忽略,建議
IOS客戶端app線上安裝ipa包,
在github上建立安裝需要的plist檔案 <?xml version="1.0" encoding="UTF-8"?><!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN""http://www.app
58 同城 iOS 客戶端元件化演變思路整理
1、 http://geek.csdn.net/news/detail/193435 2、標題:58 同城 iOS 客戶端元件化演變歷程 3、第一版App架構:功能比較簡單,出發點是為了快速搶佔市場,採取“短平快”的方式開發。 4、第二版架構: