Upload apk or bundle to Google Play via command line script

version 2 with Kotlin

Paweł Szymański
3 min readMay 5, 2020

In short:

  • Create a service account and get its authorization data json file.
  • Make a script uses above json and Google Play Developer API to perform actions on your account.

Prerequisites:

  • You can login as an owner of a Google Play Account.
  • You can make Kotlin code. Android Studio is good enough. You can create a pure Kotlin non-Android module and then run it.

Step 1. Create a service account and get access keys json file

  • Open Google Play console. Go to “Settings” > “Developer account” > “API access”.
  • In “Service Accounts” section, choose “Create Service Account”.
  • You will be sent to “Google Cloud Plaform” console. Continue creating account there.
  • Give it a chosen name and ID.
  • Set “Service Account User” role.
  • Create private key and download it as a json file. We’ll use it later.
  • No need to grant any additional access here.
  • Copy e-mail of a created user. Should look like some_id@api-12345–12345.iam.gserviceaccount.com
  • Return to “Service Accounts” in Google Play. Created account should be visible there. If not, invite it using saved e-mail.
  • Press “Grant Access” button next to your service account and allow it to upload apks. When finished choosing permissions, press “add”.

Another description of this process (“Create Google service account” section):
https://plugins.jenkins.io/google-play-android-publisher

Step 2. Create a Kotlin code that can log you in and upload apk/bundle

Create a Kotlin code that can do it using Google API libraries

Full example:
https://github.com/stasheq/google-play-apk-upload

Dependencies

plugins {
id("kotlin")
id("application")
}

application {
mainClassName = "me.szymanski.apkupload.Main"
}

dependencies {
implementation("com.google.auth:google-auth-library-oauth2-http:0.22.0")
implementation("com.google.apis:google-api-services-androidpublisher:v3-rev20201022-1.30.10")
}

Uploading function

private fun setHttpTimeout(requestInitializer: HttpRequestInitializer): HttpRequestInitializer {
return HttpRequestInitializer { request ->
requestInitializer.initialize(request)
request.connectTimeout = 3 * 60000
request.readTimeout = 3 * 60000
}
}

private fun uploadApk(appId: String, apkPath: String, credentialsPath: String) {
val credentials = ServiceAccountCredentials
.fromStream(FileInputStream(credentialsPath))
.createScoped(AndroidPublisherScopes.all())

val publisher = AndroidPublisher.Builder(
GoogleNetHttpTransport.newTrustedTransport(),
JacksonFactory.getDefaultInstance(),
setHttpTimeout(HttpCredentialsAdapter(credentials))
).setApplicationName("Google Play APK upload").build()

val edit: AppEdit = publisher.edits().insert(appId, null).execute()

println("Created edit: ${edit.id}")

// can use publisher.edits().apks()
val apk: Bundle = publisher.edits().bundles().upload(
appId,
edit.id,
FileContent("application/octet-stream", File(apkPath))
).execute()

println("Uploaded apk versionCode: ${apk.versionCode}")

publisher.edits().commit(appId, edit.id).execute()
println("Committed edit with a new apk")
}

Sources of my knowledge:
https://github.com/googleapis/google-api-java-client-services
https://github.com/googleapis/google-auth-library-java

Step 3. Use above code to upload apk/bundle from console

Compile app created above.
If used above github example, command will look like below.

cd ./google-play-apk-upload/
./gradlew apk_upload:installDist
cd apk_upload/build/install/apk_upload/bin

installDist is a command building this app.

Run with your params: app id, apk path, json credentials file created before. In below example all these files are in the same folder as executable file.

./apk_upload my.test.app.id app-release.aab api-12345.json

Success! App is now visible in Artifact Library.

My use case was to upload it there, without publishing it. It can be now used to create a release etc.
For your specific use case, check API reference for all available actions.

Full API reference, including above commands:
https://developers.google.com/android-publisher/api-ref/

--

--