淺談React原生APP更新
App更新流程
1.在 App 打開時請求接口或文件, 獲取遠程版本/版本更新說明/地址等等重用信息
2.通過庫或者原生方案, 獲取 App 的當前版本
3.比較遠程版本和當前版本的區(qū)別(可以使用庫,也可以自己寫一個比較方案)
4.通過獲取到的鏈接進行操作(可以跳轉到對應網站下載,類似蒲公英這種,可以是 apk 鏈接, 通過安卓原生方法下載, 也可以是 App Store 鏈接)
大致的流程圖
詳細說明:
1.這些遠程信息,可以是接口, 這樣可以有一個中臺來控制, 當然也可以是一個文件, 讓運維來控制
關于信息,不止于遠程版本, 在項目里還可以添加其他屬性,如: versionCode, versionCodeSwitch , notUpdate , deleteApp
- 1.1 versionCode 通過 code 來升級版本,一般是一個數字(在 ios 里提交 App Store 的時候有需要用到的地方), 這樣 versionName 并不會增加, 但是如果添加了 versionCode, 如果要升級 versionName, versionCode 也需要增加
- 1.2 versionCodeSwitch 用來控制是否要根據versionCode來更新, 一般我都是在測試和其他環(huán)境開啟,生產環(huán)境關閉的
- 1.3 notUpdate 是否要根據遠程信息來更新, 一般都是開啟狀態(tài)
- 1.4 deleteApp 安卓 app 需要卸載重新安裝, 因為直接安裝可能存在某些問題, 將會使用此信息,先刪除 APP, 再重新下載
2.獲取當前手機的信息,方案較多, 我使用的是 react-native-device-info 這個庫, 這個庫里面提供的信息較全, 當然也可以使用原生方法, 來獲取APP的信息
3.關于本地版本號和原生版本號之間的對比也是可以使用庫,也可以自己寫, 這邊推薦兩個庫,下載量都是百萬以上的: semver-compare 和 compare-versions, 這邊附上我的 versionName 比較方案, 較為簡陋:
/** * 比較兩版本號 * @param currentVersion * @return boolean * true=需要更新 false=不需要 */ compareVersion = (currentVersion: string): boolean => { const {versionName: remoteVersion} = this.remoteInfo || {} if (!remoteVersion) { return false } if (currentVersion === remoteVersion) { return false } const currentVersionArr = currentVersion.split('.') const remoteVersionArr = remoteVersion.split('.') for (let i = 0; i < 3; i++) { if (Number(currentVersionArr[i]) < Number(remoteVersionArr[i])) { return true } } return false }
關于下載 app 有很多方案, 最簡單的就是跳轉鏈接到第三方平臺, 像蒲公英這樣的, 使用 RN 提供的 Linking 方法來直接跳轉
當然安卓是可以直接通過自己提供的地址下載的, 這里提供一個方法(此方法來源于網絡):
@ReactMethod public void installApk(String filePath, String fileProviderAuthority) { File file = new File(filePath); if (!file.exists()) { Log.e("RNUpdater", "installApk: file doe snot exist '" + filePath + "'"); // FIXME this should take a promise and fail it return; } if (Build.VERSION.SDK_INT >= 24) { // API24 and up has a package installer that can handle FileProvider content:// URIs Uri contentUri; try { contentUri = FileProvider.getUriForFile(getReactApplicationContext(), fileProviderAuthority, file); } catch (Exception e) { // FIXME should be a Promise.reject really Log.e("RNUpdater", "installApk exception with authority name '" + fileProviderAuthority + "'", e); throw e; } Intent installApp = new Intent(Intent.ACTION_INSTALL_PACKAGE); installApp.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); installApp.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); installApp.setData(contentUri); installApp.putExtra(Intent.EXTRA_INSTALLER_PACKAGE_NAME, reactContext.getApplicationInfo().packageName); reactContext.startActivity(installApp); } else { // Old APIs do not handle content:// URIs, so use an old file:// style String cmd = "chmod 777 " + file; try { Runtime.getRuntime().exec(cmd); } catch (Exception e) { e.printStackTrace(); } Intent intent = new Intent(Intent.ACTION_VIEW); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setDataAndType(Uri.parse("file://" + file), "application/vnd.android.package-archive"); reactContext.startActivity(intent); } }
如果是我們自己提供下載服務,需要注意的是帶寬, 如果網速過慢則用戶體驗過差, 還有就會帶來更多的流量消耗, 其中的取舍,需要開發(fā)者決定
更新APP信息
在打包時, 通過腳本更新接口或者文件信息, 當然這個得看具體的打包方案
比如我現在的方案是使用 Jenkins 打包, 在打包時使用 shell 腳本更新對應信息(有需要也可以使用其他語言腳本):
1.首先定義需要獲取的文件地址
androidVersionFilePath="$WORKSPACE/android/app/build.gradle" // 通過此文件獲取安卓的版本信息 iosVersionFilePath="$WORKSPACE/ios/veronica/Info.plist" // 通過此文件獲取iOS的版本信息 changeLogPath="$WORKSPACE/change.log" // 將版本更新信息存儲在此文件中
2.通過文件地址, 獲取打完包后的版本信息
getAndroidVersion(){ androidVersion=$(cat $androidVersionFilePath | grep "versionName" | awk '{print $2}' | sed 's/\"http://g') androidCode=$(cat $androidVersionFilePath | grep "versionCode " | awk '{print $2}' | sed 's/\"http://g') androidDelete=$(cat $androidVersionFilePath | grep "deleteApp" | awk '{print $4}' | sed 's/\"http://g') return 0 } getIOSVersion(){ rows=$(awk '/CFBundleShortVersionString/ {getline; print}' $iosVersionFilePath) iosVersion=$(echo "$rows" | sed -ne 's/<string>\(.*\)<\/string>/\1/p') iosVersion=$(echo "$iosVersion" | sed 's/^[[:space:]]*//') rows2=$(awk '/VersionCode/ {getline; print}' $iosVersionFilePath) iosCode=$(echo "$rows2" | sed -ne 's/<string>\(.*\)<\/string>/\1/p') iosCode=$(echo "$iosCode" | sed 's/^[[:space:]]*//') return 0 } desc=$(cat $changeLogPath | tr "\n" "#")
3.替換現有文件中的信息
sed -i '' "s/\"releaseInfo\":.*$/\"releaseInfo\": \"$desc\"/" $JsonPath/$fileName sed -i '' "s/\"versionName\":.*$/\"versionName\": \"$versionName\",/" $JsonPath/$fileName sed -i '' "s/\"versionCode\":.*$/\"versionCode\": \"$versionCode\",/" $JsonPath/$fileName sed -i '' "s/\"deleteApp\":.*$/\"deleteApp\": \"$deleteApp\",/" $JsonPath/$fileName
我的文件是以 json 作為格式的,說明文字是可以任意填寫的,會觸發(fā)一些解析問題:
- 不允許出現會造成 JSON.parse 解析失敗的符號, 如 \ , ````, \n ,\r, \" 等等
- 因為說明文字的換行我是通過 # 切割的, 所以也不允許出現這個符號
大致流程圖
總結
關于 APP 原生版本的更新流程基本就是這樣,當然這個流程不光適用 APP, 也可以用于 PC 軟件的更新
除了原生版本的更新,還有熱更新, 也是非常重要的,
以上就是淺談React原生APP更新的詳細內容,更多關于React原生APP更新的資料請關注腳本之家其它相關文章!
相關文章
jenkins分環(huán)境部署vue/react項目的方法步驟
這篇文章主要介紹了jenkins分環(huán)境部署vue/react項目的方法,本文分步驟給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02在Ant Design Pro登錄功能中集成圖形驗證碼組件的方法步驟
這篇文章主要介紹了在Ant Design Pro登錄功能中集成圖形驗證碼組件的方法步驟,這里的登錄功能其實就是一個表單提交,實現起來也很簡單,具體實例代碼跟隨小編一起看看吧2021-05-05antd-react使用Select組件defaultValue踩的坑及解決
這篇文章主要介紹了antd-react使用Select組件defaultValue踩的坑及解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-05-05