我們假設(shè)您已經(jīng)能夠配置 React Native 開發(fā)環(huán)境,并且已經(jīng)開發(fā)完畢您的 App 了。
接下來,我們來配置熱更新,讓發(fā)布變得更簡單吧。
一、安裝 Android NDK
1、首先需要下載 NDK 包,
2、設(shè)置環(huán)境變量 ANDROID_NDK_HOME
$ vi ~/.bash_profile
ANDROID_NDK_HOME=/你的NDK地址
export PATH=${PATH}:其他變量:${ANDROID_NDK_HOME}
$ source ~/.bash_profile
二、打包簽名App
1、生成簽名文件
keytool -genkey -v -keystore my-release-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
此命令使用 keytool 生成一個(gè)簽名文件 my-release-key.keystore,使用此簽名文件 my-release-key.keystore 對已經(jīng)開發(fā)完畢的 App 簽名,生成 release 包進(jìn)行發(fā)布。
2、設(shè)置gradle變量
把my-release-key.keystore文件放到你工程中的android/app文件夾下。
編輯~/.gradle/gradle.properties(沒有這個(gè)文件你就創(chuàng)建一個(gè)),添加如下的代碼(注意把其中的****替換為相應(yīng)密碼)
MYAPP_RELEASE_STORE_FILE=my-release-key.keystore
MYAPP_RELEASE_KEY_ALIAS=my-key-alias
MYAPP_RELEASE_STORE_PASSWORD=*****
MYAPP_RELEASE_KEY_PASSWORD=*****
3、添加簽名到項(xiàng)目的gradle配置文件
編輯你項(xiàng)目目錄下的android/app/build.gradle,添加如下的簽名配置:
...
android {
...
defaultConfig { ... }
signingConfigs {
release {
storeFile file(MYAPP_RELEASE_STORE_FILE)
storePassword MYAPP_RELEASE_STORE_PASSWORD
keyAlias MYAPP_RELEASE_KEY_ALIAS
keyPassword MYAPP_RELEASE_KEY_PASSWORD
}
}
buildTypes {
release {
...
signingConfig signingConfigs.release
}
}
}
...
4、添加 NDK
修改 項(xiàng)目根目錄/android 下的 local.properties 文件(如果沒有,可以新建此文件)
sdk.dir=/你的 Android SDK 路徑
ndk.dir=/你的 Android NDK 路徑
5、生成發(fā)行App包
項(xiàng)目根目錄下運(yùn)行如下命令:
$ cd android && ./gradlew assembleRelease
三、安裝熱更新
1、在你的項(xiàng)目根目錄下運(yùn)行以下命令:
npm install -g react-native-update-cli rnpm
npm install --save react-native-update@具體版本請看下面的表格
react-native link react-native-update
npm install -g react-native-update-cli rnpm 這一句在每一臺電腦上僅需運(yùn)行一次。
如果RN版本低于0.29,請使用rnpm link代替react-native link命令。
因?yàn)镽eact Native不同版本代碼結(jié)構(gòu)不同,因而請按下面表格對號入座:
| React Native版本 | react-native-update版本 |
|---|---|
| <= 0.26 | 1.0.x |
| 0.27 - 0.28 | 2.x |
| 0.29 - 0.33 | 3.x |
| 0.34 - 0.39 | 4.x |
| 0.40 | 暫不支持 |
2、配置Bundle URL(Android)
0.29及以后版本:在你的MainApplication中增加如下代碼:
// ... 其它代碼
import cn.reactnative.modules.update.UpdateContext;
public class MainApplication extends Application implements ReactApplication {
private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
@Override
protected String getJSBundleFile() {
return UpdateContext.getBundleUrl(MainApplication.this);
}
// ... 其它代碼
}
}
0.28及以前版本:在你的MainActivity中增加如下代碼:
// ... 其它代碼
import cn.reactnative.modules.update.UpdateContext;
public class MainActivity extends ReactActivity {
@Override
protected String getJSBundleFile() {
return UpdateContext.getBundleUrl(this);
}
// ... 其它代碼
}
四、創(chuàng)建pushy帳號
1、注冊帳號
打開 http://update.reactnative.cn/
創(chuàng)建帳號,帳號為 YOUR_ACCOUNT, 密碼為 YOUR_PWD(記住,后期會(huì)用到)
并創(chuàng)建一個(gè)應(yīng)用,如下圖1,填入應(yīng)用名稱,選擇一個(gè)平臺。創(chuàng)建后,如下圖2。


2、命令行中,項(xiàng)目根目錄下運(yùn)行以下命令:
$ pushy login
email: <`YOUR_ACCOUNT`>
password: <`YOUR_PWD`>
3、創(chuàng)建或選擇 App
登錄之后可以創(chuàng)建應(yīng)用。注意iOS平臺和安卓平臺需要分別創(chuàng)建:(如果已經(jīng)創(chuàng)建則可以跳過)
$ pushy createApp --platform ios
App Name: <輸入應(yīng)用名字>
$ pushy createApp --platform android
App Name: <輸入應(yīng)用名字>
兩次輸入的名字可以相同,這沒有關(guān)系。
如果你已經(jīng)在網(wǎng)頁端或者其它地方創(chuàng)建過應(yīng)用,也可以直接選擇應(yīng)用:
$ pushy selectApp --platform ios|android
1) AppName1(android)
3) AppName2(ios)
Total 2 ios apps
Enter appId: <輸入應(yīng)用前面的編號>
五、App添加熱更新功能
修改項(xiàng)目根目錄下的 index.android.js,下面為完整的示例:
import React, {
Component,
} from 'react';
import {
AppRegistry,
StyleSheet,
Platform,
Text,
View,
Alert,
TouchableOpacity,
Linking,
} from 'react-native';
import {
isFirstTime,
isRolledBack,
packageVersion,
currentVersion,
checkUpdate,
downloadUpdate,
switchVersion,
switchVersionLater,
markSuccess,
} from 'react-native-update';
import _updateConfig from './update.json';
const {appKey} = _updateConfig[Platform.OS];
class MyProject extends Component {
componentWillMount(){
if (isFirstTime) {
Alert.alert('提示', '這是當(dāng)前版本第一次啟動(dòng),是否要模擬啟動(dòng)失敗?失敗將回滾到上一版本', [
{text: '是', onPress: ()=>{throw new Error('模擬啟動(dòng)失敗,請重啟應(yīng)用')}},
{text: '否', onPress: ()=>{markSuccess()}},
]);
} else if (isRolledBack) {
Alert.alert('提示', '剛剛更新失敗了,版本被回滾.');
}
}
doUpdate = info => {
downloadUpdate(info).then(hash => {
Alert.alert('提示', '下載完畢,是否重啟應(yīng)用?', [
{text: '是', onPress: ()=>{switchVersion(hash);}},
{text: '否',},
{text: '下次啟動(dòng)時(shí)', onPress: ()=>{switchVersionLater(hash);}},
]);
}).catch(err => {
Alert.alert('提示', '更新失敗.');
});
};
checkUpdate = () => {
checkUpdate(appKey).then(info => {
if (info.expired) {
Alert.alert('提示', '您的應(yīng)用版本已更新,請前往應(yīng)用商店下載新的版本', [
{text: '確定', onPress: ()=>{info.downloadUrl && Linking.openURL(info.downloadUrl)}},
]);
} else if (info.upToDate) {
Alert.alert('提示', '您的應(yīng)用版本已是最新.');
} else {
Alert.alert('提示', '檢查到新的版本'+info.name+',是否下載?\n'+ info.description, [
{text: '是', onPress: ()=>{this.doUpdate(info)}},
{text: '否',},
]);
}
}).catch(err => {
Alert.alert('提示', '更新失敗.');
});
};
render() {
return (
<View style={styles.container}>
<Text style={styles.welcome}>
歡迎使用熱更新服務(wù)
</Text>
<Text style={styles.instructions}>
這是版本一 {'\n'}
當(dāng)前包版本號: {packageVersion}{'\n'}
當(dāng)前版本Hash: {currentVersion||'(空)'}{'\n'}
</Text>
<TouchableOpacity onPress={this.checkUpdate}>
<Text style={styles.instructions}>
點(diǎn)擊這里檢查更新
</Text>
</TouchableOpacity>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: '#F5FCFF',
},
welcome: {
fontSize: 20,
textAlign: 'center',
margin: 10,
},
instructions: {
textAlign: 'center',
color: '#333333',
marginBottom: 5,
},
});
AppRegistry.registerComponent('MyProject', () => MyProject);
六、發(fā)布帶熱更新功能的App
1、上傳 apk 到 pushy
我們先在android文件夾下運(yùn)行 ./gradlew assembleRelease,你就可以在 android/app/build/outputs/apk/app-release.apk 中找到你的應(yīng)用包。
然后運(yùn)行如下命令,即可上傳apk以供后續(xù)版本比對之用。
$ pushy uploadApk android/app/build/outputs/apk/app-release.apk
2、發(fā)布新版
我們可以嘗試修改一行代碼(譬如將版本一修改為版本二),然后生成新的熱更新版本。
$ pushy bundle --platform <ios|android>
Bundling with React Native version: 0.22.2
<各種進(jìn)度輸出>
Bundled saved to: build/output/android.1459850548545.ppk
Would you like to publish it?(Y/N)
如果想要立即發(fā)布,此時(shí)輸入Y。當(dāng)然,你也可以在將來使用pushy publish --platform <ios|android> <ppkFile>來發(fā)布版本。
Uploading [========================================================] 100% 0.0s
Enter version name: <輸入版本名字,如1.0.0-rc>
Enter description: <輸入版本描述>
Enter meta info: {"ok":1}
Ok.
Would you like to bind packages to this version?(Y/N)
此時(shí)版本已經(jīng)提交到update服務(wù),但用戶暫時(shí)看不到此更新,你需要先將特定的包版本綁定到此熱更新版本上。
此時(shí)輸入Y立即綁定,你也可以在將來使用 pushy update --platform <ios|android> 來使得對應(yīng)包版本的用戶更新。 除此以外,你還可以在網(wǎng)頁端操作,簡單的將對應(yīng)的包版本拖到此版本下即可。
Offset 0
1) FvXnROJ1 1.0.1 (no package)
2) FiWYm9lB 1.0 [1.0]
Enter versionId or page Up/page Down/Begin(U/D/B) <輸入序號,U/D翻頁,B回到開始,序號就是上面列表中)前面的數(shù)字>
1) 1.0(normal) - 3 FiWYm9lB (未命名)
Total 1 packages.
Enter packageId: <輸入包版本序號,序號就是上面列表中)前面的數(shù)字>
版本綁定完畢后,客戶端就應(yīng)當(dāng)可以檢查到更新并進(jìn)行更新了。