天天看點

React Native釋出APP之簽名打包APK

用React Native開發好APP之後,如何将APP釋出以供使用者使用呢?一款APP的釋出流程無外乎:簽名打包—>釋出到各store這兩大步驟。本文将向大家分享如何簽名打包一款React Native APP。

衆所周知,Android要求所有的APP都需要進行數字簽名後,才能夠被安裝到相應的裝置上。簽名打包一個Android APP已經是每一位Android開發者的家常便飯了。

那麼如何簽名打包一款用React Native開發的APP呢?

既然Android Studio中可以進行APP的簽名打包,那我們可不可以用它進行打包呢,實踐表明用Android Studio打包React Native APP不是一種推薦的方案。

關于打包React Native iOS應用請檢視《React Native釋出APP之打包iOS應用》

為什麼不用Android Studio打包React Native APP?

在發這篇博文前我曾試着用Android Studio打包React Native APP,編譯,打包,安裝各項指數正常,當我欣喜在手機上打開APP看一下效果時,APP在啟動時閃退了。多試幾次依然如此,這時讓我想起每次通過terminal安裝APP到模拟器上時,

launchPackager.command

終端都會輸出

http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false

這樣一行資訊,然後APP在啟動頁加載一會才進入應用。通過浏覽器通路上面的連結,發現連結傳回的是一個js檔案,打開該檔案發現檔案中的代碼其實是我們寫的 React Native 的 JS 代碼。

PS.

1. 在開發環境下,每次啟動APP,都會連接配接JS Server将項目中編寫的js檔案代碼加載到APP(這也是React Native的動态更新的精髓)。

2. 簽名打包後的APK已經從開發環境變成了生産環境,自然不會在每次啟動的時候連接配接JS Server加載相應的js檔案。是以導緻APP因缺少相應的js而無法啟動。

既然Android Stuio打包行不通,那麼我們采用React Native官方推薦的方式進行簽名打包(下文會重點講解“通過官方推薦的方式簽名打包”),打包過程很順利,将打包好的APK安裝到手機上後,發現能正常運作。

對比用Android Studio簽名打包生成的APK與用官方推薦方式簽名打包生成的APK,發現了它們在大小上和内容上都有所差别,如圖:

大小上的差别:

React Native釋出APP之簽名打包APK

對比兩種打包方式發現,它們所生成的apk在大小上相差幾百k。為什麼會相差那麼大呢,帶着這個疑問我們就将兩個apk解壓之後看看他們内部具體有什麼不同。

apk内部差别:

React Native釋出APP之簽名打包APK

上圖是解壓之後apk的内部細節,發現通過官方推薦的方式打包的apk多了兩個檔案“index.android.bundle”與“index.android.bundle.meta”,打開“index.android.bundle”發現其和從

http://localhost:8081/index.android.bundle?platform=android&dev=true&hot=false&minify=false

擷取的檔案内容是一樣的,都是我們寫的 React Native 的 JS 代碼。

結論

1. 在開發環境下,為友善調試,APP會在啟動時從JS Server伺服器将index.android.bundle檔案加載到APP。

2. 簽名打包後的APP變成了生産環境,此時APP會預設從本地加載 index.android.bundle檔案,由于通過Android Studio打包的APK沒有将index.android.bundle打包進apk,是以會因缺少index.android.bundle而無法啟動。

通過官方推薦的方式簽名打包APK

第一步:生成Android簽名證書

如果你已經有簽名證書可以繞過此步驟。

簽名APK需要一個證書用于為APP簽名,生成簽名證書可以Android Studio以可視化的方式生成,也可以使用終端采用指令行的方式生成,需要的可以自行Google這裡不再敖述。

第二步:設定gradle變量

  1. 将你的簽名證書copy到 android/app目錄下。
  2. 編輯

    ~/.gradle/gradle.properties

    ../android/gradle.properties

    (一個是全局

    gradle.properties

    ,一個是項目中的

    gradle.properties

    ,大家可以根據需要進行修改) ,加入如下代碼:
MYAPP_RELEASE_STORE_FILE=your keystore filename  
MYAPP_RELEASE_KEY_ALIAS=your keystore alias  
MYAPP_RELEASE_STORE_PASSWORD=*****    
MYAPP_RELEASE_KEY_PASSWORD=*****  
           

提示:用正确的證書密碼、alias以及key密碼替換掉 *。

第三步:在gradle配置檔案中添加簽名配置

編輯 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  
        }  
    }  
}  
...  
           

第四步:簽名打包APK

terminal進入項目下的android目錄,運作如下代碼:

./gradlew assembleRelease

React Native釋出APP之簽名打包APK

簽名打包成功後你會在 “android/app/build/outputs/apk/”目錄下看到簽名成功後的app-release.apk檔案。

提示:如果你需要對apk進行混淆打包 編輯android/app/build.gradle:

/**     
 * Run Proguard to shrink the Java bytecode in release builds.  
 */  
def enableProguardInReleaseBuilds = true  
           

如何在gradle中不使用明文密碼?

上文中直接将證書密碼以明文的形式寫在了gradle.properties檔案中,雖然可以将此檔案排除在版本控制之外,但也無法保證密碼的安全,下面将向大家分享一種方法避免在gradle中直接使用明文密碼。

通過“鑰匙串通路(Keychain Access)”工具保護密碼安全

下面闡述的方法隻在OS X上可行。

我們可以通過将釋出證書密碼委托在“鑰匙串通路(Keychain Access)”工具中,然後通過gradle通路“鑰匙串通路”工具來獲驗證書密碼。

具體步驟:

  1. cmd+space

    打開“鑰匙串通路(Keychain Access)”工具。
  2. 在登入選項中新鑰匙串,如圖:
    React Native釋出APP之簽名打包APK

提示: 你可以在terminal中運作如下指令檢查建立的鑰匙串是否成功。

security find-generic-password -s android_keystore -w

3. 在build.gradle中通路你的秘鑰串,将下列代碼編輯到android/app/build.gradle中:

def getPassword(String currentUser, String keyChain) {
   def stdout = new ByteArrayOutputStream()
   def stderr = new ByteArrayOutputStream()
   exec {
       commandLine 'security', '-q', 'find-generic-password', '-a', currentUser, '-s', keyChain, '-w'
       standardOutput = stdout
       errorOutput = stderr
       ignoreExitValue true
   }
   //noinspection GroovyAssignabilityCheck
      stdout.toString().trim()
}
           
// Add this line
def pass = getPassword("YOUR_USER_NAME","android_keystore")
...
android {
    ...
    defaultConfig { ... }
    signingConfigs {
        release {
            storeFile file(MYAPP_RELEASE_STORE_FILE)
            storePassword pass // Change this
            keyAlias MYAPP_RELEASE_KEY_ALIAS
            keyPassword pass // Change this
        }
    }
    buildTypes {
        release {
            ...
            signingConfig signingConfigs.release
        }
    }
}
...
           

注意事項

鑰匙串通路(Keychain Access)工具隻是幫我們托管了,證書密碼,證書明和alias還是需要我們在

gradle.properties

中設定一下的。

About

本文出自《React Native學習筆記》系列文章。

了解更多,可以關注我的GitHub

@https://crazycodeboy.github.io/

推薦閱讀

  • React Native高手進階
  • React Native布局詳細指南
  • React Native應用部署、熱更新-CodePush最新內建總結
  • React Native釋出APP之簽名打包APK