Slide 1

Slide 1 text

Dailymotion Android App March 28th, 2019

Slide 2

Slide 2 text

Plan 2 2 1. Historique de l'app. 2. Stack tech. 3. Focus: automatisation de nos processus. 4. Focus: SQL delight.

Slide 3

Slide 3 text

The home for videos that matter 3 milliards video vues par mois 300 millions visiteurs uniques par mois 150 millions vidéos dans le catalogue CHIFFRES CLES 3

Slide 4

Slide 4 text

© 2018 CONFIDENTIAL RETROFIT 8 années d'app Android FIRST RELEASE MATERIAL DESIGN 2012 2019 2016 2015 2018 2017 2014 2013 NEON NEXT 2x 3x 4x MEDIAPLAYER EXOPLAYER WEBVIEW PLAYER GRAPHQL VOLLEY JACKSON GSON ANDROIDX MOSHI ROOM SQL DELIGHT KOTLIN PAPERDB RXJAVA COROUTINES BUTTERKNIFE SYNTHETIC PROPERTIES DAGGER SINGLE ACTIVITY ORMLITE JAVA

Slide 5

Slide 5 text

© 2018 CONFIDENTIAL Stack technique 5

Slide 6

Slide 6 text

Présentation Dailymotion Android en quelques mots... Single Activity Aucun fragment Kotlin à 75% Coroutines depuis 4 mois ≈ 58k lignes de code Android App Bundle 6 STACK TECH 6 SavedInstanceState

Slide 7

Slide 7 text

© 2018 CONFIDENTIAL STACK TECH Architecture 7 MVP Dagger Epoxy L’incontournable Introduction en Septembre 2018 Déploiement progressif Librairie d’AirBnb Gestion de RecyclerView Support du diff

Slide 8

Slide 8 text

© 2018 CONFIDENTIAL Mobile & tablette TV Modules STACK TECH 8 Partner

Slide 9

Slide 9 text

© 2018 CONFIDENTIAL Modules STACK TECH 9 Mobile Tablette Partner TV Shared Tracking Design

Slide 10

Slide 10 text

© 2018 CONFIDENTIAL Outils STACK TECH 10 •Saucelabs •HockeyApps •Braze •Firebase •Transifex •Bitrise •Jira •Slack Intégration continue GitHub User Test

Slide 11

Slide 11 text

© 2018 CONFIDENTIAL Interlude (Questions ?) 11

Slide 12

Slide 12 text

© 2018 CONFIDENTIAL Focus technique : Kinta 12

Slide 13

Slide 13 text

© 2018 CONFIDENTIAL FOCUS TECH KINTA 13 • Librairie Kotlin • Script nos workflows • Interface les outils • L’utilitaire du dev • Process d’une release Kinta : le couteau suisse • Intelligence des builds • Sauvegarde des artefacts

Slide 14

Slide 14 text

© 2018 CONFIDENTIAL Process d’une release FOCUS TECH KINTA 14 Release Beta Pre-launch Report Release Prod rollout

Slide 15

Slide 15 text

© 2018 CONFIDENTIAL Track.BETA -> { val aabFile= getAabFile(versionCode, module) //Upload aab on beta track publisherHelper.uploadBetaBundle(aabFile, prodVersionCode,lastReleaseName) //Upload WhatsNew data for this versionCode WhatsNew(publisherHelper).run(listOf(versionCode, transifex_key)) //Send slack info Slack.sendNotif("androiddev", "Version $versionCode is in beta stage") } $ kinta beta 13712 dailymotion transifex_key

Slide 16

Slide 16 text

© 2018 CONFIDENTIAL Track.BETA -> { val aabFile= getAabFile(versionCode, module) //Upload aab on beta track publisherHelper.uploadBetaBundle(aabFile, prodVersionCode,lastReleaseName) //Upload WhatsNew data for this versionCode WhatsNew(publisherHelper).run(listOf(versionCode, transifex_key)) //Send slack info Slack.sendNotif("androiddev", "Version $versionCode is in beta stage") } $ kinta beta 13712 dailymotion transifex_key

Slide 17

Slide 17 text

© 2018 CONFIDENTIAL Track.BETA -> { val aabFile= getAabFile(versionCode, module) //Upload aab on beta track publisherHelper.uploadBetaBundle(aabFile, prodVersionCode,lastReleaseName) //Upload WhatsNew data for this versionCode WhatsNew(publisherHelper).run(listOf(versionCode, transifex_key)) //Send slack info Slack.sendNotif("androiddev", "Version $versionCode is in beta stage") } $ kinta beta 13712 dailymotion transifex_key

Slide 18

Slide 18 text

© 2018 CONFIDENTIAL Track.BETA -> { val aabFile= getAabFile(versionCode, module) //Upload aab on beta track publisherHelper.uploadBetaBundle(aabFile, prodVersionCode,lastReleaseName) //Upload WhatsNew data for this versionCode WhatsNew(publisherHelper).run(listOf(versionCode, transifex_key)) //Send slack info Slack.sendNotif("androiddev", "Version $versionCode is in beta stage") } $ kinta beta 13712 dailymotion transifex_key

Slide 19

Slide 19 text

© 2018 CONFIDENTIAL Track.BETA -> { val aabFile= getAabFile(versionCode, module) //Upload aab on beta track publisherHelper.uploadBetaBundle(aabFile, prodVersionCode,lastReleaseName) //Upload WhatsNew data for this versionCode WhatsNew(publisherHelper).run(listOf(versionCode, transifex_key)) //Send slack info Slack.sendNotif("androiddev", "Version $versionCode is in beta stage") } $ kinta beta 13712 dailymotion transifex_key

Slide 20

Slide 20 text

© 2018 CONFIDENTIAL Track.RELEASE -> { //Deploy version or update the rollout publisherHelper.deployVersion(versionCode, userFraction) //Get all JIRA tickets and comment Changelog.getChangelog(versionCode, module).forEach { jiraUrl -> Jira.postComment(jiraUrl, "$versionCode is rolled out $userFraction %") } //Send slack info Slack.sendNotif("android_team", "$versionCode is rolled out $userFraction %") } $ kinta release 13712 dailymotion 5

Slide 21

Slide 21 text

© 2018 CONFIDENTIAL Track.RELEASE -> { //Deploy version or update the rollout publisherHelper.deployVersion(versionCode, userFraction) //Get all JIRA tickets and comment Changelog.getChangelog(versionCode, module).forEach { jiraUrl -> Jira.postComment(jiraUrl, "$versionCode is rolled out $userFraction %") } //Send slack info Slack.sendNotif("android_team", "$versionCode is rolled out $userFraction %") } $ kinta release 13712 dailymotion 5

Slide 22

Slide 22 text

© 2018 CONFIDENTIAL Track.RELEASE -> { //Deploy version or update the rollout publisherHelper.deployVersion(versionCode, userFraction) //Get all JIRA tickets and comment Changelog.getChangelog(versionCode, module).forEach { jiraUrl -> Jira.postComment(jiraUrl, "$versionCode is rolled out $userFraction %") } //Send slack info Slack.sendNotif("android_team", "$versionCode is rolled out $userFraction %") } $ kinta release 13712 dailymotion 5

Slide 23

Slide 23 text

© 2018 CONFIDENTIAL Track.RELEASE -> { //Deploy version or update the rollout publisherHelper.deployVersion(versionCode, userFraction) //Get all JIRA tickets and comment Changelog.getChangelog(versionCode, module).forEach { jiraUrl -> Jira.postComment(jiraUrl, "$versionCode is rolled out $userFraction %") } //Send slack info Slack.sendNotif("android_team", "$versionCode is rolled out $userFraction %") } $ kinta release 13712 dailymotion 5

Slide 24

Slide 24 text

© 2018 CONFIDENTIAL Focus technique : SQL Delight 24

Slide 25

Slide 25 text

© 2018 CONFIDENTIAL SQL delight FOCUS TECH 25 1. Librairie square 2. Génération automatique de code Kotlin depuis du SQL. 3. Version 1.0 annoncée le 8 janvier https://github.com/square/sqldelight

Slide 26

Slide 26 text

© 2018 CONFIDENTIAL -- build.gradle buildscript { ext.kotlin_version = Versions.kotlin repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:3.3.2' classpath "com.squareup.sqldelight:gradle-plugin:${Versions.sqldelight}" } } dependencies { implementation " com.squareup.sqldelight:android-driver:1.1.1" } apply plugin: "com.squareup.sqldelight" Configuration

Slide 27

Slide 27 text

© 2018 CONFIDENTIAL -- src/main/sql/com/…/OfflineVideo.sq CREATE TABLE offlineVideo ( xid TEXT NOT NULL, title TEXT NOT NULL, duration REAL, [..more..] ); selectAll: SELECT * FROM offlineVideo; selectAllMatchingState: SELECT * FROM offlineVideo WHERE state = ?; insertVideo: INSERT OR REPLACE INTO offlineVideo VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?); delete: DELETE FROM offlineVideo WHERE xid = ?; -- build/generated/…/OfflineVideo.kt interface OfflineVideo { val xid: String val title: String val duration: Double? … data class Impl(…) } -- build/generated/…/OfflineVideoQueries.kt class OfflineVideoQueries(private val database: Database, private val driver: SqlDriver) : Transacter(driver) { fun selectAll(): Query fun selectAllMatchingState(state: SyncState?): Query fun delete(xid: String) }

Slide 28

Slide 28 text

© 2018 CONFIDENTIAL val driver = AndroidSqliteDriver(Database.Schema, applicationContext, »videos.db") val database = Database( driver = driver, offlineVideoAdapter = OfflineVideo.Adapter() ) val query = database.offlineVideoQueries.selectAll() val offlineVideoList:List = query.executeAsList() Utilisation

Slide 29

Slide 29 text

© 2018 CONFIDENTIAL @Entity data class User( @PrimaryKey var uid: Int, @ColumnInfo(name = "first_name") var firstName: String?, @ColumnInfo(name = "last_name") var lastName: String?, @ColumnInfo(name = "email") var lastName: String? ) val MIGRATION_2_3 = object : Migration(2, 3) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("ALTER TABLE Book ADD COLUMN email TEXT") } } Migrations Room

Slide 30

Slide 30 text

© 2018 CONFIDENTIAL -- src/main/sql/com/…/1.sqm ALTER TABLE offlineVideo ADD COLUMN partner INTEGER NOT NULL; -- src/main/sql/com/…/OfflineVideo.sq CREATE TABLE offlineVideo ( [..more..] partner INTEGER NOT NULL, ); -- build/generated/…/OfflineVideo.kt interface OfflineVideo { val xid: String val title: String val duration: Double? val partner: Integer … data class Impl(…) } Migrations SQL Delight

Slide 31

Slide 31 text

© 2018 CONFIDENTIAL -- build.gradle buildscript { ext.kotlin_version = Versions.kotlin repositories { mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:3.3.2' classpath "com.squareup.sqldelight:gradle-plugin:${Versions.sqldelight}" } } dependencies { implementation "com.squareup.sqldelight:ios-driver:1.1.1" } -- File.kt val driver = NativeSqliteDriver(Database.Schema,"videos.db") Multiplateforme

Slide 32

Slide 32 text

© 2018 CONFIDENTIAL SQL delight FOCUS TECH 32 • Un seul schema • Vérification du SQL à la compilation • Plugin Android Studio • Coloration syntaxique • Autocomplete • Multiplateforme

Slide 33

Slide 33 text

© 2018 CONFIDENTIAL La suite… • Modularisation • Coroutines • Plus de tests automatiques • Multiplatform ? • … • Design System!

Slide 34

Slide 34 text

© 2018 CONFIDENTIAL Questions ? 34

Slide 35

Slide 35 text

© 2018 CONFIDENTIAL Annexes FOCUS TECH 35 • https://www.meetup.com/fr-FR/Android- Paris/events/256368406/