Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Behind the curtains: how Photos™ work

Behind the curtains: how Photos™ work

Daniele Bonaldo (@danybony_) and I will explore the inner works of Google Photos and how we integrated it with Android Things and get to create a smart photo boot project

Roberto Orgiu

October 27, 2018

More Decks by Roberto Orgiu

Other Decks in Programming


  1. HELLO! I am Robertoooooooo I do things Android at The

    New York Times You can find me at @_tiwiz
  2. Place your screenshot here ANDROID COMPANION APP Lets you pick

    a user, authenticate and send the token to the Android Things™ app.
  3. private val oAuthSecret = "S3cR3t11!" private val gso = GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)

    .requestEmail() .requestScopes(Scope(PHOTOS_SHARING_SCOPE), Scope(PHOTOS_READ_APPEND_SCOPE)) .requestIdToken(oAuthSecret) .build() private val client = GoogleSignIn.getClient(host, gso)
  4. val credential = GoogleAccountCredential.usingOAuth2(host, scopes).apply { selectedAccount = account.account }

    launch(UI) { val token = async { credential.token } host.showLoggedUi(token.await()) }
  5. data class AlbumListResponse( val albums: Array<AlbumResponse>, val nextPageToken: String? )

    data class AlbumResponse( val productUrl: String, val id: String, val title: String, @Json(name = "isWriteable") val writeable: Boolean )
  6. internal fun fetchAlbums(): Deferred<ArrayList<CompleteAlbum>> { return async { val albums

    = arrayListOf<CompleteAlbum>() var nextPageToken: String? = null do { val page = apiService .fetchAlbums(tokenBearer, nextPageToken).await() nextPageToken = nextPageToken .replaceWith(page.nextPageToken) albums.addAll(page.albums) } while (nextPageToken != null && nextPageToken.isNotEmpty()) return@async albums } }
  7. internal fun uploadImage(albumId: String, fileName: String, bytes: ByteArray): Deferred<ImageUploadResult> {

    return async { val token = uploadApiService .uploadMedia(tokenBearer, fileName, bytes).await() apiService .createMediaLink(tokenBearer, token.asImageUploadRequestWith(albumId, fileName) ).await() } }
  8. fun uploadMedia(token: String, fileName: String, bytes: ByteArray): Deferred<String> { val

    requestBody = RequestBody.create(MediaType.parse(OCTET_TYPE), bytes) return async { val request = Request.Builder() .url(endpoint) .addHeader(AUTHORIZATION, token) .addHeader(UPLOAD_FILENAME, fileName) .post(requestBody) .build() client.newCall(request).execute().body().string() } }
  9. An album only shows in Photos™ when it has at

    least one picture. Cannot delete a picture. You can only interact with albums you created. LESSONS LEARNED