Pro Yearly is on sale from $80 to $50! »

Publishing API & Continuous Deployment on Android

Publishing API & Continuous Deployment on Android

Presented at Droidcon Italy 2017

2bf14ad96e09ea7eda4973795ce70fa6?s=128

Júlio Zynger

April 07, 2017
Tweet

Transcript

  1. Publishing API and Continuous Deployment Júlio Zynger

  2. Continuous Deployment?

  3. None
  4. http://bit.ly/cd_codeship

  5. http://bit.ly/cd_codeship

  6. http://bit.ly/cd_codeship

  7. None
  8. Google Play Developer API

  9. Google Play Developer API * • Subscriptions and In-App Purchases

    API ◦ In-App Products ◦ Product entitlements ◦ Recurring sales and subscriptions • Publishing API ◦ Create and modify apps’ Listings ◦ Upload new APKs ◦ APK promotion to distribution tracks (alpha, beta, staged rollout and production) • Reviews API ◦ List and answer reviews * quota: 200k requests/day
  10. Console configuration

  11. Google Developer Console Enabling Google Play Android Developer API *

    * create a project on the console if you haven’t yet * panel Library https://console.developers.google.com/apis
  12. Google Developer Console Getting the service account key * panel

    Credentials https://console.developers.google.com/apis
  13. Google Developer Console JSON key https://console.developers.google.com/apis

  14. Google Developer Console JSON key https://console.developers.google.com/apis

  15. Google Developer Console secret.pem * https://console.developers.google.com/apis * replace character \n

    with new line
  16. Google Play Store Console Link the app to the created

    project to access the API https://play.google.com/apps/publish
  17. Google Play Store Console Grant access to the service account

    https://play.google.com/apps/publish * check out for the address present on the client_email field in the JSON key
  18. Android Publisher

  19. developers.google.com/android-publisher/api-ref/

  20. Configuring the dependency compile 'com.google.apis:google-api-services-androidpublisher:v2-rev41-1.22.0' http://bit.ly/androidpublisher_maven https://developers.google.com/android-publisher/#publishing

  21. Configuring the dependency Instantiating GoogleCredential NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport(); JacksonFactory

    json = JacksonFactory.getDefaultInstance(); Set<String> scopes = Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER); File secretFile = new File(Constants.SECRET_FILE_PATH); GoogleCredential credential = new GoogleCredential.Builder(). setTransport(http). setJsonFactory(json). setServiceAccountPrivateKeyId(Constants.KEY_ID). setServiceAccountId(Constants.SERVICE_ACCOUNT_EMAIL). setServiceAccountScopes(scopes). setServiceAccountPrivateKeyFromPemFile(secretFile). build(); https://developers.google.com/android-publisher/#publishing
  22. Configuring the dependency Instantiating GoogleCredential NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport(); JacksonFactory

    json = JacksonFactory.getDefaultInstance(); Set<String> scopes = Collections.singleton(AndroidPublisherScopes.ANDROIDPUBLISHER); File secretFile = new File(Constants.SECRET_FILE_PATH); GoogleCredential credential = new GoogleCredential.Builder(). setTransport(http). setJsonFactory(json). setServiceAccountPrivateKeyId(Constants.KEY_ID). setServiceAccountId(Constants.SERVICE_ACCOUNT_EMAIL). setServiceAccountScopes(scopes). setServiceAccountPrivateKeyFromPemFile(secretFile). build(); https://developers.google.com/android-publisher/#publishing setServiceAccountPrivateKeyId(Constants.KEY_ID). setServiceAccountId(Constants.SERVICE_ACCOUNT_EMAIL). setServiceAccountPrivateKeyFromPemFile(secretFile). private_key_id client_email private_key (.pem)
  23. Configuring the dependency Instantiating AndroidPublisher NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport(); JacksonFactory

    json = JacksonFactory.getDefaultInstance(); GoogleCredential credential = ... AndroidPublisher publisher = new AndroidPublisher.Builder(http, json, credential). setApplicationName(PACKAGE). build(); https://developers.google.com/android-publisher/#publishing
  24. AppEdits AndroidPublisher publisher = ... Edits edits = publisher.edits(); //

    insert, get, delete AppEdit appEdit = edits.insert(PACKAGE, null).execute(); String transactionId = appEdit.getId(); ... ... https://developers.google.com/android-publisher/#publishing
  25. AppEdits validate and commit AndroidPublisher publisher = ... Edits edits

    = publisher.edits(); // insert, get, delete AppEdit appEdit = edits.insert(PACKAGE, null).execute(); String transactionId = appEdit.getId(); ... ... edits.validate(PACKAGE, transactionId).execute(); edits.commit(PACKAGE, transactionId).execute(); https://developers.google.com/android-publisher/#publishing
  26. AppEdits validate and commit AndroidPublisher publisher = ... Edits edits

    = publisher.edits(); // insert, get, delete AppEdit appEdit = edits.insert(PACKAGE, null).execute(); String transactionId = appEdit.getId(); ... ... edits.validate(PACKAGE, transactionId).execute(); edits.commit(PACKAGE, transactionId).execute(); https://developers.google.com/android-publisher/#publishing { "code" : 403, "errors" : [ { "domain" : "androidpublisher", "message" : "The full description for the app is too long for language en-US.", "reason" : "fullDescriptionTooLong" } ], "message" : "The full description for the app is too long for language en-US." }
  27. AppEdits Listings Edits edits = publisher.edits(); Listings listings = edits.listings();

    ListingsListResponse listingsListResponse = listings.list(PACKAGE, transactionId).execute(); // Select the Listing you want to update Listing listing = listingsListResponse.getListings().get(...) listing.setFullDescription(description); listings.update(PACKAGE, transactionId, language, listing).execute(); // ... validate // ... commit https://developers.google.com/android-publisher/#publishing
  28. AppEdits Listings Edits edits = publisher.edits(); Listings listings = edits.listings();

    ListingsListResponse listingsListResponse = listings.list(PACKAGE, transactionId).execute(); // Select the Listing you want to update Listing listing = listingsListResponse.getListings().get(...) listing.setFullDescription(description); listings.update(PACKAGE, transactionId, language, listing).execute(); // ... validate // ... commit https://developers.google.com/android-publisher/#publishing { "fullDescription" : string, "language" : string // e.g. "en-US", "shortDescription" : string, "title" : string, "video" : string }
  29. AppEdits Uploading a new APK Apks apks = edits.apks(); FileContent

    apkContent = new FileContent(APK_MIME_TYPE, apkFile); Apk apk = apks.upload(PACKAGE, transactionId, apkContent).execute(); int version = apk.getVersionCode(); https://developers.google.com/android-publisher/#publishing
  30. AppEdits Tracks Apks apks = edits.apks(); FileContent apkContent = new

    FileContent(APK_MIME_TYPE, apkFile); Apk apk = apks.upload(PACKAGE, transactionId, apkContent).execute(); int version = apk.getVersionCode(); Tracks tracks = edits.tracks(); List<Integer> versions = Collections.singletonList(version); Track track = new Track().setVersionCodes(versions); tracks.update(PACKAGE, transactionId, trackId, track).execute(); https://developers.google.com/android-publisher/#publishing
  31. AppEdits Tracks Apks apks = edits.apks(); FileContent apkContent = new

    FileContent(APK_MIME_TYPE, apkFile); Apk apk = apks.upload(PACKAGE, transactionId, apkContent).execute(); int version = apk.getVersionCode(); Tracks tracks = edits.tracks(); List<Integer> versions = Collections.singletonList(version); Track track = new Track().setVersionCodes(versions); tracks.update(PACKAGE, transactionId, trackId, track).execute(); https://developers.google.com/android-publisher/#publishing “alpha”, “beta”, “rollout” (with userFraction), “production”
  32. AppEdits APKListing Apks apks = edits.apks(); FileContent apkContent = new

    FileContent(APK_MIME_TYPE, apkFile); Apk apk = apks.upload(PACKAGE, transactionId, apkContent).execute(); int version = apk.getVersionCode(); Tracks tracks = edits.tracks(); List<Integer> versions = Collections.singletonList(version); Track track = new Track().setVersionCodes(versions); tracks.update(PACKAGE, transactionId, trackId, track).execute(); Apklistings apklistings = edits.apklistings(); ApkListing whatsnew = new ApkListing().setRecentChanges(whatsNewDescription); apklistings.update(PACKAGE, transactionId, version, language, whatsnew).execute(); https://developers.google.com/android-publisher/#publishing
  33. Reviews AndroidPublisher publisher = ... AndroidPublisher.Reviews reviewsApi = publisher.reviews(); List<Review>

    reviews = reviewsApi.list(PACKAGE).execute().getReviews(); Review specificReview = reviewsApi.get(PACKAGE, reviewId).execute(); ... ... https://developers.google.com/android-publisher/#publishing
  34. Reviews AndroidPublisher publisher = ... AndroidPublisher.Reviews reviewsApi = publisher.reviews(); List<Review>

    reviews = reviewsApi.list(PACKAGE).execute().getReviews(); Review specificReview = reviewsApi.get(PACKAGE, reviewId).execute(); ... ... https://developers.google.com/android-publisher/#publishing { "reviewId" : string, "authorName" : string, "comments" : [ "userComment" : { "text" : string, "starRating" : int, "device" : string, "androidOsVersion" : integer, ... }, "developerComment" : { ... } ] }
  35. Reviews AndroidPublisher publisher = ... AndroidPublisher.Reviews reviewsApi = publisher.reviews(); List<Review>

    reviews = reviewsApi.list(PACKAGE).execute().getReviews(); Review specificReview = reviewsApi.get(PACKAGE, reviewId).execute(); ReviewsReplyRequest replyRequest = new ReviewsReplyRequest().setReplyText(replyText); reviewsApi.reply(PACKAGE, reviewId, replyRequest).execute(); ... ... https://developers.google.com/android-publisher/#publishing
  36. Continuous Delivery From git push to production bit.ly/googlepublisher_jenkins bit.ly/googlepublisher_gradle

  37. https://github.com/julioz/continuousdeploydemo

  38. Thanks! about.me/ julioz linkedin.com/in/ juliozynger twitter.com/ juliozynger github.com/ julioz medium.com/@juliozynger