Slide 1

Slide 1 text

Continuous Deploy no Android Júlio Zynger

Slide 2

Slide 2 text

Deploy Contínuo?

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

http://bit.ly/cd_codeship

Slide 5

Slide 5 text

http://bit.ly/cd_codeship

Slide 6

Slide 6 text

http://bit.ly/cd_codeship

Slide 7

Slide 7 text

No content

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

Configuração do console

Slide 11

Slide 11 text

Google Developer Console Habilitar a Google Play Android Developer API * * crie um projeto no developer console se já não houver um com APIs configuradas * painel Visão Geral do console https://console.developers.google.com/apis

Slide 12

Slide 12 text

Google Developer Console Obtendo a service account key * painel Credenciais do console https://console.developers.google.com/apis

Slide 13

Slide 13 text

Google Developer Console JSON da chave https://console.developers.google.com/apis

Slide 14

Slide 14 text

Google Developer Console JSON da chave https://console.developers.google.com/apis

Slide 15

Slide 15 text

Google Developer Console secret.pem * https://console.developers.google.com/apis * substituição de \n por nova linha

Slide 16

Slide 16 text

Google Play Store Console Vincular o acesso à API https://play.google.com/apps/publish

Slide 17

Slide 17 text

Google Play Store Console Adicionar conta de serviço https://play.google.com/apps/publish * vincule o email do campo client_email no JSON da chave

Slide 18

Slide 18 text

No content

Slide 19

Slide 19 text

O Android Publisher

Slide 20

Slide 20 text

Google Play Developer API * ● Subscriptions and In-App Purchases API ○ In-App Products ○ Status de produtos comprados ○ Produtos recorrentes e subscriptions ● Publishing API ○ Criação e modificação dos Listings de seu app ○ Upload de novas versões do APK ○ Atribuição de APKs às Tracks do Google Play (alpha, beta, staged rollout e produção) * Limite de 200 mil requisições por dia

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

Configurando a dependência Download da biblioteca compile 'com.google.apis:google-api-services-androidpublisher:v2-rev30- 1.22.0' http://bit.ly/androidpublisher_maven https://developers.google.com/android-publisher/#publishing

Slide 23

Slide 23 text

Configurando a dependência Instanciando o GoogleCredential NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport(); JacksonFactory json = JacksonFactory.getDefaultInstance(); Set 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

Slide 24

Slide 24 text

Configurando a dependência Instanciando o GoogleCredential NetHttpTransport http = GoogleNetHttpTransport.newTrustedTransport(); JacksonFactory json = JacksonFactory.getDefaultInstance(); Set 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)

Slide 25

Slide 25 text

Configurando a dependência Instanciando o 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

Slide 26

Slide 26 text

Configurando a dependência 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

Slide 27

Slide 27 text

Configurando a dependência AppEdits - validate e 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

Slide 28

Slide 28 text

Configurando a dependência AppEdits - validate e 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." }

Slide 29

Slide 29 text

Configurando a dependência AppEdits - Listings Edits edits = publisher.edits(); Listings listings = edits.listings(); ListingsListResponse listingsListResponse = listings.list(PACKAGE, transactionId).execute(); // Selecionar o Listing que vai ser atualizado Listing listing = listingsListResponse.getListings().get(...) listing.setFullDescription(description); listings.update(PACKAGE, transactionId, language, listing).execute(); // ... validate // ... commit https://developers.google.com/android-publisher/#publishing

Slide 30

Slide 30 text

Configurando a dependência AppEdits - Listings Edits edits = publisher.edits(); Listings listings = edits.listings(); ListingsListResponse listingsListResponse = listings.list(PACKAGE, transactionId).execute(); // Selecionar o Listing que vai ser atualizado 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" : "This app is a simple demo application for developers who are interested in continuous deploy in the android platform.", "language" : "en-US", "shortDescription" : "Demo application for developers", "title" : "Continuous Deploy Demo App", "video" : "" }

Slide 31

Slide 31 text

Configurando a dependência AppEdits - upload do 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

Slide 32

Slide 32 text

Configurando a dependência 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 versions = Collections.singletonList(version); Track track = new Track().setVersionCodes(versions); tracks.update(PACKAGE, transactionId, trackId, track).execute(); https://developers.google.com/android-publisher/#publishing

Slide 33

Slide 33 text

Configurando a dependência 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 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” (com userFraction), “production”

Slide 34

Slide 34 text

Configurando a dependência AppEdits - APKListings 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 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

Slide 35

Slide 35 text

Continuous Delivery De um git push para produção bit.ly/googlepublisher_jenkins bit.ly/googlepublisher_gradle

Slide 36

Slide 36 text

Continuous Delivery De um git push para produção bit.ly/googlepublisher_jenkins bit.ly/googlepublisher_gradle

Slide 37

Slide 37 text

Demo!

Slide 38

Slide 38 text

https://github.com/julioz/continuousdeploydemo

Slide 39

Slide 39 text

http://bit.ly/android-continuous-deploy-post

Slide 40

Slide 40 text

Perguntas?