Use Gradle and ant implementations to configure automatic packaging for different environments

Source: Internet
Author: User
Tags jcenter build gradle

First, build Jenkins environment and configure Gradle environment
Online construction Jenkins A lot of tutorials, here no longer repeat, the main next Jenkins configuration Gradle environment
Click "Manage Jenkins"
1.Search and install Gradle plugin in "Manage Plugins"
2, in the "
Configure System" configuration point to your computer in the Gradle path (before this step of course to download Gradle)
    

Ii. Create a new Jenkins project and set up the build Gradle configuration item
1, click New Item to create a new Jenkins project
2. Set up configuration Items
A. Configure the directory where SVN code resides
    
B, configure the Execute gradle command (note "Invoke gradle script" is seen in the "Build" Construction item by clicking "Add Build Step" in the Jenkins installation of the Gradle plug-in) Invoke Gradle script)
    

as a few steps after the implementation of Gradle most basic packaging (output apk path app/build/outputs/apk/xxxx.apk)

Configure ant script to modify environment-related configuration item code (modify Jenkins project source)
According to the information on the web search, You can modify your project in the task of the Build.gradle script. Java code, but do not see a large number of changes in the source code and very convenient practices, for the current project team to modify the environment in the context of multiple sources, or use ant to specialize in the modification of the source, two ways:
1, Jenkin's "Add Build Step" can first invoke "Invoke Ant" and "Invoke Gradle script"
2, Build.gradle in the introduction of ant script (this method is a disadvantage is not in the "Invoke Ant" dynamic changes in the properties of the source code)
Ant.importbuild '.. /power-gradle.xml '

The ant foot modifies the source steps as follows:
A, AppConfig. Java source Code

Package com.demo.project;
public class AppConfig {
    /**
     * 
     * * Open debug
    /public static Boolean isdebug = true;
    /**
     * Configuration is used for testing/public
     static Boolean istest = true;
}

B, Before-gradle.xml script

<?xml version= "1.0" encoding= "UTF-8"?> <project name= "Demoproject" basedir= "." default= "release" > <!-- "One", start Project source code directory--> <property name= "src" value= "app/src"/> <property name= "Res value=" App/src/mai N/res "/> <!--" One ", end project source code directory--> <!--" II ", start file modification related to file name and path statement--> <property name=" AppC Onfig "value=" ${src}/main/java/com/demo/project/appconfig.java "/> <!--" II, end file modification related to file name and path statement--> & lt;!
    --"Three", start in Jenkins Ant property properties Configure different values according to requirements--> <!--1, appconfig file--> <!--isdebug, default false--> <property name= "Isdebug" value= "false"/> <property name= "Isdebug-pattern" value= "Isdebug () *= () *.*" >& lt;/property> <property name= "Replace-isdebug-pattern" value= "isdebug = ${isdebug};"/> <!--isTest, tacitly True--> <property name= "Istest" value= "true"/> <property name= "Istest-pattern" value= () isTest ( ) *.* "></property> <property name= "Replace-istest-pattern" value= "istest = ${istest};"/> <!--"Three", End in Jenkins ant property P Roperties configure different values according to requirements--> <target name= "Init" > <echo> 1, setting AppConfig file accord ant Proper Ties</echo> <!--turn off the debug--> <echo>replace isdebug to ${isdebug}</echo> &L T;replaceregexp file= "${appconfig}" match= "${isdebug-pattern}" replace= "${replace-isdebug-pattern}" byline= "true" flags= "GS" encoding= "Utf-8"/> <!--can choose environment--> <echo>replace istest to ${istest}</echo&
        Gt <replaceregexp file= "${appconfig}" match= "${istest-pattern}" replace= "${replace-istest-pattern}" byline= "true" flags= "GS" encoding= "Utf-8"/> </target> <target name= "release" depends= "Init" > &LT;ECHO&G
 T;ant Prepare for release</echo> </target> </project>

C, Jenkins in the configuration.
  

==> The above steps can be set to Istest False,isdebug set to False, to perform the construction can come out of the corresponding code configuration APK

v. Import signature files Externally
Specially creates a new file to hold the signature related KeyStore the path and the signature password, said purple is relatively safe.
1, in Build.gradle

Signingconfigs {
        //External file Mode import signature
        def Properties props = new Properties ()
        def propfile = new File (' Signing.properties ')
        if (propsfile.exists () && propfile.canread ()) {
            props.load (new FileInputStream (propfile))

            Signingconfigs {release
                {
                    storefile file (props[' StoreFile '])
                    storepassword props[' Storepassword ']
                    keyalias props[' Keyalias ']
                    keypassword props[' Keypassword '}
                }
            }
    

2, in Signing.properties. New file under the project directory

KeyStore absolute path
storefile=c:\\demo\\project\\demo.keystore
storepassword=123456
keypassword=123456
Keyalias=demo

six, multi-channel packaging
1, Androidmanifest.xml

<meta-data android:name= "channel_id" android:value= "${channel_id_value}"/>

2, Build.gradle
A, mode one:

Productflavors {//multi-channel packaging, command-line packaging: Gradle assemblerelease
    Xiaomi {/
/        ApplicationID ' xiaomirelease '//comments, Default Xiaomirelease and Xiaomidebug
          manifestplaceholders.put ("Channel_id_value", ' Xiaomi ')
     }
    googlepaly {
//        ApplicationID ' googlepalyrelease '  //default googlepalyrelease and Googlepalydebug
          Manifestplaceholders.put ("Channel_id_value", ' Googlepaly ')
     }
}

A, mode two:

productflavors {
    xiaomi{}
    googleplay{} 

    productflavors.all {flavor->
        Flavor.manifestplaceholders = [Channel_id_value:name]//name value is Xiaomi/googleplay
    }

}

3. Packing Order
Gradle environment variables are configured in the computer
1, Gradle clean build-b./build.gradle Build All Packages
    
2, Gradle assemblerelease build all channel release package
3, Gradle assemble[xxx]release build a single channel to publish the package.
such as: Gradle assemblexiaomirelease or Gradle assemblegooglepalyrelease, and other channel names related to release order

4, to see if the channel changes with the configuration. View the value of channel_id in Androidmanifest.xml in the following diagram directory Xiaomi/googleplay

5, copy apk to the directory APKs directory. Because the above release of the package level is too deep, not convenient for testers on the Jenkins to find download apk, all this step will be./app/build/outputs/apk all xx.apk under Demoproject directory

The copy output apk to the APKs directory
task CopyFiles (type:copy) {
    description = ' Copy APKs to project directory './apks '
    fr Om ' build/outputs/apk ' into
    '.
such as: Gradle assemblexiaomirelease)
//build builds the package. That CopyFiles task is dependent on Assemblerelease/assemblexiaomirelease/build
Assemblerelease.dependson copyFiles

Complete Build.gradle Script

Apply plugin: ' com.android.application ' import java.util.regex.Pattern////get verbose time def buildtime () {return new Date () . Format ("YyyyMMdd '-' HHmm", Timezone.getdefault ())}//Get date def builddate () {return new date (). Format ("YyyyMMdd", Time Zone.getdefault ())} android {compilesdkversion buildtoolsversion "23.0.2" Defaultconfig {appli Cationid "Com.demo.project" Minsdkversion 8 targetsdkversion 8 multidexenabled true} SOU            Rcesets {main {//Manifest.srcfile ' androidmanifest.xml '//java.srcdirs = [' src ']//            Resources.srcdirs = [' src ']//aidl.srcdirs = [' src ']///renderscript.srcdirs = [' src ']// 
        Res.srcdirs = [' res ']//assets.srcdirs = [' assets '] jnilibs.srcdirs = [' libs ']//Specify JNI Path            }//Signature Signingconfigs {release {//StoreFile file (' Release.keystore ')// Storepassword ' 123456 '//Keyalias ' demo '//Keypassword ' 111111 '} buildtypes {release { Whether to confuse switch minifyenabled false//whether zip-aligned zipalignenabled true//Yes
            No open debuggable switch debuggable false/Open jnidebuggable switch jnidebuggable false Confusing configuration file Proguardfiles getdefaultproguardfile (' proguard-android.txt '), ' proguard-rules.txt '//signature matching Signingconfig///signingconfigs.release////release release version for multi-channel.                Equivalent to omitting multiple manifestplaceholders.put ("Channel_id_value", ' Xiaomi ')//Productflavors.all {flavor->// Manifestplaceholders.put ("Channel_id_value", name)//name equals Xiaomi/googlepaly//}}} L intoptions {//lint Check, there are any errors or warning prompts, will terminate the build. False is to turn off lint//In the package release version of the time to detect, you can open, so the error will also show up checkreleasebuilds false//abortonerror must be set to FAL Se so that you don't stop packing even if you have an errorAbortonerror false} productflavors {//multi-channel packaging, command line packaging: Gradlew assemblerelease Xiaomi {// ApplicationID ' xiaomirelease '//annotated words, default xiaomirelease and Xiaomidebug manifestplaceholders.put ("Channel_id_value" , ' Xiaomi ')} googlepaly {//ApplicationID ' googlepalyrelease '//default Googlepalyrelease and Googlepa Lydebug manifestplaceholders.put ("Channel_id_value", ' Googlepaly ')}} Android.applicationvari Ants.all {Variant-> def manifestfile = File ("Src/main/androidmanifest.xml") def pattern = pattern.com Pile ("versionname=\" (. +) \ "") def Manifesttext = Manifestfile.gettext () def matcher = Pattern.matcher (manif Esttext) Matcher.find ()//Get versionname def versionname = matcher.group (1) pattern = Patte Rn.compile ("Versioncode=\" (. +) \ "") Matcher = Pattern.matcher (manifesttext) Matcher.find ()//Get Vers Ioncode def versIoncode = Matcher.group (1) if (variant.buildType.name.equals (' release ')) {variant.outputs.each {out Put-> def outputfile = Output.outputfile if (outputfile!= null && outputfile. Name.endswith ('. apk ')) {//Def fileName = "Gradle4android_v${defaultconfig.versionname}_${releasetime" ( )}_${variant.flavorname}.apk "Def fileName = builddate () +"/"+ ApplicationID +"-V "+ Versionname + "-" + Variant.name + "-" + buildtime () + "-" + Variant.flavorname + ". apk" output.outputfile = new Fil E (Outputfile.parent, FileName)}}} else {variant.outputs.each {output -> def outputfile = Output.outputfile if (outputfile!= null && outputfile.name . EndsWith ('. apk ')) {def fileName = builddate () + "/" + ApplicationID + "-V" + versionname + "-" + var Iant.name + "-" + BuildtIME () + "-unaligned.apk" output.outputfile = new File (outputfile.parent, FileName)} }}///Copy output APK to APKs directory task CopyFiles (type:copy) {description = ' copy APKs to Proje in the project directory CT directory./apks ' from ' build/outputs/apk ' into '. /apks '//Because the default './' in app directory include (' **/* ')//Copy all}/////According to the command line is to build all channels Gradle assemblerelease, a single channel package (such as: Gradle Assemblexiaomir Elease)//or build builds the package.
    That is, the CopyFiles task is dependent on the Assemblerelease/assemblexiaomirelease/build Assemblerelease.dependson copyFiles dependencies {
 Compile Filetree (include: [' *.jar '], dir: ' Libs ')}

Gradle in a multi-channel package with super advantage, after the explosion ant; As on the script Gradle dozen 2 packs on the brother Mac only need 35-50s, pure ant script to play a package 2min ...
  

Problem Solving:
1,

Could not resolve all dependencies for configuration ': Classpath '.
Could not resolve com.android.tools.build:gradle:1.5.0.
Required by:
:D emoproject:unspecified
Could not get ' https://jcenter.bintray.com/com/android/tools/build/gradle/1.5.0/gradle-1.5.0.pom '.
Connection to Https://jcenter.bintray.com refused
The solution is to reduce the version required in the code classpath ' com.android.tools.build:gradle:1.3.0 '

2, Gradle compilation speed is very slow

Add –offline to the command line. such as: gradle assemble--offline,gradle clean--offline
Gradle-tool is the Gradle tool that executes the Gradle Bin directory (window is Gradle.bat,unix system is gradle)

  <target name= "clean" depends= "xxx" >
       <echo>gradle clean--offline</echo>
       <exec Executable= "${gradle-tool}" failonerror= "true" >
           <arg value= "clean"/> <arg value=
        "--offline"/ >
       </exec>
   </target>


Reference:
1, http://doc.okbase.net/tanlon/archive/125036.html
2, http://www.jianshu.com/p/aa7f93d29805
3, multi-channel Packaging: http://mp.weixin.qq.com/s?__biz=MzI4MzE2MTQ5Mw==&mid=402123825&idx=1&sn= 404bdcfd65b6da9a9058260a753b6b55#rd
4. Complete script: https://github.com/WuXiaolong/Gradle4Android
5, Gradle series: Http://gold.xitu.io/#/tag/gradle
6, http://blog.csdn.net/shanlianting/article/details/49820607
7, http://blog.csdn.net/changemyself/article/details/39927381
8, "Gradle build a slow resolution of the compilation Speed" http://www.52codes.net/article/658.html

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.