├── LICENSE
└── v3
├── java
├── .gitignore
├── README.md
└── src
│ ├── com
│ └── google
│ │ └── play
│ │ └── developerapi
│ │ └── samples
│ │ ├── AndroidPublisherHelper.java
│ │ ├── ApplicationConfig.java
│ │ ├── BasicUploadApk.java
│ │ ├── ListApks.java
│ │ ├── UpdateListing.java
│ │ └── UploadApkWithListing.java
│ └── resources
│ └── client_secrets.json
└── python
├── README.md
├── basic_list_apks.py
├── basic_list_apks_service_account.py
├── basic_upload_apks.py
├── client_secrets.json
├── update_listings.py
├── upload_apks_rollout.py
└── upload_apks_with_listing.py
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction, and
10 | distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by the copyright
13 | owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all other entities
16 | that control, are controlled by, or are under common control with that entity.
17 | For the purposes of this definition, "control" means (i) the power, direct or
18 | indirect, to cause the direction or management of such entity, whether by
19 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
20 | outstanding shares, or (iii) beneficial ownership of such entity.
21 |
22 | "You" (or "Your") shall mean an individual or Legal Entity exercising
23 | permissions granted by this License.
24 |
25 | "Source" form shall mean the preferred form for making modifications, including
26 | but not limited to software source code, documentation source, and configuration
27 | files.
28 |
29 | "Object" form shall mean any form resulting from mechanical transformation or
30 | translation of a Source form, including but not limited to compiled object code,
31 | generated documentation, and conversions to other media types.
32 |
33 | "Work" shall mean the work of authorship, whether in Source or Object form, made
34 | available under the License, as indicated by a copyright notice that is included
35 | in or attached to the work (an example is provided in the Appendix below).
36 |
37 | "Derivative Works" shall mean any work, whether in Source or Object form, that
38 | is based on (or derived from) the Work and for which the editorial revisions,
39 | annotations, elaborations, or other modifications represent, as a whole, an
40 | original work of authorship. For the purposes of this License, Derivative Works
41 | shall not include works that remain separable from, or merely link (or bind by
42 | name) to the interfaces of, the Work and Derivative Works thereof.
43 |
44 | "Contribution" shall mean any work of authorship, including the original version
45 | of the Work and any modifications or additions to that Work or Derivative Works
46 | thereof, that is intentionally submitted to Licensor for inclusion in the Work
47 | by the copyright owner or by an individual or Legal Entity authorized to submit
48 | on behalf of the copyright owner. For the purposes of this definition,
49 | "submitted" means any form of electronic, verbal, or written communication sent
50 | to the Licensor or its representatives, including but not limited to
51 | communication on electronic mailing lists, source code control systems, and
52 | issue tracking systems that are managed by, or on behalf of, the Licensor for
53 | the purpose of discussing and improving the Work, but excluding communication
54 | that is conspicuously marked or otherwise designated in writing by the copyright
55 | owner as "Not a Contribution."
56 |
57 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf
58 | of whom a Contribution has been received by Licensor and subsequently
59 | incorporated within the Work.
60 |
61 | 2. Grant of Copyright License.
62 |
63 | Subject to the terms and conditions of this License, each Contributor hereby
64 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
65 | irrevocable copyright license to reproduce, prepare Derivative Works of,
66 | publicly display, publicly perform, sublicense, and distribute the Work and such
67 | Derivative Works in Source or Object form.
68 |
69 | 3. Grant of Patent License.
70 |
71 | Subject to the terms and conditions of this License, each Contributor hereby
72 | grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
73 | irrevocable (except as stated in this section) patent license to make, have
74 | made, use, offer to sell, sell, import, and otherwise transfer the Work, where
75 | such license applies only to those patent claims licensable by such Contributor
76 | that are necessarily infringed by their Contribution(s) alone or by combination
77 | of their Contribution(s) with the Work to which such Contribution(s) was
78 | submitted. If You institute patent litigation against any entity (including a
79 | cross-claim or counterclaim in a lawsuit) alleging that the Work or a
80 | Contribution incorporated within the Work constitutes direct or contributory
81 | patent infringement, then any patent licenses granted to You under this License
82 | for that Work shall terminate as of the date such litigation is filed.
83 |
84 | 4. Redistribution.
85 |
86 | You may reproduce and distribute copies of the Work or Derivative Works thereof
87 | in any medium, with or without modifications, and in Source or Object form,
88 | provided that You meet the following conditions:
89 |
90 | You must give any other recipients of the Work or Derivative Works a copy of
91 | this License; and
92 | You must cause any modified files to carry prominent notices stating that You
93 | changed the files; and
94 | You must retain, in the Source form of any Derivative Works that You distribute,
95 | all copyright, patent, trademark, and attribution notices from the Source form
96 | of the Work, excluding those notices that do not pertain to any part of the
97 | Derivative Works; and
98 | If the Work includes a "NOTICE" text file as part of its distribution, then any
99 | Derivative Works that You distribute must include a readable copy of the
100 | attribution notices contained within such NOTICE file, excluding those notices
101 | that do not pertain to any part of the Derivative Works, in at least one of the
102 | following places: within a NOTICE text file distributed as part of the
103 | Derivative Works; within the Source form or documentation, if provided along
104 | with the Derivative Works; or, within a display generated by the Derivative
105 | Works, if and wherever such third-party notices normally appear. The contents of
106 | the NOTICE file are for informational purposes only and do not modify the
107 | License. You may add Your own attribution notices within Derivative Works that
108 | You distribute, alongside or as an addendum to the NOTICE text from the Work,
109 | provided that such additional attribution notices cannot be construed as
110 | modifying the License.
111 | You may add Your own copyright statement to Your modifications and may provide
112 | additional or different license terms and conditions for use, reproduction, or
113 | distribution of Your modifications, or for any such Derivative Works as a whole,
114 | provided Your use, reproduction, and distribution of the Work otherwise complies
115 | with the conditions stated in this License.
116 |
117 | 5. Submission of Contributions.
118 |
119 | Unless You explicitly state otherwise, any Contribution intentionally submitted
120 | for inclusion in the Work by You to the Licensor shall be under the terms and
121 | conditions of this License, without any additional terms or conditions.
122 | Notwithstanding the above, nothing herein shall supersede or modify the terms of
123 | any separate license agreement you may have executed with Licensor regarding
124 | such Contributions.
125 |
126 | 6. Trademarks.
127 |
128 | This License does not grant permission to use the trade names, trademarks,
129 | service marks, or product names of the Licensor, except as required for
130 | reasonable and customary use in describing the origin of the Work and
131 | reproducing the content of the NOTICE file.
132 |
133 | 7. Disclaimer of Warranty.
134 |
135 | Unless required by applicable law or agreed to in writing, Licensor provides the
136 | Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
137 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
138 | including, without limitation, any warranties or conditions of TITLE,
139 | NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
140 | solely responsible for determining the appropriateness of using or
141 | redistributing the Work and assume any risks associated with Your exercise of
142 | permissions under this License.
143 |
144 | 8. Limitation of Liability.
145 |
146 | In no event and under no legal theory, whether in tort (including negligence),
147 | contract, or otherwise, unless required by applicable law (such as deliberate
148 | and grossly negligent acts) or agreed to in writing, shall any Contributor be
149 | liable to You for damages, including any direct, indirect, special, incidental,
150 | or consequential damages of any character arising as a result of this License or
151 | out of the use or inability to use the Work (including but not limited to
152 | damages for loss of goodwill, work stoppage, computer failure or malfunction, or
153 | any and all other commercial damages or losses), even if such Contributor has
154 | been advised of the possibility of such damages.
155 |
156 | 9. Accepting Warranty or Additional Liability.
157 |
158 | While redistributing the Work or Derivative Works thereof, You may choose to
159 | offer, and charge a fee for, acceptance of support, warranty, indemnity, or
160 | other liability obligations and/or rights consistent with this License. However,
161 | in accepting such obligations, You may act only on Your own behalf and on Your
162 | sole responsibility, not on behalf of any other Contributor, and only if You
163 | agree to indemnify, defend, and hold each Contributor harmless for any liability
164 | incurred by, or claims asserted against, such Contributor by reason of your
165 | accepting any such warranty or additional liability.
166 |
167 | END OF TERMS AND CONDITIONS
168 |
169 | APPENDIX: How to apply the Apache License to your work
170 |
171 | To apply the Apache License to your work, attach the following boilerplate
172 | notice, with the fields enclosed by brackets "[]" replaced with your own
173 | identifying information. (Don't include the brackets!) The text should be
174 | enclosed in the appropriate comment syntax for the file format. We also
175 | recommend that a file or class name and description of purpose be included on
176 | the same "printed page" as the copyright notice for easier identification within
177 | third-party archives.
178 |
179 | Copyright 2014 Google Inc.
180 |
181 | Licensed under the Apache License, Version 2.0 (the "License");
182 | you may not use this file except in compliance with the License.
183 | You may obtain a copy of the License at
184 |
185 | http://www.apache.org/licenses/LICENSE-2.0
186 |
187 | Unless required by applicable law or agreed to in writing, software
188 | distributed under the License is distributed on an "AS IS" BASIS,
189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
190 | See the License for the specific language governing permissions and
191 | limitations under the License.
192 |
--------------------------------------------------------------------------------
/v3/java/.gitignore:
--------------------------------------------------------------------------------
1 | .project
2 | .metadata
3 | bin/**
4 | libs/**
5 | src/resources/*.apk
6 | src/resources/*.bak
7 | local.properties
8 | .classpath
9 | .settings/
10 |
--------------------------------------------------------------------------------
/v3/java/README.md:
--------------------------------------------------------------------------------
1 | # Google Play Developer API samples
2 |
3 | A collection of Java samples for the Play Developer API.
4 |
5 | ## Installation
6 |
7 | 1. Download the Google Play Developer API client library:
8 | https://developers.google.com/android-publisher/libraries
9 |
10 | 2. Unzip the client library. The unzipped folder contains the
11 | google-api-services-androidpublisher-v3.jar client library and a lib/ folder with all required
12 | dependencies.
13 |
14 | 3. Import the Java sample code into your favorite IDE and reference all libraries in the /lib folder
15 | as well as the google-api-services-androidpublisher-v3.jar from the sample project.
16 |
17 | ## Getting started
18 | To use the Google Play Developer API you need to create or reuse an existing API project in the
19 | Google Api console, https://console.developers.google.com/. You can either use the API with a client
20 | ID for Native Application (Installed Application) or create a Service Account.
21 |
22 | ### Edit `ApplicationConfig.java` for global sample configuration
23 |
24 | 1. Specify the name of your application. If the application name is null or blank, the application
25 | will log a warning. Suggested format is `MyCompany-Application/1.0`.
26 |
27 | 2. Specify the package name of the app as per developer console.
28 |
29 | 3. If you want to run any of the upload apk samples, please copy your apk to the `/resources` folder
30 | and specify the apk file path, i.e. `/resources/your_apk.apk`
31 |
32 | ### First request using OAuth2: Installed application
33 |
34 | 1. Edit the `/resources/client_secrets.json` file and add the client ID, client secret and redirect
35 | uris.
36 |
37 | 2. Execute any sample class using its `main()` method to begin the auth flow:
38 |
39 | A browser window will open and ask you to login. Make sure the account has
40 | appropriate permissions in the Google Play Developer console.
41 |
42 | 3. Accept the permissions dialog. The browser should display
43 |
44 | `The authentication flow has completed.`
45 |
46 | Close the window and go back into your IDE and check the console output.
47 |
48 | 4. The script will output a list of apks.
49 |
50 | 5. The tokens will be stored in `.store/android_publisher_api` in your home folder. Remove this file
51 | to restart the auth flow.
52 |
53 |
54 | ### First request using OAuth2: Service accounts
55 |
56 | 1. Edit `ApplicationConfig.java` and add the service account email
57 | address.
58 |
59 | 2. Copy the service account key file, generated in the Google APIs Console into
60 | the same directory and rename it to `key.p12`.
61 |
62 | 3. Execute any sample class using its `main()` method in your IDE
63 |
64 | 4. The script will output a list of apks.
65 |
66 |
67 | > You're all set and ready to run the Play Developer API samples.
68 | Thank you for being such a great developer on Google Play, your feedback is very important to ensure
69 | that Google continues to improve the developer experience on Play! Enjoy :-).
70 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/AndroidPublisherHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | import com.google.api.client.auth.oauth2.Credential;
20 | import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
21 | import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
22 | import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
23 | import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
24 | import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
25 | import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
26 | import com.google.api.client.http.HttpTransport;
27 | import com.google.api.client.json.JsonFactory;
28 | import com.google.api.client.json.jackson2.JacksonFactory;
29 | import com.google.api.client.repackaged.com.google.common.base.Preconditions;
30 | import com.google.api.client.repackaged.com.google.common.base.Strings;
31 | import com.google.api.client.util.store.DataStoreFactory;
32 | import com.google.api.client.util.store.FileDataStoreFactory;
33 | import com.google.api.services.androidpublisher.AndroidPublisher;
34 | import com.google.api.services.androidpublisher.AndroidPublisherScopes;
35 |
36 | import java.io.File;
37 | import java.io.IOException;
38 | import java.io.InputStreamReader;
39 | import java.security.GeneralSecurityException;
40 | import java.util.Collections;
41 |
42 | import javax.annotation.Nullable;
43 |
44 | import org.apache.commons.logging.Log;
45 | import org.apache.commons.logging.LogFactory;
46 |
47 | /**
48 | * Helper class to initialize the publisher APIs client library.
49 | *
50 | * Before making any calls to the API through the client library you need to
51 | * call the {@link AndroidPublisherHelper#init(String)} method. This will run
52 | * all precondition checks for for client id and secret setup properly in
53 | * resources/client_secrets.json and authorize this client against the API.
54 | *
55 | */
56 | public class AndroidPublisherHelper {
57 |
58 | private static final Log log = LogFactory.getLog(AndroidPublisherHelper.class);
59 |
60 | static final String MIME_TYPE_APK = "application/vnd.android.package-archive";
61 |
62 | /** Path to the private key file (only used for Service Account auth). */
63 | private static final String SRC_RESOURCES_KEY_P12 = "src/resources/key.p12";
64 |
65 | /**
66 | * Path to the client secrets file (only used for Installed Application
67 | * auth).
68 | */
69 | private static final String RESOURCES_CLIENT_SECRETS_JSON = "/resources/client_secrets.json";
70 |
71 | /**
72 | * Directory to store user credentials (only for Installed Application
73 | * auth).
74 | */
75 | private static final String DATA_STORE_SYSTEM_PROPERTY = "user.home";
76 | private static final String DATA_STORE_FILE = ".store/android_publisher_api";
77 | private static final File DATA_STORE_DIR =
78 | new File(System.getProperty(DATA_STORE_SYSTEM_PROPERTY), DATA_STORE_FILE);
79 |
80 | /** Global instance of the JSON factory. */
81 | private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
82 |
83 | /** Global instance of the HTTP transport. */
84 | private static HttpTransport HTTP_TRANSPORT;
85 |
86 | /** Installed application user ID. */
87 | private static final String INST_APP_USER_ID = "user";
88 |
89 | /**
90 | * Global instance of the {@link DataStoreFactory}. The best practice is to
91 | * make it a single globally shared instance across your application.
92 | */
93 | private static FileDataStoreFactory dataStoreFactory;
94 |
95 | private static Credential authorizeWithServiceAccount(String serviceAccountEmail)
96 | throws GeneralSecurityException, IOException {
97 | log.info(String.format("Authorizing using Service Account: %s", serviceAccountEmail));
98 |
99 | // Build service account credential.
100 | GoogleCredential credential = new GoogleCredential.Builder()
101 | .setTransport(HTTP_TRANSPORT)
102 | .setJsonFactory(JSON_FACTORY)
103 | .setServiceAccountId(serviceAccountEmail)
104 | .setServiceAccountScopes(
105 | Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER))
106 | .setServiceAccountPrivateKeyFromP12File(new File(SRC_RESOURCES_KEY_P12))
107 | .build();
108 | return credential;
109 | }
110 |
111 | /**
112 | * Authorizes the installed application to access user's protected data.
113 | *
114 | * @throws IOException
115 | * @throws GeneralSecurityException
116 | */
117 | private static Credential authorizeWithInstalledApplication() throws IOException {
118 | log.info("Authorizing using installed application");
119 |
120 | // load client secrets
121 | GoogleClientSecrets clientSecrets = GoogleClientSecrets.load(
122 | JSON_FACTORY,
123 | new InputStreamReader(
124 | AndroidPublisherHelper.class
125 | .getResourceAsStream(RESOURCES_CLIENT_SECRETS_JSON)));
126 | // Ensure file has been filled out.
127 | checkClientSecretsFile(clientSecrets);
128 |
129 | dataStoreFactory = new FileDataStoreFactory(DATA_STORE_DIR);
130 |
131 | // set up authorization code flow
132 | GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow
133 | .Builder(HTTP_TRANSPORT,
134 | JSON_FACTORY, clientSecrets,
135 | Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER))
136 | .setDataStoreFactory(dataStoreFactory).build();
137 | // authorize
138 | return new AuthorizationCodeInstalledApp(
139 | flow, new LocalServerReceiver()).authorize(INST_APP_USER_ID);
140 | }
141 |
142 | /**
143 | * Ensure the client secrets file has been filled out.
144 | *
145 | * @param clientSecrets the GoogleClientSecrets containing data from the
146 | * file
147 | */
148 | private static void checkClientSecretsFile(GoogleClientSecrets clientSecrets) {
149 | if (clientSecrets.getDetails().getClientId().startsWith("[[INSERT")
150 | || clientSecrets.getDetails().getClientSecret().startsWith("[[INSERT")) {
151 | log.error("Enter Client ID and Secret from "
152 | + "APIs console into resources/client_secrets.json.");
153 | System.exit(1);
154 | }
155 | }
156 |
157 | /**
158 | * Performs all necessary setup steps for running requests against the API
159 | * using the Installed Application auth method.
160 | *
161 | * @param applicationName the name of the application: com.example.app
162 | * @return the {@Link AndroidPublisher} service
163 | */
164 | protected static AndroidPublisher init(String applicationName) throws Exception {
165 | return init(applicationName, null);
166 | }
167 |
168 | /**
169 | * Performs all necessary setup steps for running requests against the API.
170 | *
171 | * @param applicationName the name of the application: com.example.app
172 | * @param serviceAccountEmail the Service Account Email (empty if using
173 | * installed application)
174 | * @return the {@Link AndroidPublisher} service
175 | * @throws GeneralSecurityException
176 | * @throws IOException
177 | */
178 | protected static AndroidPublisher init(String applicationName,
179 | @Nullable String serviceAccountEmail) throws IOException, GeneralSecurityException {
180 | Preconditions.checkArgument(!Strings.isNullOrEmpty(applicationName),
181 | "applicationName cannot be null or empty!");
182 |
183 | // Authorization.
184 | newTrustedTransport();
185 | Credential credential;
186 | if (serviceAccountEmail == null || serviceAccountEmail.isEmpty()) {
187 | credential = authorizeWithInstalledApplication();
188 | } else {
189 | credential = authorizeWithServiceAccount(serviceAccountEmail);
190 | }
191 |
192 | // Set up and return API client.
193 | return new AndroidPublisher.Builder(
194 | HTTP_TRANSPORT, JSON_FACTORY, credential).setApplicationName(applicationName)
195 | .build();
196 | }
197 |
198 | private static void newTrustedTransport() throws GeneralSecurityException,
199 | IOException {
200 | if (null == HTTP_TRANSPORT) {
201 | HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
202 | }
203 | }
204 |
205 | }
206 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/ApplicationConfig.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | /**
20 | * Contains global application configuration, which is required by all samples.
21 | */
22 | public final class ApplicationConfig {
23 |
24 | private ApplicationConfig() {
25 | // no instance
26 | }
27 |
28 | /**
29 | * Specify the name of your application. If the application name is
30 | * {@code null} or blank, the application will log a warning. Suggested
31 | * format is "MyCompany-Application/1.0".
32 | */
33 | static final String APPLICATION_NAME = "";
34 |
35 | /**
36 | * Specify the package name of the app.
37 | */
38 | static final String PACKAGE_NAME = "";
39 |
40 | /**
41 | * Authentication.
42 | *
43 | * Installed application: Leave this string empty and copy or
44 | * edit resources/client_secrets.json.
45 | *
46 | *
47 | * Service accounts: Enter the service
48 | * account email and add your key.p12 file to the resources directory.
49 | *
50 | */
51 | static final String SERVICE_ACCOUNT_EMAIL = "";
52 |
53 | /**
54 | * Specify the apk file path of the apk to upload, i.e. /resources/your_apk.apk
55 | *
56 | * This needs to be set for running {@link BasicUploadApk} and {@link UploadApkWithListing}
57 | * samples.
58 | *
59 | */
60 | public static final String APK_FILE_PATH = "";
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/BasicUploadApk.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | import com.google.api.client.util.Lists;
20 | import com.google.api.services.androidpublisher.model.LocalizedText;
21 | import com.google.api.services.androidpublisher.model.TrackRelease;
22 | import java.io.File;
23 | import java.io.IOException;
24 | import java.net.URISyntaxException;
25 | import java.security.GeneralSecurityException;
26 | import java.util.ArrayList;
27 | import java.util.Collections;
28 | import java.util.List;
29 |
30 | import org.apache.commons.logging.Log;
31 | import org.apache.commons.logging.LogFactory;
32 |
33 | import com.google.api.client.http.AbstractInputStreamContent;
34 | import com.google.api.client.http.FileContent;
35 | import com.google.api.client.repackaged.com.google.common.base.Preconditions;
36 | import com.google.api.client.repackaged.com.google.common.base.Strings;
37 | import com.google.api.services.androidpublisher.AndroidPublisher;
38 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits;
39 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Apks.Upload;
40 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Commit;
41 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Insert;
42 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Tracks.Update;
43 | import com.google.api.services.androidpublisher.model.Apk;
44 | import com.google.api.services.androidpublisher.model.AppEdit;
45 | import com.google.api.services.androidpublisher.model.Track;
46 |
47 | /**
48 | * Uploads an apk to the alpha track.
49 | */
50 | public class BasicUploadApk {
51 |
52 | private static final Log log = LogFactory.getLog(BasicUploadApk.class);
53 |
54 | /**
55 | * Track for uploading the apk, can be 'alpha', beta', 'production' or
56 | * 'rollout'.
57 | */
58 | private static final String TRACK_ALPHA = "alpha";
59 |
60 | public static void main(String[] args) {
61 | try {
62 | Preconditions.checkArgument(!Strings.isNullOrEmpty(ApplicationConfig.PACKAGE_NAME),
63 | "ApplicationConfig.PACKAGE_NAME cannot be null or empty!");
64 |
65 | // Create the API service.
66 | AndroidPublisher service = AndroidPublisherHelper.init(
67 | ApplicationConfig.APPLICATION_NAME, ApplicationConfig.SERVICE_ACCOUNT_EMAIL);
68 | final Edits edits = service.edits();
69 |
70 | // Create a new edit to make changes to your listing.
71 | Insert editRequest = edits
72 | .insert(ApplicationConfig.PACKAGE_NAME,
73 | null /** no content */);
74 | AppEdit edit = editRequest.execute();
75 | final String editId = edit.getId();
76 | log.info(String.format("Created edit with id: %s", editId));
77 |
78 | // Upload new apk to developer console
79 | final String apkPath = BasicUploadApk.class
80 | .getResource(ApplicationConfig.APK_FILE_PATH)
81 | .toURI().getPath();
82 | final AbstractInputStreamContent apkFile =
83 | new FileContent(AndroidPublisherHelper.MIME_TYPE_APK, new File(apkPath));
84 | Upload uploadRequest = edits
85 | .apks()
86 | .upload(ApplicationConfig.PACKAGE_NAME,
87 | editId,
88 | apkFile);
89 | Apk apk = uploadRequest.execute();
90 | log.info(String.format("Version code %d has been uploaded",
91 | apk.getVersionCode()));
92 |
93 | // Assign apk to alpha track.
94 | List apkVersionCodes = new ArrayList<>();
95 | apkVersionCodes.add(Long.valueOf(apk.getVersionCode()));
96 | Update updateTrackRequest = edits
97 | .tracks()
98 | .update(ApplicationConfig.PACKAGE_NAME,
99 | editId,
100 | TRACK_ALPHA,
101 | new Track().setReleases(
102 | Collections.singletonList(
103 | new TrackRelease()
104 | .setName("My Alpha Release")
105 | .setVersionCodes(apkVersionCodes)
106 | .setStatus("completed")
107 | .setReleaseNotes(Collections.singletonList(
108 | new LocalizedText()
109 | .setLanguage("en-US")
110 | .setText("Adds the exciting new feature X!"))))));
111 | Track updatedTrack = updateTrackRequest.execute();
112 | log.info(String.format("Track %s has been updated.", updatedTrack.getTrack()));
113 |
114 | // Commit changes for edit.
115 | Commit commitRequest = edits.commit(ApplicationConfig.PACKAGE_NAME, editId);
116 | AppEdit appEdit = commitRequest.execute();
117 | log.info(String.format("App edit with id %s has been comitted", appEdit.getId()));
118 |
119 | } catch (IOException | URISyntaxException | GeneralSecurityException ex) {
120 | log.error("Excpetion was thrown while uploading apk to alpha track", ex);
121 | }
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/ListApks.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | import java.io.IOException;
20 | import java.security.GeneralSecurityException;
21 |
22 | import org.apache.commons.logging.Log;
23 | import org.apache.commons.logging.LogFactory;
24 |
25 | import com.google.api.client.repackaged.com.google.common.base.Preconditions;
26 | import com.google.api.client.repackaged.com.google.common.base.Strings;
27 | import com.google.api.services.androidpublisher.AndroidPublisher;
28 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits;
29 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Insert;
30 | import com.google.api.services.androidpublisher.model.Apk;
31 | import com.google.api.services.androidpublisher.model.ApksListResponse;
32 | import com.google.api.services.androidpublisher.model.AppEdit;
33 |
34 | /**
35 | * Lists all the apks for a given app.
36 | */
37 | public class ListApks {
38 |
39 | private static final Log log = LogFactory.getLog(ListApks.class);
40 |
41 | public static void main(String[] args) {
42 | try {
43 | Preconditions.checkArgument(!Strings.isNullOrEmpty(ApplicationConfig.PACKAGE_NAME),
44 | "ApplicationConfig.PACKAGE_NAME cannot be null or empty!");
45 |
46 | // Create the API service.
47 | final AndroidPublisher service = AndroidPublisherHelper.init(
48 | ApplicationConfig.APPLICATION_NAME, ApplicationConfig.SERVICE_ACCOUNT_EMAIL);
49 | final Edits edits = service.edits();
50 |
51 | // Create a new edit to make changes.
52 | Insert editRequest = edits
53 | .insert(ApplicationConfig.PACKAGE_NAME,
54 | null /** no content */);
55 | AppEdit appEdit = editRequest.execute();
56 |
57 | // Get a list of apks.
58 | ApksListResponse apksResponse = edits
59 | .apks()
60 | .list(ApplicationConfig.PACKAGE_NAME,
61 | appEdit.getId()).execute();
62 |
63 | // Print the apk info.
64 | for (Apk apk : apksResponse.getApks()) {
65 | System.out.println(
66 | String.format("Version: %d - Binary sha1: %s", apk.getVersionCode(),
67 | apk.getBinary().getSha1()));
68 | }
69 | } catch (IOException | GeneralSecurityException ex) {
70 | log.error("Exception was thrown while updating listing", ex);
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/UpdateListing.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | import java.io.IOException;
20 | import java.security.GeneralSecurityException;
21 | import java.util.Locale;
22 |
23 | import org.apache.commons.logging.Log;
24 | import org.apache.commons.logging.LogFactory;
25 |
26 | import com.google.api.client.repackaged.com.google.common.base.Preconditions;
27 | import com.google.api.client.repackaged.com.google.common.base.Strings;
28 | import com.google.api.services.androidpublisher.AndroidPublisher;
29 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits;
30 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Commit;
31 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Insert;
32 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Listings.Update;
33 | import com.google.api.services.androidpublisher.model.AppEdit;
34 | import com.google.api.services.androidpublisher.model.Listing;
35 |
36 | /**
37 | * Updates US and UK listings. Changes title, short-description, full-description and video for
38 | * en-US and en-GB locales.
39 | */
40 | public class UpdateListing {
41 |
42 | private static final Log log = LogFactory.getLog(UpdateListing.class);
43 |
44 | private static final String US_LISTING_TITLE = "App Title US";
45 | private static final String US_LISTING_SHORT_DESCRITPION = "Bacon ipsum";
46 | private static final String US_LISTING_FULL_DESCRIPTION = "Dessert trunk truck";
47 |
48 | private static final String UK_LISTING_TITLE = "App Title UK";
49 | private static final String UK_LISTING_SHORT_DESCRITPION = "Pancetta ipsum";
50 | private static final String UK_LISTING_FULL_DESCRIPTION = "Pudding boot lorry";
51 |
52 | private static final String LISTINGS_PROMO_VIDEO =
53 | "https://www.youtube.com/watch?v=ZNSLQlNSPu8";
54 |
55 | public static void main(String[] args) {
56 | try {
57 | Preconditions.checkArgument(!Strings.isNullOrEmpty(ApplicationConfig.PACKAGE_NAME),
58 | "ApplicationConfig.PACKAGE_NAME cannot be null or empty!");
59 |
60 | // Create the API service.
61 | AndroidPublisher service = AndroidPublisherHelper.init(
62 | ApplicationConfig.APPLICATION_NAME, ApplicationConfig.SERVICE_ACCOUNT_EMAIL);
63 | final Edits edits = service.edits();
64 |
65 | // Create an edit to update listing for application.
66 | Insert editRequest = edits
67 | .insert(ApplicationConfig.PACKAGE_NAME,
68 | null /** no content */);
69 | AppEdit edit = editRequest.execute();
70 | final String editId = edit.getId();
71 | log.info(String.format("Created edit with id: %s", editId));
72 |
73 | // Update listing for US version of the application.
74 | final Listing newUsListing = new Listing();
75 | newUsListing.setTitle(US_LISTING_TITLE)
76 | .setFullDescription(US_LISTING_FULL_DESCRIPTION)
77 | .setShortDescription(US_LISTING_SHORT_DESCRITPION)
78 | .setVideo(LISTINGS_PROMO_VIDEO);
79 |
80 | Update updateUSListingsRequest = edits
81 | .listings()
82 | .update(ApplicationConfig.PACKAGE_NAME,
83 | editId,
84 | Locale.US.toString(),
85 | newUsListing);
86 | Listing updatedUsListing = updateUSListingsRequest.execute();
87 | log.info(String.format("Created new US app listing with title: %s",
88 | updatedUsListing.getTitle()));
89 |
90 | // Create and update listing for UK version of the application.
91 | final Listing newUkListing = new Listing();
92 | newUkListing.setTitle(UK_LISTING_TITLE)
93 | .setFullDescription(UK_LISTING_FULL_DESCRIPTION)
94 | .setShortDescription(UK_LISTING_SHORT_DESCRITPION)
95 | .setVideo(LISTINGS_PROMO_VIDEO);
96 |
97 | Update updateUkListingsRequest = edits
98 | .listings()
99 | .update(ApplicationConfig.PACKAGE_NAME,
100 | editId,
101 | Locale.UK.toString(),
102 | newUkListing);
103 | Listing updatedUkListing = updateUkListingsRequest.execute();
104 | log.info(String.format("Created new UK app listing with title: %s",
105 | updatedUkListing.getTitle()));
106 |
107 | // Commit changes for edit.
108 | Commit commitRequest = edits.commit(ApplicationConfig.PACKAGE_NAME, editId);
109 | AppEdit appEdit = commitRequest.execute();
110 | log.info(String.format("App edit with id %s has been comitted", appEdit.getId()));
111 |
112 | } catch (IOException | GeneralSecurityException ex) {
113 | log.error("Exception was thrown while updating listing", ex);
114 | }
115 | }
116 | }
117 |
--------------------------------------------------------------------------------
/v3/java/src/com/google/play/developerapi/samples/UploadApkWithListing.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2014 Google Inc. All rights reserved.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.google.play.developerapi.samples;
18 |
19 | import com.google.api.services.androidpublisher.model.LocalizedText;
20 | import com.google.api.services.androidpublisher.model.TrackRelease;
21 | import java.io.File;
22 | import java.io.IOException;
23 | import java.net.URISyntaxException;
24 | import java.security.GeneralSecurityException;
25 | import java.util.ArrayList;
26 | import java.util.Collections;
27 | import java.util.List;
28 | import java.util.Locale;
29 |
30 | import org.apache.commons.logging.Log;
31 | import org.apache.commons.logging.LogFactory;
32 |
33 | import com.google.api.client.http.AbstractInputStreamContent;
34 | import com.google.api.client.http.FileContent;
35 | import com.google.api.client.repackaged.com.google.common.base.Preconditions;
36 | import com.google.api.client.repackaged.com.google.common.base.Strings;
37 | import com.google.api.services.androidpublisher.AndroidPublisher;
38 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits;
39 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Commit;
40 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Insert;
41 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Apks.Upload;
42 | import com.google.api.services.androidpublisher.AndroidPublisher.Edits.Tracks.Update;
43 | import com.google.api.services.androidpublisher.model.Apk;
44 | import com.google.api.services.androidpublisher.model.AppEdit;
45 | import com.google.api.services.androidpublisher.model.Track;
46 |
47 | /**
48 | * Uploads an apk to the beta track and updates recent changes description.
49 | */
50 | public class UploadApkWithListing {
51 |
52 | private static final Log log = LogFactory.getLog(UploadApkWithListing.class);
53 |
54 | private static final String RECENT_CHANGES_TEXT = "Release recent changes en-US";
55 |
56 | /**
57 | * Track for uploading the apk, can be 'alpha', beta', 'production' or
58 | * 'rollout'.
59 | */
60 | private static final String TRACK_BETA = "beta";
61 |
62 | public static void main(String[] args) {
63 | try {
64 | Preconditions.checkArgument(!Strings.isNullOrEmpty(ApplicationConfig.PACKAGE_NAME),
65 | "ApplicationConfig.PACKAGE_NAME cannot be null or empty!");
66 |
67 | // Create the API service.
68 | AndroidPublisher service = AndroidPublisherHelper.init(
69 | ApplicationConfig.APPLICATION_NAME, ApplicationConfig.SERVICE_ACCOUNT_EMAIL);
70 | final Edits edits = service.edits();
71 |
72 | // Create a new edit to make changes.
73 | Insert editRequest = edits
74 | .insert(ApplicationConfig.PACKAGE_NAME,
75 | null /** no content */);
76 | AppEdit edit = editRequest.execute();
77 | final String editId = edit.getId();
78 | log.info(String.format("Created edit with id: %s", editId));
79 |
80 | // Upload new apk to developer console
81 | final String apkPath = UploadApkWithListing.class
82 | .getResource(ApplicationConfig.APK_FILE_PATH)
83 | .toURI().getPath();
84 | final AbstractInputStreamContent apkFile =
85 | new FileContent(AndroidPublisherHelper.MIME_TYPE_APK, new File(apkPath));
86 | Upload uploadRequest = edits
87 | .apks()
88 | .upload(ApplicationConfig.PACKAGE_NAME,
89 | editId,
90 | apkFile);
91 | Apk apk = uploadRequest.execute();
92 | log.info(String.format("Version code %d has been uploaded",
93 | apk.getVersionCode()));
94 |
95 | // Assign apk to beta track.
96 | List apkVersionCodes = new ArrayList<>();
97 | apkVersionCodes.add(Long.valueOf(apk.getVersionCode()));
98 | Update updateTrackRequest = edits
99 | .tracks()
100 | .update(ApplicationConfig.PACKAGE_NAME,
101 | editId,
102 | TRACK_BETA,
103 | new Track().setReleases(
104 | Collections.singletonList(
105 | new TrackRelease()
106 | .setName("My Beta Release")
107 | .setVersionCodes(apkVersionCodes)
108 | .setStatus("completed")
109 | .setReleaseNotes(Collections.singletonList(
110 | new LocalizedText()
111 | .setLanguage(Locale.US.toString())
112 | .setText(RECENT_CHANGES_TEXT))))));
113 | Track updatedTrack = updateTrackRequest.execute();
114 | log.info(String.format("Track %s has been updated.", updatedTrack.getTrack()));
115 |
116 |
117 | // Commit changes for edit.
118 | Commit commitRequest = edits.commit(ApplicationConfig.PACKAGE_NAME, editId);
119 | AppEdit appEdit = commitRequest.execute();
120 | log.info(String.format("App edit with id %s has been comitted", appEdit.getId()));
121 |
122 | } catch (IOException | URISyntaxException | GeneralSecurityException ex) {
123 | log.error(
124 | "Exception was thrown while uploading apk and updating recent changes",
125 | ex);
126 | }
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/v3/java/src/resources/client_secrets.json:
--------------------------------------------------------------------------------
1 | {
2 | "installed": {
3 | "client_id": "[[INSERT CLIENT ID HERE]]",
4 | "client_secret": "[[INSERT CLIENT SECRET HERE]]",
5 | "redirect_uris": [],
6 | "auth_uri": "https://accounts.google.com/o/oauth2/auth",
7 | "token_uri": "https://accounts.google.com/o/oauth2/token"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/v3/python/README.md:
--------------------------------------------------------------------------------
1 | # Google Play Developer Publishing API samples
2 |
3 | A collection of command-line samples for the Play Developer Publishing API.
4 |
5 | ## Installation
6 |
7 | 1. Download Google APIs Client Library for Python (google-api-python-client):
8 | https://code.google.com/p/google-api-python-client/
9 |
10 | or use pip:
11 |
12 | ```bash
13 | $ pip install google-api-python-client
14 | ```
15 |
16 | 2. Make sure you can import the client library:
17 |
18 | ```bash
19 | $ python
20 | >>> import apiclient
21 | >>>
22 | ```
23 |
24 | ## First request using OAuth2: Installed application
25 |
26 | 1. Edit the `client_secrets.json` file and add the client ID and client secret.
27 |
28 | 2. Execute any of the scripts to begin the auth flow:
29 |
30 | ```bash
31 | $ python basic_list_apks.py com.myapp.package
32 | ```
33 |
34 | A browser window will open and ask you to login. Make sure the account has
35 | enough permissions in the Google Play Developer console.
36 |
37 | 3. Accept the permissions dialog. The browser should display
38 |
39 | `The authentication flow has completed.`
40 |
41 | Close the window and go back to the shell.
42 |
43 | 4. The script will output a list of apks.
44 |
45 | 5. The tokens will be stored in `androidpublisher.dat`. Remove this file to restart the
46 | auth flow.
47 |
48 |
49 | ## First request using OAuth2: Service accounts
50 |
51 | 1. Edit `basic_list_apks_service_account.py` and add the service account Email
52 | address.
53 |
54 | 2. Copy the service account key file, generated in the Google APIs Console into
55 | the same directory and rename it to `key.p12`.
56 |
57 | 3. Execute the script:
58 |
59 | ```bash
60 | $ python basic_list_apks_service_account.py com.myapp.package
61 | ```
62 |
63 | 4. The script will output a list of apks.
64 |
65 |
--------------------------------------------------------------------------------
/v3/python/basic_list_apks.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Lists all the apks for a given app."""
18 |
19 | import argparse
20 | import sys
21 | from apiclient import sample_tools
22 | from oauth2client import client
23 |
24 | # Declare command-line flags.
25 | argparser = argparse.ArgumentParser(add_help=False)
26 | argparser.add_argument('package_name',
27 | help='The package name. Example: com.android.sample')
28 |
29 |
30 | def main(argv):
31 | # Authenticate and construct service.
32 | service, flags = sample_tools.init(
33 | argv,
34 | 'androidpublisher',
35 | 'v3',
36 | __doc__,
37 | __file__,
38 | parents=[argparser],
39 | scope='https://www.googleapis.com/auth/androidpublisher')
40 |
41 | # Process flags and read their values.
42 | package_name = flags.package_name
43 |
44 | try:
45 |
46 | edit_request = service.edits().insert(body={}, packageName=package_name)
47 | result = edit_request.execute()
48 | edit_id = result['id']
49 |
50 | apks_result = service.edits().apks().list(
51 | editId=edit_id, packageName=package_name).execute()
52 |
53 | for apk in apks_result['apks']:
54 | print 'versionCode: %s, binary.sha1: %s' % (
55 | apk['versionCode'], apk['binary']['sha1'])
56 |
57 | except client.AccessTokenRefreshError:
58 | print ('The credentials have been revoked or expired, please re-run the '
59 | 'application to re-authorize')
60 |
61 | if __name__ == '__main__':
62 | main(sys.argv)
63 |
--------------------------------------------------------------------------------
/v3/python/basic_list_apks_service_account.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the "License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Lists all the apks for a given app."""
18 |
19 | import argparse
20 |
21 | from apiclient.discovery import build
22 | import httplib2
23 | from oauth2client import client
24 |
25 |
26 | SERVICE_ACCOUNT_EMAIL = (
27 | 'ENTER_YOUR_SERVICE_ACCOUNT_EMAIL_HERE@developer.gserviceaccount.com')
28 |
29 | # Declare command-line flags.
30 | argparser = argparse.ArgumentParser(add_help=False)
31 | argparser.add_argument('package_name',
32 | help='The package name. Example: com.android.sample')
33 |
34 |
35 | def main():
36 | # Load the key in PKCS 12 format that you downloaded from the Google APIs
37 | # Console when you created your Service account.
38 | f = file('key.p12', 'rb')
39 | key = f.read()
40 | f.close()
41 |
42 | # Create an httplib2.Http object to handle our HTTP requests and authorize it
43 | # with the Credentials. Note that the first parameter, service_account_name,
44 | # is the Email address created for the Service account. It must be the email
45 | # address associated with the key that was created.
46 | credentials = client.SignedJwtAssertionCredentials(
47 | SERVICE_ACCOUNT_EMAIL,
48 | key,
49 | scope='https://www.googleapis.com/auth/androidpublisher')
50 | http = httplib2.Http()
51 | http = credentials.authorize(http)
52 |
53 | service = build('androidpublisher', 'v3', http=http)
54 |
55 | # Process flags and read their values.
56 | flags = argparser.parse_args()
57 |
58 | package_name = flags.package_name
59 |
60 | try:
61 |
62 | edit_request = service.edits().insert(body={}, packageName=package_name)
63 | result = edit_request.execute()
64 | edit_id = result['id']
65 |
66 | apks_result = service.edits().apks().list(
67 | editId=edit_id, packageName=package_name).execute()
68 |
69 | for apk in apks_result['apks']:
70 | print('versionCode: %s, binary.sha1: %s' % (
71 | apk['versionCode'], apk['binary']['sha1']))
72 |
73 | except client.AccessTokenRefreshError:
74 | print ('The credentials have been revoked or expired, please re-run the '
75 | 'application to re-authorize')
76 |
77 | if __name__ == '__main__':
78 | main()
79 |
--------------------------------------------------------------------------------
/v3/python/basic_upload_apks.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the 'License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Uploads an apk to the alpha track."""
18 |
19 | import argparse
20 | import sys
21 | from apiclient import sample_tools
22 | from oauth2client import client
23 |
24 | TRACK = 'alpha' # Can be 'alpha', beta', 'production' or 'rollout'
25 |
26 | # Declare command-line flags.
27 | argparser = argparse.ArgumentParser(add_help=False)
28 | argparser.add_argument('package_name',
29 | help='The package name. Example: com.android.sample')
30 | argparser.add_argument('apk_file',
31 | nargs='?',
32 | default='test.apk',
33 | help='The path to the APK file to upload.')
34 |
35 |
36 | def main(argv):
37 | # Authenticate and construct service.
38 | service, flags = sample_tools.init(
39 | argv,
40 | 'androidpublisher',
41 | 'v3',
42 | __doc__,
43 | __file__, parents=[argparser],
44 | scope='https://www.googleapis.com/auth/androidpublisher')
45 |
46 | # Process flags and read their values.
47 | package_name = flags.package_name
48 | apk_file = flags.apk_file
49 |
50 | try:
51 | edit_request = service.edits().insert(body={}, packageName=package_name)
52 | result = edit_request.execute()
53 | edit_id = result['id']
54 |
55 | apk_response = service.edits().apks().upload(
56 | editId=edit_id,
57 | packageName=package_name,
58 | media_body=apk_file).execute()
59 |
60 | print 'Version code %d has been uploaded' % apk_response['versionCode']
61 |
62 | track_response = service.edits().tracks().update(
63 | editId=edit_id,
64 | track=TRACK,
65 | packageName=package_name,
66 | body={u'releases': [{
67 | u'name': u'My first API release',
68 | u'versionCodes': [str(apk_response['versionCode'])],
69 | u'status': u'completed',
70 | }]}).execute()
71 |
72 | print 'Track %s is set with releases: %s' % (
73 | track_response['track'], str(track_response['releases']))
74 |
75 | commit_request = service.edits().commit(
76 | editId=edit_id, packageName=package_name).execute()
77 |
78 | print 'Edit "%s" has been committed' % (commit_request['id'])
79 |
80 | except client.AccessTokenRefreshError:
81 | print ('The credentials have been revoked or expired, please re-run the '
82 | 'application to re-authorize')
83 |
84 | if __name__ == '__main__':
85 | main(sys.argv)
86 |
--------------------------------------------------------------------------------
/v3/python/client_secrets.json:
--------------------------------------------------------------------------------
1 | {
2 | "installed": {
3 | "client_id": "[[INSERT CLIENT ID HERE]]",
4 | "client_secret": "[[INSERT CLIENT SECRET HERE]]",
5 | "redirect_uris": [],
6 | "auth_uri": "https://accounts.google.com/o/oauth2/auth",
7 | "token_uri": "https://accounts.google.com/o/oauth2/token"
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/v3/python/update_listings.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the 'License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Changes the description, promo text and title of an app in en-US and en-GB.
18 | """
19 |
20 | import argparse
21 | import sys
22 | from apiclient import sample_tools
23 | from oauth2client import client
24 |
25 | TRACK = 'alpha' # Can be 'alpha', beta', 'production' or 'rollout'
26 |
27 | # Declare command-line flags.
28 | argparser = argparse.ArgumentParser(add_help=False)
29 | argparser.add_argument('package_name',
30 | help='The package name. Example: com.android.sample')
31 |
32 |
33 | def main(argv):
34 | # Authenticate and construct service.
35 | service, flags = sample_tools.init(
36 | argv,
37 | 'androidpublisher',
38 | 'v2',
39 | __doc__,
40 | __file__, parents=[argparser],
41 | scope='https://www.googleapis.com/auth/androidpublisher')
42 |
43 | # Process flags and read their values.
44 | package_name = flags.package_name
45 |
46 | try:
47 | edit_request = service.edits().insert(body={}, packageName=package_name)
48 | result = edit_request.execute()
49 | edit_id = result['id']
50 |
51 | listing_response_us = service.edits().listings().update(
52 | editId=edit_id, packageName=package_name, language='en-US',
53 | body={'fullDescription': 'Dessert trunk truck',
54 | 'shortDescription': 'Bacon ipsum',
55 | 'title': 'App Title US'}).execute()
56 |
57 | print ('Listing for language %s was updated.'
58 | % listing_response_us['language'])
59 |
60 | listing_response_gb = service.edits().listings().update(
61 | editId=edit_id, packageName=package_name, language='en-GB',
62 | body={'fullDescription': 'Pudding boot lorry',
63 | 'shortDescription': 'Pancetta ipsum',
64 | 'title': 'App Title UK'}).execute()
65 |
66 | print ('Listing for language %s was updated.'
67 | % listing_response_gb['language'])
68 |
69 | commit_request = service.edits().commit(
70 | editId=edit_id, packageName=package_name).execute()
71 |
72 | print 'Edit "%s" has been committed' % (commit_request['id'])
73 |
74 | except client.AccessTokenRefreshError:
75 | print ('The credentials have been revoked or expired, please re-run the '
76 | 'application to re-authorize')
77 |
78 | if __name__ == '__main__':
79 | main(sys.argv)
80 |
--------------------------------------------------------------------------------
/v3/python/upload_apks_rollout.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the 'License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Uploads apk to rollout track with user fraction."""
18 |
19 | import argparse
20 | import sys
21 | from apiclient import sample_tools
22 | from oauth2client import client
23 |
24 | TRACK = 'rollout'
25 | USER_FRACTION = 0.2
26 |
27 | # Declare command-line flags.
28 | argparser = argparse.ArgumentParser(add_help=False)
29 | argparser.add_argument('package_name',
30 | help='The package name. Example: com.android.sample')
31 | argparser.add_argument('apk_file',
32 | nargs='?',
33 | default='test.apk',
34 | help='The path to the APK file to upload.')
35 |
36 |
37 | def main(argv):
38 | # Authenticate and construct service.
39 | service, flags = sample_tools.init(
40 | argv,
41 | 'androidpublisher',
42 | 'v3',
43 | __doc__,
44 | __file__, parents=[argparser],
45 | scope='https://www.googleapis.com/auth/androidpublisher')
46 |
47 | # Process flags and read their values.
48 | package_name = flags.package_name
49 | apk_file = flags.apk_file
50 |
51 | try:
52 | edit_request = service.edits().insert(body={}, packageName=package_name)
53 | result = edit_request.execute()
54 | edit_id = result['id']
55 |
56 | apk_response = service.edits().apks().upload(
57 | editId=edit_id, packageName=package_name, media_body=apk_file).execute()
58 |
59 | print 'Version code %d has been uploaded' % apk_response['versionCode']
60 |
61 | track_response = service.edits().tracks().update(
62 | editId=edit_id,
63 | track=TRACK,
64 | packageName=package_name,
65 | body={u'releases': [{
66 | u'name': u'My first API release',
67 | u'versionCodes': [str([apk_response['versionCode']])],
68 | u'userFraction': USER_FRACTION,
69 | u'status': u'inProgress',
70 | }]}).execute()
71 |
72 | print 'Track %s is set with releases: %s' % (
73 | track_response['track'], str(track_response['releases']))
74 |
75 | commit_request = service.edits().commit(
76 | editId=edit_id, packageName=package_name).execute()
77 |
78 | print 'Edit "%s" has been committed' % (commit_request['id'])
79 |
80 | except client.AccessTokenRefreshError:
81 | print ('The credentials have been revoked or expired, please re-run the '
82 | 'application to re-authorize')
83 |
84 | if __name__ == '__main__':
85 | main(sys.argv)
86 |
--------------------------------------------------------------------------------
/v3/python/upload_apks_with_listing.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | #
3 | # Copyright 2014 Google Inc. All Rights Reserved.
4 | #
5 | # Licensed under the Apache License, Version 2.0 (the 'License");
6 | # you may not use this file except in compliance with the License.
7 | # You may obtain a copy of the License at
8 | #
9 | # http://www.apache.org/licenses/LICENSE-2.0
10 | #
11 | # Unless required by applicable law or agreed to in writing, software
12 | # distributed under the License is distributed on an "AS IS" BASIS,
13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | # See the License for the specific language governing permissions and
15 | # limitations under the License.
16 |
17 | """Uploads apk to alpha track and updates its listing properties."""
18 |
19 | import argparse
20 | import sys
21 | from apiclient import sample_tools
22 | from oauth2client import client
23 |
24 | TRACK = 'alpha' # Can be 'alpha', beta', 'production' or 'rollout'
25 |
26 | # Declare command-line flags.
27 | argparser = argparse.ArgumentParser(add_help=False)
28 | argparser.add_argument('package_name',
29 | help='The package name. Example: com.android.sample')
30 | argparser.add_argument('apk_file',
31 | nargs='?',
32 | default='test.apk',
33 | help='The path to the APK file to upload.')
34 |
35 |
36 | def main(argv):
37 | # Authenticate and construct service.
38 | service, flags = sample_tools.init(
39 | argv,
40 | 'androidpublisher',
41 | 'v3',
42 | __doc__,
43 | __file__, parents=[argparser],
44 | scope='https://www.googleapis.com/auth/androidpublisher')
45 |
46 | # Process flags and read their values.
47 | package_name = flags.package_name
48 | apk_file = flags.apk_file
49 |
50 | try:
51 | edit_request = service.edits().insert(body={}, packageName=package_name)
52 | result = edit_request.execute()
53 | edit_id = result['id']
54 |
55 | apk_response = service.edits().apks().upload(
56 | editId=edit_id,
57 | packageName=package_name,
58 | media_body=apk_file).execute()
59 |
60 | print 'Version code %d has been uploaded' % apk_response['versionCode']
61 |
62 | track_response = service.edits().tracks().update(
63 | editId=edit_id,
64 | track=TRACK,
65 | packageName=package_name,
66 | body={u'releases': [{
67 | u'name': u'My first API release with release notes',
68 | u'versionCodes': [str([apk_response['versionCode']])],
69 | u'releaseNotes': [
70 | {u'recentChanges': u'Apk recent changes in en-US'},
71 | ],
72 | u'status': u'completed',
73 | }]}).execute()
74 |
75 | print 'Track %s is set with releases: %s' % (
76 | track_response['track'], str(track_response['releases']))
77 |
78 | commit_request = service.edits().commit(
79 | editId=edit_id, packageName=package_name).execute()
80 |
81 | print 'Edit "%s" has been committed' % (commit_request['id'])
82 |
83 | except client.AccessTokenRefreshError:
84 | print ('The credentials have been revoked or expired, please re-run the '
85 | 'application to re-authorize')
86 |
87 | if __name__ == '__main__':
88 | main(sys.argv)
89 |
--------------------------------------------------------------------------------