Jenkins is an open source software project. It is a Continuous integration tool developed based on Java for monitoring continuous repetitive work. It aims to provide an open and easy to use software platform to make continuous integration of software possible. The content of this paper is to automate the packaging of Android projects by Jenkins, compile APK files by Jenkins running Gradle, upload APK files to Dandelion by Python script, and send notification emails after upload.



Environment: Windows10+Python3.6+Java1.8 software: Jenkins2.89.3+Git2.13.2

Install Jenkins

1. Install files

Download the installation package from the Jenkis official website. The following uses Windows as an example.








java -jar jenkins.war 
Copy the code

The default Jenkins port is 8080. To change the Jenkins port number, run the following command (for example, the Jenkins port number is 9090) :

java -jar jenkins.war  --ajp13Port=-1 --httpPort=9090
Copy the code

You can see Jenkins’ startup information below







After the startup is complete, type in your browser

http://localhost:9090
Copy the code

When you open it for the first time, you will see that you need to fill in the administrator password. The path of the password file has been shown on the web page. Open the text copy and fill in the password in the input box and click the next button.









2. Install the plug-in

After opening the page for the first time, Jenkins will initialize it for a period of time. You can skip the plug-in installation first, because it takes too long to download the plug-in, and then select the required plug-in in [Management Plug-in] in [System Management].










Of course, it is also possible to install the recommended plug-in configuration directly.




Configure Jenkins

1. Configure The Android environment variables

If the Android environment variables have not been configured, you need to configure them. You are advised to configure environment variables in Windows. This can also be configured in Jenkins’ System Settings.


2. Configure Git

Go to Global Tools Configuration and select configure JDK. Since you’ve already installed the JDK, just fill in the name and the path to the environment variable.


3. Configure Git

Go to Global Tool Configuration and select Configure Git. As with the JDK, it is already installed, so only the path is configured.


3. The configuration Gradle

Go to Global Tools Configuration and select Configure Gradle. Select automatic installation and select the Gradle version number.


Create a project

1. Create







Create a new task, fill in the task name, select “Build a Free style software project”, and click “OK”. After the creation, the configuration page of the project is displayed.


2. Configure parameterized Build Process


Parameters allow you to prompt users for one or more inputs that will be passed into a build. For example, you might have a project that runs tests on demand by allowing users to upload a zip file with binaries to be tested. This could be done by adding a File Parameter here. Or you might have a project that releases some software, and you want users to enter release notes that will be uploaded along with the software. This could be done by adding a Multi-line String Parameter here. Each parameter has a Name and some sort of Value, depending on the parameter type. These name-value pairs will be exported as environment variables when the build starts, allowing subsequent parts of the build configuration (such as build steps) to access those values, e.g. by using the ${PARAMETER_NAME} syntax (or %PARAMETER_NAME% on Windows). This also implies that each parameter defined here should have a unique Name.

Here’s the official explanation. This article names these added parameters “Build parameters.” The build parameter acts as a global variable for the component task and can be of different types, such as Boolean or String. You can pass these parameters in when you start a component task and reference them in the task as ${PARAMETER_NAME} or %PARAMETER_NAME%.

For example, if you want to start a task with the option to pull code from different branches, create a construction parameter of type Choice called Branch. The optional parameter is the Branch name in your Git repository. For example: master, sprint1, sprint2. Of course, you can also create the channel name or environment name that the channel APK needs to package.







When the component parameters are configured, the option to select the parameters is provided when the task is started to select a specific run scenario.




3. Configure the Git repository address

Enter your project address in source Control and, if the project requires a password, the account and password for the project to be authorized. If you haven’t added it before, click “Add” to Add it. The build parameters created in the previous step are also available. To configure the branch, the branch of pull code is

*/${BRANCH}
Copy the code


4. Build the configuration

Since you are using Gradle packaging, select “Invoke Gradle Script” in the build.







Then select the Gradle configuration you installed earlier







clean assemble${FLAVORS}${BUILD_TYPE} --stacktrace --debug
Copy the code

${FLAVORS} and ${BUILD_TYPE} are options that you can look forward to writing about. Gradle files correspond to productFlavors and buildTypes. If you don’t need buildTypes and productFlavors, assemble${FLAVORS}${BUILD_TYPE} instead of assembleDebug.

buildTypes {
    release {
        //debuggable = true;
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
    beta {
        debuggable = true;
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
    qa {
        debuggable = true;
        proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        signingConfig signingConfigs.release
    }
}
productFlavors {
    northAmerica {
        applicationId 'xxx'
    }
    china {
        applicationId 'xxx'
    }

}
Copy the code
5. Upload the dandelion configuration

The code to upload dandelion is done using Python scripts. Only the important parts are included here; the entire code can be downloaded in the Demo. Alternatively, you can view the official documentation and upload apK to Dandelion via Jenkins plugin. Considering the flexibility, we decided to upload apK by calling the HTTP interface provided by the official Python script if uploading to the company’s server or other requirements is convenient to modify.

# Jenkins = "C:\ Users\ Flyn\.jenkins\ workspace\ Android App" # Gradle = "C:\ Users\ Flyn\.jenkins\ workspace\ Android App" # Gradle = "C:\ Users\ Flyn\.jenkins\ workspace\ Android App Apk_path = workspace + "\\app\\build\ \apk" BRANCH = sys.argv[1] # parameter BUILD_TYPE = sys.argv[2] # Create type options = Argv [3] # def upload_file(path): parent = os.listdir(path) for parent: child = os.path.join(path, parent) if os.path.isdir(child): upload_file(child) else: if child.endswith(".apk"): Print (child) # Http https://www.pgyer.com/doc/view/api#uploadApp result = requests.post( url="https://www.pgyer.com/apiv2/app/upload", data={"_api_key": "8bc2faf1cea2b0aa0b18465fd3b7ed47", }, files={"file": open(child, "rb")} ) if result.status_code < 300: Response = result.text print(response) # load apK url = "https://www.pgyer.com/" + json.loads(response)['data'][ 'buildShortcutUrl'] print(" "+ url) # Send ("[" + date + "] Android APP "+ BRANCH +" "+ FLAVORS +" "+ BUILD_TYPE +" APK" "+ date + "\n" + "APK download link:" + url, lambda: print(" email sent successfully!!" Lambda: print(" Failed to send mail!!" ) else: print(" ApK file upload failed!! ") )Copy the code

Since it is a Python script, Windows batch processing is required to execute the script. Select Execute Windows Batch Command.







Fill in the Windows execution command and change the path in the code below to the path of your own Python script

py -3 C:\User\Development\my_scripts\APK_upload_scripts\apk_upload.py  %BRANCH%  %BUILD_TYPE%  %FLAVORS%
Copy the code


6. Send emails Using The Python script, but you can also use Jenkins’ built-in Email notification or Email Extension Plugin. The built-in email function still has some drawbacks, such as the inability to customize the content and format of the email. Jenkins can configure Email notification using the Email Extension Plugin by referring to this article, but it still feels cumbersome. Python script can be used for quick configuration and Email sending function. Here is the code that sends the mail to create the mail_sender.py file

from email.mime.text import MIMEText
import smtplib
from email.header import Header

class MailSender(object):
    def __init__(self):
        self.my_name = ''
        self.from_address = ''
        self.password = ''
        self.to_address = ''
        self.smtp_server = ''
        self.smtp_server_port = ''

    def send(self, title: str, content: str, success_callback, failed_callback):
        msg = MIMEText(content, 'plain', 'utf-8')
        from_address = self.my_name + '<' + self.from_address + '>'
        msg['From'] = from_address
        msg['To'] = ", ".join(self.to_address)
        msg['Subject'] = Header(title, 'utf-8')

        server = smtplib.SMTP(self.smtp_server, self.smtp_server_port)
        server.set_debuglevel(1)
        try:
            server.login(self.from_address, self.password)
            server.sendmail(self.from_address, self.to_address, msg.as_string())
            success_callback()
        except Exception as e:
            print(e)
            failed_callback(str(e.args))
        finally:
            server.quit()
Copy the code

Create a config.txt file and read the configuration in the file to get some information about sending the mail

[Info]
my_name = Your name
from_address = your mail
password = your password
to_address = addressee 
smtp_server = email server address
smtp_server_port = email server port 
Copy the code

Call the method that sends the message

mail_sender = MailSender() configparser = configparser.ConfigParser() configparser.read(os.path.dirname(os.path.realpath(__file__)) + '\\config.txt') mail_sender.to_address = configparser.get("Info", "to_address").split(',') mail_sender.from_address = configparser.get("Info", "from_address") mail_sender.my_name = configparser.get("Info", "my_name") mail_sender.password = configparser.get("Info", "password") mail_sender.smtp_server = configparser.get("Info", Smtp_server_port = configParser. get("Info", "smtp_server_port") Send ("[" + date + "] Android APP "+ BRANCH +" "+ FLAVORS +" "+ BUILD_TYPE +" APK" "+ date + "\n" + "APK download link:" + url, lambda: print(" email sent successfully!!" Lambda: print(" Failed to send mail!!" ))Copy the code

Three. Running tasks

Next click on the “Build with Paramerters” button and select the Build parameters to Build.







Click the number and then Consloe Log to view the specific log information

















4. To summarize

It is not difficult to use Jenkins continuous integration, and it is not easy to make mistakes by paying attention to details step by step. Other reference articles are also many, encountered problems are easy to solve. Attached: Project code