開發(fā)完了,該看看如何上線和維護(hù)一個項目了。
(一)打包apk
乍一看目錄結(jié)構(gòu),有一個Android的gradle項目,所以筆者瞬間就想到使用Android Studio生成一個簽名密鑰,然后打包生成正式簽名的apk,
(不太懂得給個鏈接自己去看:?http://blog.csdn.net/sunylat/article/details/9239595/)
待筆者adb install這個apk以后才發(fā)現(xiàn),日了,native的代碼跑完之后就紅屏了(Error),這才突然想到,在開發(fā)的時候貌似有這樣一個過程:

首次運行的話,有一個從服務(wù)端下載js的過程,所以中間肯定是缺了哪一步,才導(dǎo)致了無法訪問到我們的React native界面,
那么到底該如何打包這樣一個apk呢?
在這里詳解一下Android的,關(guān)于IOS的,想了解的自行去rn中文網(wǎng)
1)生成一個簽名密鑰,
①你可以像作者一樣用AS搞一個簽名文件放在桌面上~ ? 會生成一個

②也可以用命令行生成
因為作者不是這樣生成的,所以就不做介紹了,可以參考
http://reactnative.cn/docs/0.42/signed-apk-android.html#content
備注:這里一定要注意,記住你給密鑰起的別名(keyAlias),一定要記住,后面填錯了會報Failed to read key from keystore…
2)在gradle中配置上正式的簽名信息

別名要寫對,然后再buildTypes里弄上這一句,注意,名字要對應(yīng)起來!寫的是config就是.config,至于下面的編譯時混淆的功能就不在這里進(jìn)行詳細(xì)解釋了。
3)在Rn項目的android目錄中,執(zhí)行./gradlew assembleRelease
前面的點別忘,記得要翻墻。(下載gradle過程中出現(xiàn)一堆點不要緊,只要保證網(wǎng)絡(luò)正常,過一會就會下載完成)。
Gradle的assembleRelease參數(shù)會把所有用到的JavaScript代碼都打包到一起,然后內(nèi)置到APK包中。生成的APK文件位于android/app/build/outputs/apk/app-release.apk,它已經(jīng)可以用來發(fā)布了。
4)可以用他提供的命令:./gradlew installRelease
也可以把apk直接adb install,這時候演示的時候已經(jīng)可以脫離Reactpackager了
(二)熱更新方案 和 應(yīng)用
1)什么是熱更新
? ? ? ?簡單說就是不需要去應(yīng)用市場重新下載,直接打開app就會下載更新的內(nèi)容然后進(jìn)入app,類似于經(jīng)常玩的手游,游戲里需要更新,然后就有個進(jìn)度條在讀取??偨Y(jié)就是可以不通過應(yīng)用市場來進(jìn)行升級,極大的提升了app修bug和賦予新功能的能力。
備注:當(dāng)然,Android現(xiàn)在app也可以在加載開機(jī)動畫的時候檢查更新,去服務(wù)端下載最新apk,然后調(diào)起install頁面安裝覆蓋。但體驗不佳,且IOS就無法這樣搞了…所以熱更新還是比較有研究價值的。
2)熱更新方案原理
就目前來看,RN的熱更新方案已有的,有微軟的CodePush和reactnative中文網(wǎng)的pushy。
從上面的圖中可以看出,當(dāng)加載RN頁面的時候,需要先加載叫做JS bundle的文件,而加載bundle文件又有幾個途徑,通過對Android項目中native代碼的分析,可以得出bundle的加載路徑來源取決于JSBundleLoader的loadScript,而loadScript又調(diào)用了CatalystInstanceImpl的loadScriptFromAssets或者loadScriptFromFile,所以,加載bundle文件的途徑本質(zhì)上有兩種方式:
①loadScriptFromAssets
從android項目下的assets文件夾下去加載,這也是RN發(fā)布版的默認(rèn)加載方式,也就是在cmd命令行下使用gradlew assembleRelease命令打包簽名后的apk,里面的assets就包含有bundle文件
②loadScriptFromFile
第二種方式是從android文件系統(tǒng)也就是sd卡下去加載bundle。我們只要事先在sd卡下存放bundle文件,然后在ReactNativeHost的getJSBundleFile返回文件路徑即可。getJSBundleFile首先會嘗試在sd卡目錄下:data/data//cache/react_native/
看是否存在index.android.bundle文件,如果有,那么就會使用該bundle,如果沒有,那么就會返回null,這時候就是去加載assets下的bundle了。
具體的分析代碼過程可參考?http://blog.csdn.net/shandian000/article/details/54582603
所以,熱更新需要做的,就是兩點:
①把服務(wù)端存放的bundle patch(包括bundle文件和一些圖片資源)下載到sd卡
②在程序中加載bundle文件
根據(jù)bug的緊急/重要程度,可以把加載bundle的時機(jī)分為:立馬加載和下次啟動加載,這里將它們分別稱為熱加載和冷加載:
?(1)冷加載
冷加載方式比較簡單,不用做任何特殊處理,下載并解壓完patch.zip包之后,當(dāng)應(yīng)用完全退出之后(應(yīng)用在后臺不算完全退出,應(yīng)用被殺死才算),用戶再次啟動應(yīng)用,就會去加載新的bundle了
?(2)熱加載
熱加載需要特殊處理一下,處理也很簡單,只要在解壓unzip之后,調(diào)用以下代碼即可

備注:這個檢測的過程也可以通過JS端調(diào)用Android Native提供的module來完成,具體請詳見前面的博客鏈接
3)熱更新的應(yīng)用
熱更新可以自己搭服務(wù)進(jìn)行,參考前面的博客鏈接,
但考慮到為了減少客戶端與服務(wù)端開發(fā)量起見,我們選用RN中文網(wǎng)上提供的pushy進(jìn)行詳解
項目git地址: https://github.com/yujiesuperman/react-native-hotupload-thirdapp
① 去熱更新開放平臺注冊賬號,郵件激活 ??http://update.reactnative.cn
安裝 npm install -g react-native-update-cli rnpm
在Rn項目中:npm install --save react-native-update
rnpm link react-native-update 看到success
②配置Bundle URL,(這里提供Android的,Ios的請參考Rn中文網(wǎng))
0.29及以后版本:在你的MainApplication中增加如下代碼:

即重寫getJSBundleFile方法。
③如果你之前沒安裝過NDK,你還必須安裝Android NDK,并設(shè)置環(huán)境變量ANDROID_NDK_HOME,指向你的NDK根目錄

④登錄與創(chuàng)建應(yīng)用
pushy login
email:<輸入你的注冊郵箱>
password:<輸入你的密碼>
登錄之后可以創(chuàng)建應(yīng)用。注意iOS平臺和安卓平臺需要分別創(chuàng)建:
$ pushy createApp --platform ios
App Name:<輸入應(yīng)用名字>
$ pushy createApp --platform android
App Name:<輸入應(yīng)用名字>
兩次輸入的名字可以相同,這沒有關(guān)系,create了以后,就可以看到update.json里的

備注:因為之前只創(chuàng)建了Android應(yīng)用,所以只能看到Android相關(guān)信息
⑤接下來就該在應(yīng)用里快速添加熱更新相關(guān)的代碼了
(1)先來看頭部的引入的組件

注釋里詳細(xì)介紹了每個組件的作用,以及獲取后面用到的參數(shù)appKey的方法
(2)然后看添加在thirdRNandNativeapp的主頁面內(nèi)的方法

是的,眼尖的同學(xué)又發(fā)現(xiàn)了,除了兩個自定義的檢查更新和下載更新的方法外,又出現(xiàn)了一個生命周期內(nèi)的函數(shù):componentWillMount()。
在組件創(chuàng)建之前,會先調(diào)用getDefaultProps(),這是全局調(diào)用一次,嚴(yán)格地來說,這不是組件的生命周期的一部分。在組件被創(chuàng)建并加載的時候,首先調(diào)用getInitialState(),來初始化組件的狀態(tài)(現(xiàn)在多在構(gòu)造里完成)。componentWillMount這個函數(shù)調(diào)用時機(jī)是在組件創(chuàng)建,并初始化了狀態(tài)之后,在第一次繪制render()之前??梢栽谶@里做一些業(yè)務(wù)初始化操作,也可以設(shè)置組件狀態(tài)。這個函數(shù)在整個生命周期中只被調(diào)用一次。在這里我們進(jìn)行了判斷是否是第一次啟動,或者是否模擬回滾操作。
(3)再來看頁面上添加的這一部分,render()函數(shù)里

在這一坨熱更新相關(guān)里,顯示了當(dāng)前Native包的版本號packageVersion,
這個在Native代碼的這個位置:

熱更新下載下來的新的版本號currentVersion,如果沒有就顯示空。
備注:這時候運行,多半會遇到這個錯誤,

原因是有時候用rnpm去link代碼的時候會失敗,需要手動配置;
首先確認(rèn)

這三個不要忘了添加,,作者就是忘了添加第三處。。教程里都沒有說。。。
然后在項目android目錄下的setting.gradle文件中添加
include ':react-native-update'
project(':react-native-update').projectDir =?
new File(rootProject.projectDir, '../node_modules/react-native-update/android')
然后在app目錄下的build.gradle文件中添加
dependencies {
compile project(':react-native-update') //<--這一句
……
}
運行實際效果圖:

因為這個時候服務(wù)端并沒有任何的版本,所以顯示

⑥發(fā)布應(yīng)用
先重新打包一個代簽名的apk;方法見前。
pushy uploadApk android/app/build/outputs/apk/app-release.apk
即可上傳apk以供后續(xù)版本比對之用。
隨后你可以選擇往應(yīng)用市場發(fā)布這個版本,也可以先往設(shè)備上直接安裝這個apk文件以進(jìn)行測試。

這個時候上傳了版本后,再點擊更新,就顯示

注意:要在Rn目錄下執(zhí)行這個命令,不能直接找到apk直接upload;要不然無法正常執(zhí)行。
⑦修改一行代碼,然后上傳,
我們就把Demo1中的那張圖片加上,加完后效果:

⑧然后去命令行去發(fā)布新的版本
pushy bundle --platform android


版本名,版本描述,最后一個可以空著,然后綁定到一個版本上去,這時候再回到應(yīng)用:

備注:可以看到,當(dāng)我們下載更新完一個版本之后,首次啟動,isFirstTime會變?yōu)閠rue,走那個模擬回滾的alert,在這里就不模擬了,感興趣的自己玩下~