Operations 6 min read

Android CI/CD Pipeline with Jenkins and Automated APK Upload to Fir.im and Pgyer

This guide explains how to configure an Android project, write Python upload scripts for Fir.im and Pgyer, create a Jenkinsfile with checkout, build, and upload stages, set up Jenkins global variables and pipeline parameters, and run a full build‑test cycle to publish APKs via QR codes.

DevOps Cloud Academy
DevOps Cloud Academy
DevOps Cloud Academy
Android CI/CD Pipeline with Jenkins and Automated APK Upload to Fir.im and Pgyer

1. Project configuration: define the package storage path (app/build/outputs/apk/[debug|release]) and create upload scripts that support both Fir.im and Pgyer platforms.

1.2 Upload script (Python) – reference the Fir.im and Pgyer API documentation, obtain the upload certificate from cert.binary , and upload the APK using HTTP POST requests.

#coding:utf8

import requests
import sys
import json

from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

class ApkManage(object):
    def __init__(self):
        self.url = "http://api.fir.im/apps"

    def getCert(self):
        dataargs = {'type' : 'android',
                    'bundle_id' : bundleid,
                    'api_token' : apitoken}
        response = requests.post(self.url,data=dataargs)
        cert = json.loads(response.text)
        return cert['cert']['binary']

    def uploadFir(self):
        certdata = self.getCert()
        try:
            print("upload apk to fir......")
            apkfile = {'file' : open(apkpath,'rb')}
            params = {"key"   : certdata['key'],
                      "token" : certdata['token'],
                      "x:name": appname ,
                      "x:build" : buildid,
                      "x:version" : appversion}
            response = requests.post(certdata['upload_url'],files=apkfile,data=params,verify=False)
            print(response.text)
            if int(response.status_code) == 200 :
                print("upload success!  return -->" + str(response.status_code))
            else:
                print("upload error! return -->" + str(response.status_code))
        except Exception as e:
            print("error: " + str(e))

    def uploadPgyer(self):
        url = 'https://qiniu-storage.pgyer.com/apiv1/app/upload'
        try:
            apkfile = {'file' : open(apkpath,'rb')}
            params = {"uKey" : '7b70873bb4d6xxxxx1d2ae5',
                      "_api_key" : 'a9acab611e1xxxxxxx5cae360a5ab'}
            response = requests.post(url,files=apkfile,data=params,verify=False)
            qrcodes = json.loads(response.text)['data']['appQRCodeURL']
            if int(response.status_code) == 200 :
                print(qrcodes)
            else:
                print("upload error! return -->" + str(response.status_code))
        except Exception as e:
            raise

if __name__ == '__main__':
    bundleid = sys.argv[1]
    apitoken = sys.argv[2]
    apkpath = sys.argv[3]
    appname = sys.argv[4]
    buildid = sys.argv[5]
    appversion = sys.argv[6]
    platform= sys.argv[7]

    server = ApkManage()

    if platform == 'fir':
        server.uploadFir()
    elif platform == 'pgyer':
        server.uploadPgyer()

Usage example:

python upapk.py demo-android-app-10 65d7edxxxxxxx7c4fabda25 app.apk demo-android-app 10 10.12 fir

1.3 Jenkinsfile: defines three stages – Checkout (retrieve code), Build (run Gradle to assemble the APK), and Upload (rename the APK and invoke the Python upload script).

node("master"){
  stage("Checkout"){
    checkout scm
  }

  stage("Build"){
    sh 'chmod +x ./gradlew '
    sh " ${params.buildShell} "
  }
  
  stage("Upload"){
      sh "mv app/build/outputs/apk/debug/app-debug.apk ./${params.apkName}.apk"
      def result
      result = sh returnStdout: true, script: """python uploadapk.py ${params.bundleId} \
                                                 ${params.apiToken} "${params.apkName}.apk" \
                                                 "${params.apkName}" "${BUILD_ID}" \
                                                 "${params.apkVersion}" "${params.appPlatform}" """
      result = result - "\n"
      println(result)
      currentBuild.description="
"
  }
}

2. Jenkins configuration: add a global Android SDK variable via System Settings, create a pipeline, and configure parameters such as buildShell (debug or release Gradle commands), bundleId , apiToken , apkVersion , and apkName .

4. Build test: demonstrates the steps of checking out the code, building the APK, and publishing it to Fir.im and Pgyer, with QR code screenshots for each platform.

PythonCI/CDAndroidautomationDevOpsAPKJenkins
DevOps Cloud Academy
Written by

DevOps Cloud Academy

Exploring industry DevOps practices and technical expertise.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.