Skip to content

Instantly share code, notes, and snippets.

@iocentos
Last active December 18, 2016 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iocentos/cc581206b80a6e28ac7c60ee1a1db3a7 to your computer and use it in GitHub Desktop.
Save iocentos/cc581206b80a6e28ac7c60ee1a1db3a7 to your computer and use it in GitHub Desktop.
#!/usr/bin/python
'''
The following script performs unsupervised apk upload to google play console.
Make sure first to create a service account and store the json file somwhere safe.
It also uploads the mapping.txt file so that we can see crash reports in developer console.
First install google api publisher api
$ pip install google-api-python-client
Create service account for unsupervised api calls and give access to your android application
Invoke like that
python android-publisher.py \
--client-secrets-file /path/to/secrets_file.json \
--mapping-txt-file /path/to/mapping.txt \
--package-name com.package.name \
--apk-file /path/to/app-signed.apk \
--google-play-track {alpha,beta,production} \
--noauth_local_webserver
'''
from __future__ import absolute_import [46/1984]
import argparse
import os
import sys
import httplib2
from googleapiclient import discovery
from oauth2client import client
from oauth2client import file
from oauth2client import tools
from oauth2client.service_account import ServiceAccountCredentials
# Set up arguments
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument("--client-secrets-file", help="File path with client secrets", type=str, required=True)
parser.add_argument("--package-name", help="Package name of android application", type=str, required=True)
parser.add_argument("--apk-file", help="Path to the signed apk file", type=str, required=True)
parser.add_argument("--mapping-txt-file", help="Deobfuscation file generated for the apk", type=str, required=True)
parser.add_argument("--google-play-track",
help="Google play track to publish the application",
type=str,
required=True,
choices=set(("alpha", "beta", "production")))
def authenticate(argv, name, version, doc, filename, scope=None, parents=[], discovery_filename=None):
if scope is None:
scope = 'https://www.googleapis.com/auth/' + name
# Parser command-line arguments.
parent_parsers = [tools.argparser]
parent_parsers.extend(parents)
parser = argparse.ArgumentParser(
description=doc,
formatter_class=argparse.RawDescriptionHelpFormatter,
parents=parent_parsers)
flags = parser.parse_args(argv[1:])
credentials = ServiceAccountCredentials.from_json_keyfile_name( flags.client_secrets_file, [scope])
if credentials is None or credentials.invalid:
credentials = tools.run_flow(flow, storage, flags)
http = credentials.authorize(http = httplib2.Http())
if discovery_filename is None:
# Construct a service object via the discovery service.
service = discovery.build(name, version, http=http)
else:
# Construct a service object using a local discovery document file.
with open(discovery_filename) as discovery_file:
service = discovery.build_from_document(
discovery_file.read(),
base='https://www.googleapis.com/',
http=http)
return (service, flags)
# Main code
def main(argv):
# Authenticate and construct service.
service, flags = authenticate(argv,
'androidpublisher',
'v2',
__doc__,
__file__,
parents=[parser],
scope='https://www.googleapis.com/auth/androidpublisher')
# Process flags and read their values.
package_name = flags.package_name
apk_file = flags.apk_file
google_play_track = flags.google_play_track
mapping_txt_file = flags = flags.mapping_txt_file
try:
edit_request = service.edits().insert(body={}, packageName=package_name)
result = edit_request.execute()
edit_id = result['id']
apk_response = service.edits().apks().upload(
editId=edit_id,
packageName=package_name,
media_body=apk_file).execute()
apk_version_code = apk_response['versionCode']
apk_response = service.edits().deobfuscationfiles().upload(
editId=edit_id,
packageName=package_name,
apkVersionCode=apk_version_code,
deobfuscationFileType="proguard",
media_mime_type="application/octet-stream",
media_body=mapping_txt_file).execute()
print 'Version code %d has been uploaded' % apk_version_code
track_response = service.edits().tracks().update(
editId=edit_id,
track=google_play_track,
packageName=package_name,
body={u'versionCodes': [apk_version_code]}).execute()
print 'Track %s is set for version code(s) %s' % (
track_response['track'], str(track_response['versionCodes']))
commit_request = service.edits().commit(
editId=edit_id, packageName=package_name).execute()
print 'Edit "%s" has been committed' % (commit_request['id'])
except client.AccessTokenRefreshError:
print ('The credentials have been revoked or expired, please re-run the '
'application to re-authorize')
if __name__ == '__main__':
main(sys.argv)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment