Android 使用gradle打包的各種配置

在AS中利用gradle打包,可以高效並且自由地配置各種參數,發佈不同的版本。關於配置gradle文件的一些做法,總結爲如下。
一.替換AndroidManifest中的佔位符

舉個例子,在AndroidManifest文件中,我們將極光推送的key值指定爲一個佔位符

<!-- 極光KEY -->
<meta-data    
  android:name="JPUSH_APPKEY"   
  android:value="${JPUSH_APPKEY}" />

在build.gradle文件中,這裏介紹3種方法去替換該佔位符
1.接收gradlew assemble命令輸入的自定義參數的值

manifestPlaceholders = [        
            // 默認是正式的極光key        
            JPUSH_APPKEY: "\"" + JPUSH_APPKEY_PARA + "\""
]

2.使用string文件的值

manifestPlaceholders = [JPUSH_APPKEY:"@string/JPUSH_APPKEY"]

二.獨立配置簽名信息

簽名相關的信息,直接寫在gradle不利於安全,我們可以把這些信息寫到工程主module根目錄下的signing.properties文件,注意這個文件不要添加進版本控制。

KEYSTORE_FILE=你的keystore文件位置
KEYSTORE_PASSWORD= 你的keystore文件密碼
KEY_ALIAS= 你的keystore文件用到的別名
KEY_PASSWORD= 你的keystore文件用到的別名的密碼

然後在build.gradle中加載這個文件,引用其中的參數就可以了

//加載簽名配置的文件
Properties props = new Properties()props.load(new
FileInputStream(file("signing.properties")))
android {
  signingConfigs {    
    release{        
        //設置release的簽名信息       
        keyAlias props['KEY_ALIAS']        
        keyPassword props['KEY_PASSWORD']        
        storeFile file(props['KEYSTORE_FILE'])        
        storePassword props['KEYSTORE_PASSWORD']    
    }
  }

...

  buildTypes {
      debug {
        ...
        signingConfig signingConfigs.release}
      }
      ...    
      release {
        ...
        signingConfig signingConfigs.release}
    }
  }
}

三. 多渠道打包
國內應用市場非常多,爲了統計各個應用市場的app下載量和使用情況,我們需要多渠道的打包。

1.配置AndroidManifest.xml
以友盟渠道爲例,渠道信息一般都是寫在 AndroidManifest.xml文件中:

<meta-data android:name="UMENG_CHANNEL" android:value="xiaomi" />

如果不使用多渠道打包方法,那就需要我們手動一個一個去修改value中的值,xiaomi,360,qq,wandoujia等等。使用多渠道打包的方式,就需要把上面的value配置成下面的方式:

<meta-data android:name="UMENG_CHANNEL" android:value="${UMENG_CHANNEL_VALUE}" />

其中${UMENG_CHANNEL_VALUE}中的值就是你在gradle中自定義配置的值。

2.在build.gradle設置productFlavors
寫法如下:

productFlavors { 
  wandoujia  { 
    manifestPlaceholders = [UMENG_CHANNEL_VALUE: "wandoujia"] 
  } 
  xiaomi  { 
    manifestPlaceholders = [UMENG_CHANNEL_VALUE: "xiaomi"] 
  }
  qq  { 
    manifestPlaceholders = [UMENG_CHANNEL_VALUE: "qq"] 
  } 
  360  { 
    manifestPlaceholders = [UMENG_CHANNEL_VALUE: "360"] 
  }
}

其中[UMENG_CHANNEL_VALUE: “wandoujia”]就是對應
${UMENG_CHANNEL_VALUE}的值。這裏還有簡潔的寫法:

android {
  ...

  buildTypes {
      debug {
        ...
      }
      ...    
      release {
        ...
        productFlavors { 
            wandoujia{} 
            xiaomi{} 
            qq{} 
            360 {} 
        } 
        productFlavors.all { flavor -> flavor.manifestPlaceholders = [UMENG_CHANNEL_VALUE: name] 
      }
    }
}

其中name的值對相對應各個productFlavors的選項值,這樣就達到自動替換渠道值的目的了。這樣(用AS自帶工具Generate signed apk)生成apk時,選擇相應的Flavors來生成指定渠道的包就可以了,而且生成的apk會自動幫你加上相應渠道的後綴。

3.一次生成所有渠道包
使用CMD命令,進入到項目所在的目錄,直接輸入命令:

gradle assembleRelease

就可以打Release包,或者,在Android Studio中的下方底欄中有個命令行工具Terminal,你也可以直接打開,輸入上面的命令,進行打包。

注意:如果沒有對gradle配置的話,可能輸入上面的命令,會提示“不是內部或者外部命令”,不要着急,我們只需要找到gradle的目錄,把它配置到電腦中的環境變量中去即可。

配置方式如下:

先找到gralde的根目錄,在系統變量裏添加兩個環境變量:

變量名爲:GRADLE_HOME,變量值就爲gradle的根目錄;

比如變量值爲:
D:androidandroid-studio-ide-143.2739321-windowsandroid-studiogradlegradle-2.10

還有一個在系統變量裏PATH裏面添加gradle的bin目錄

比如:
D:androidandroid-studio-ide-143.2739321-windowsandroid-studiogradlegradle-2.10bin

這樣就配置完了,執行以下這個命令:gradle assembleRelease,看看是不是可以了。
4.修改導出包的文件目錄和apk名稱

// 定義一個打包時間
def releaseTime() {    
      return new Date().format("yyyyMMdd", TimeZone.getTimeZone("UTC"))
}

android {
  ...

  buildTypes {
      debug {
        ...
      }
      ...    
      release {
        ...
        applicationVariants.all { 
            variant ->    variant.outputs.each { output ->        
                def outputFile = output.outputFile        
                if (outputFile != null && outputFile.name.endsWith('.apk')) {           
                    // 輸出apk名稱爲XXX20160328_v1.0.0_vc10_XXXX_test.apk        
                    if (project.hasProperty('ENVIRONMENT_PARA') 
                    def fileName=" XXX${releaseTime()}_v${defaultConfig.versionName}_vc${defaultConfig.versionCode}_${variant.productFlavors[0].name}_${ENVIRONMENT_PARA}.apk"                  
                    //控制輸出的APK的存放路徑                
                    if (project.hasProperty('OUT_PUT_DIR_PARA')) {                    
                        File output_dir1 = file("${OUT_PUT_DIR_PARA}");                    
                        output.outputFile = new File(output_dir1, fileName)                    
                         println "輸出文件位置: " + output.outputFile                
                    } else {                    
                        output.outputFile = new File(outputFile.parent, fileName)                    
                        println "輸出文件位置: " + output.outputFile                
                    }            
                }        
            }    
        }
      }
  }
}

當升級sdk、build tool、target sdk等,幾個module都要更改,非常的麻煩。也可能導致app module之間的差異不統一,導致不可控。強大的gradle插件在1.1.0之後支持全局變量設定,一舉解決了這個問題。先在project的根目錄下的build.gradle定義ext全局變量:

ext { 
  compileSdkVersion = 22 
  buildToolsVersion = "23.0.1" 
  minSdkVersion = 10 
  targetSdkVersion = 22 
  versionCode = 34 
  versionName = "v2.6.1"
}

然後在各module的build.gradle中引用如下:

android { 
  compileSdkVersion rootProject.ext.compileSdkVersion 
  buildToolsVersion rootProject.ext.buildToolsVersion 

  defaultConfig { 
    applicationId "com.xxx.xxx" 
    minSdkVersion rootProject.ext.minSdkVersion 
    targetSdkVersion rootProject.ext.targetSdkVersion 
    versionCode rootProject.ext.versionCode 
    versionName rootProject.ext.versionName 
  }
}

每次修改project級別的build.gradle即可實現全局統一配置。
五.混淆代碼

release版本開啓混淆

//混淆編譯
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

混淆文件可以參考這篇文章進行配置Android代碼混淆在AS的實踐
六.動態設置一些額外信息

把當前的編譯時間、編譯的機器、最新的commit版本添加到apk

android { 
  defaultConfig { 
      resValue "string", "build_time", buildTime() 
      resValue "string", "build_host", hostName() 
      resValue "string", "build_revision", revision() 
  }
}

def buildTime() { 
      return new Date().format("yyyy-MM-dd HH:mm:ss")
}

def hostName() { 
      return System.getProperty("user.name") + "@" + InetAddress.localHost.hostName
}

def revision() { 
      def code = new ByteArrayOutputStream() 
      exec { 
        commandLine 'git', 'rev-parse', '--short', 'HEAD' 
        standardOutput = code 
      } 
      return code.toString()
}

上述代碼實現了動態的添加了3個字符串資源: build_time、build_host、build_revision, 然後在其他地方可像如引用字符串一樣使用如下:

// 在Activity裏調用
getString(R.string.build_time) // 輸出2016-09-07 17:01
getString(R.string.build_host) // 輸出電腦的用戶名和PC
getString(R.string.build_revision) // 輸出3dd5823, 這是最後一次commit的sha值

七.buildConfigField自定義配置

大家可能會遇到下面這種情況,就是Beta版本服務器和Release版本服務器通常不在一臺服務器上,而測試希望可以同時發佈兩個服務器的版本用於測試,這個時候我們就需要修改代碼,然後一個一個老老實實的發包。gradle提供buildConfigField配合多渠道打不同服務器版本的方法。其實用法很簡單,首先在相應的節點加上定義,比如:

buildTypes { 
  debug { 
    buildConfigField "boolean", "LOG_DEBUG", "true"//是否輸出LOG信息   
    buildConfigField "String", "API_HOST", "\"http://api.test.com\""//API Host 
  } 
}

然後在代碼中通過BuildConfig.LOG_DEBUG或者BuildConfig.API_HOST調用即可。
八.dex突破65535的限制

隨着項目的一天天變大,慢慢的都會遇到單個dex最多65535個方法數的瓶頸,如果是ANT構建的項目就會比較麻煩,但是Gradle已經幫我們處理好了,而添加的方法也很簡單,總共就分三步 :
1.首先是在defaultConfig節點使能多DEX功能

android { 
  defaultConfig { 
      // dex突破65535的限制 
      multiDexEnabled true 
  } 
}

2.然後就是引入multidex庫文件

dependencies { 
  compile 'com.android.support:multidex:1.0.0' 
}

3.最後就是你的AppApplication繼承一下MultiDexApplication即可。
九.在gradle.properties文件中配置服務器生產環境和正式環境的地址、第三方服務appkey以及對於包名的配置

項目中加入用到一些第三方的SDK的話,就避免不了各種key的寫入,一般都會有生產環境和正式環境各自使用的值
gradle.properties如下:

極光推送的測試key

JPUSH_APPKEY_VALUE_DEBUG=111111111111111111

極光推送的正式key

JPUSH_APPKEY_VALUE_RELEASE=111111111111111111

極光推送的測試key對應的包名

APPLICATIONID_JPUSH=com.xxx.xxx

極光推送的正式key對應的包名

APPLICATIONID_RELEASE=com.xxx.xxx

測試環境地址

BASE_URL_TEST=

正式環境地址

BASE_URL_REAL=

在build.gradle文件中引用,

defaultConfig {
  if (project.hasProperty('JPUSH_APPKEY_PARA')) {    
    //如果有指定極光key的自定義參數,那麼就設置極光推送測試key對應的appId
    applicationId project.APPLICATIONID_JPUSH
  } else {    
    //工程本來的appId    
    applicationId project.APPLICATIONID_RELEASE
  }

   manifestPlaceholders = [                
      // 默認是正式的極光key
      JPUSH_APPKEY: project.JPUSH_APPKEY_VALUE_RELEASE        
  ]
}

也可配合buildConfigField自定義配置:

buildConfigField("String", "BASE_URL", "\"" + project.BASE_URL_TEST + "\"")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章