Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Tips and tricks du rebranding de l'app Captain ...
Search
Jeremie Martinez
December 12, 2016
Technology
1
350
Tips and tricks du rebranding de l'app Captain Train
Talk fait au PAUG le 12/12/16 en Français
Jeremie Martinez
December 12, 2016
Tweet
Share
More Decks by Jeremie Martinez
See All by Jeremie Martinez
Gradle, je t'aime, moi non plus…
jeremiemartinez
0
340
The evolution of Android notification
jeremiemartinez
5
5k
DevOps sur Android : from one git push to a Play Store release
jeremiemartinez
17
2.7k
See the Truth
jeremiemartinez
0
320
DevOps sur Android : D'un git push à une release Play Store
jeremiemartinez
5
590
Dagger 2 : Back to basics
jeremiemartinez
2
1.1k
La stack réseau Android, disponible également pour vos backs
jeremiemartinez
0
520
Other Decks in Technology
See All in Technology
Optuna DashboardにおけるPLaMo2連携機能の紹介 / PFN LLM セミナー
pfn
PRO
1
880
それでも私はContextに値を詰めたい | Go Conference 2025 / go conference 2025 fill context
budougumi0617
4
1.2k
後進育成のしくじり〜任せるスキルとリーダーシップの両立〜
matsu0228
6
2.3k
データエンジニアがこの先生きのこるには...?
10xinc
0
440
10年の共創が示す、これからの開発者と企業の関係 ~ Crossroad
soracom
PRO
1
170
「Verify with Wallet API」を アプリに導入するために
hinakko
1
230
Why Governance Matters: The Key to Reducing Risk Without Slowing Down
sarahjwells
0
110
SOC2取得の全体像
shonansurvivors
1
370
ACA でMAGI システムを社内で展開しようとした話
mappie_kochi
1
250
AI駆動開発を推進するためにサービス開発チームで 取り組んでいること
noayaoshiro
0
160
Modern_Data_Stack最新動向クイズ_買収_AI_激動の2025年_.pdf
sagara
0
200
「AI駆動PO」を考えてみる - 作る速さから価値のスループットへ:検査・適応で未来を開発 / AI-driven product owner. scrummat2025
yosuke_nagai
4
580
Featured
See All Featured
jQuery: Nuts, Bolts and Bling
dougneiner
64
7.9k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
12
1.2k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.1k
A better future with KSS
kneath
239
17k
Designing for Performance
lara
610
69k
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.6k
Typedesign – Prime Four
hannesfritz
42
2.8k
Optimising Largest Contentful Paint
csswizardry
37
3.4k
For a Future-Friendly Web
brad_frost
180
9.9k
Practical Orchestrator
shlominoach
190
11k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
358
30k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.2k
Transcript
@JeremMartinez From Captain Train… … to Trainline
None
Qu’est ce qu’une marque ?
Une icône 1
None
Des couleurs 2
Bonnes pratiques colors.xml Nommer vos couleurs selon le métier Garder
votre palette la plus petite possible Toujours faire des alias
<!-- Official colors --> <color name="accent">#01c3a7</color> <color name="primary">#21314d</color> <color name="primaryDark">#1a273d</color>
<!-- Text variants --> <color name="ct_text_primary">#323e42</color> <color name="ct_text_secondary">#8c9da1</color> <color name="ct_text_accent">#14b69f</color> <!-- Status colors --> <color name="ct_error">#e02007</color> <color name="ct_info">#0375b6</color> <color name="ct_success">#90c25b</color> <color name="ct_warning">#e87619</color>
<!-- Official colors --> <color name="accent">#01c3a7</color> <color name="primary">#21314d</color> <color name="primaryDark">#1a273d</color>
<!-- Text variants --> <color name="ct_text_primary">#323e42</color> <color name="ct_text_secondary">#8c9da1</color> <color name="ct_text_accent">#14b69f</color> <!-- Status colors --> <color name="ct_error">#e02007</color> <color name="ct_info">#0375b6</color> <color name="ct_success">#90c25b</color> <color name="ct_warning">#e87619</color>
<!-- Official colors --> <color name="accent">#01c3a7</color> <color name="primary">#21314d</color> <color name="primaryDark">#1a273d</color>
<!-- Text variants --> <color name="ct_text_primary">#323e42</color> <color name="ct_text_secondary">#8c9da1</color> <color name="ct_text_accent">#14b69f</color> <!-- Status colors --> <color name="ct_error">#e02007</color> <color name="ct_info">#0375b6</color> <color name="ct_success">#90c25b</color> <color name="ct_warning">#e87619</color>
Bonnes pratiques themes.xml Utiliser au maximum les thèmes Séparer vos
fichiers de thèmes : themes.xml styles.xml text_styles.xml
Theme
Theme Theme.CaptainTrain Theme.CaptainTrain.Exchange Theme.CaptainTrain.Cancellation
<style name="Theme.CaptainTrain" parent="Base.Theme.CaptainTrain"> <item name="colorAccent">@color/accent</item> </style> <style name="Theme.CaptainTrain.Cancellation">
<item name="colorAccent">@color/cancellation</item> </style> <style name="Theme.CaptainTrain.Exchange"> <item name="colorAccent">@color/exchange</item> </style>
None
None
<style name="Base.Theme.CaptainTrain"> <item name="colorControlNormal">?attr/colorAccent</item> </style> <style name="Theme.CaptainTrain"> <item name="colorAccent">@color/accent</item> </style>
<style name="Theme.CaptainTrain.Exchange"> <item name="colorAccent">@color/exchange</item> </style>
<style name="Base.Theme.CaptainTrain"> <item name="colorControlNormal">?attr/colorAccent</item> </style> <style name="Theme.CaptainTrain"> <item name="colorAccent">@color/accent</item> </style>
<style name="Theme.CaptainTrain.Exchange"> <item name="colorAccent">@color/exchange</item> </style>
attrs.xml <resources> <attr name="ctColorTextAccent" format="reference|color" /> </resources>
<style name="Theme.CaptainTrain" parent="Base.Theme.CaptainTrain"> <item name="colorAccent">@color/accent</item> <item name="ctColorTextAccent">@color/text_accent</item> </style> <style
name="Theme.CaptainTrain.Cancellation"> <item name="colorAccent">@color/cancellation</item> <item name="ctColorTextAccent">@color/text_cancellation</item> </style> <style name="Theme.CaptainTrain.Exchange"> <item name="colorAccent">@color/exchange</item> <item name="ctColorTextAccent">@color/text_exchange</item> </style> themes.xml
<?xml version="1.0" encoding="utf-8"?> <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:color="@color/disabled" android:state_enabled="false" />
<item android:color="?attr/ctColorTextAccent" /> </selector> text_accent.xml
attrs.xml <resources> <attr name="ctButtonStyle" format="reference" /> </resources>
<style name="Theme.CaptainTrain" parent="Base.Theme.CaptainTrain"> <item name="colorAccent">@color/accent</item> <item name="ctColorTextAccent">@color/text_accent</item> <item name="ctButtonStyle">@style/Button.Action</item> </style>
<style name="Theme.CaptainTrain.Cancellation"> <item name="colorAccent">@color/cancellation</item> <item name="ctColorTextAccent">@color/text_cancellation</item> <item name="ctButtonStyle">@style/Button.Action.Cancellation</item> </style> <style name="Theme.CaptainTrain.Exchange"> <item name="colorAccent">@color/exchange</item> <item name="ctColorTextAccent">@color/text_exchange</item> <item name="ctButtonStyle">@style/Button.Action.Exchange</item> </style>
<Button android:id="@+id/btn_pay" style="?attr/ctButtonStyle" android:layout_width="match_parent" android:layout_height="wrap_content" tools:text="Pay €456.00"/>
Attrs ne fonctionnent pas dans les drawables *Valable pré-Lollipop
Puissant mais pas magique Compile-time vs runtime Rapidement bordélique API
très verrouillée
Des drawables 3
Garder vos raws !
None
Un nom 4
Des empty-states 5
None
None
Des animations 6
None
None
http://jeremie-martinez.com/2016/09/15/train-animations/
Des liens 7
Interne www.captaintrain.com
Interne www.trainline.eu
Interne www.trainline.fr
Interne www.trainline.de
Interne www.trainline.it
Interne www.trainline.es
Integration Deeplinks SmartLock For Password Facebook Sign in Sharing Google
Sign in App Indexing
Un package name 8
No!
None
Une timeline 9
2 semaines avant …
Sur le web
Dans les emails
Le jour J …
None
AndroidManifest.xml <receiver android:enabled="true" android:exported="true" android:name="com.example.ApplicationUpdatedReceiver"> <intent-filter> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter>
</receiver>
AndroidManifest.xml <receiver android:enabled="true" android:exported="true" android:name="com.example.ApplicationUpdatedReceiver"> <intent-filter> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter>
</receiver>
AndroidManifest.xml <receiver android:enabled="true" android:exported="true" android:name="com.example.ApplicationUpdatedReceiver"> <intent-filter> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter>
</receiver>
AndroidManifest.xml <receiver android:enabled="true" android:exported="true" android:name="com.example.ApplicationUpdatedReceiver"> <intent-filter> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter>
</receiver>
AndroidManifest.xml <receiver android:enabled="true" android:exported="true" android:name="com.example.ApplicationUpdatedReceiver"> <intent-filter> <action android:name="android.intent.action.MY_PACKAGE_REPLACED" /> </intent-filter>
</receiver>
ApplicationUpdatedReceiver public class ApplicationUpdatedReceiver extends BroadcastReceiver { …
} } @Override public void onReceive(Context context, Intent intent) {
ApplicationUpdatedReceiver String action = intent.getAction(); if (TextUtils.isEmpty(action)) { return; }
switch (action) { … break; } } @Override public void onReceive(Context context, Intent intent) { case Intent.ACTION_MY_PACKAGE_REPLACED:
ApplicationUpdatedReceiver case Intent.ACTION_MY_PACKAGE_REPLACED: AppPreferences preferences = AppPreferences.from(context); int version =
preferences. getInt(PREVIOUS_APP_VERSION, VERSION_CODES.NARIM); if (version < VERSION_CODES.ONEILL) { bumpToOneill(context); version = VERSION_CODES.ONEILL; } if (version < VERSION_CODES.PENDERGAST) { bumpToPendergast(context); version = VERSION_CODES.PENDERGAST; } preferences.edit(). putInt(PREVIOUS_APP_VERSION, version). apply();
ApplicationUpdatedReceiver case Intent.ACTION_MY_PACKAGE_REPLACED: AppPreferences preferences = AppPreferences.from(context); int version =
preferences. getInt(PREVIOUS_APP_VERSION, VERSION_CODES.NARIM); if (version < VERSION_CODES.ONEILL) { bumpToOneill(context); version = VERSION_CODES.ONEILL; } if (version < VERSION_CODES.PENDERGAST) { bumpToPendergast(context); version = VERSION_CODES.PENDERGAST; } preferences.edit(). putInt(PREVIOUS_APP_VERSION, version). apply();
ApplicationUpdatedReceiver case Intent.ACTION_MY_PACKAGE_REPLACED: AppPreferences preferences = AppPreferences.from(context); int version =
preferences. getInt(PREVIOUS_APP_VERSION, VERSION_CODES.NARIM); if (version < VERSION_CODES.ONEILL) { bumpToOneill(context); version = VERSION_CODES.ONEILL; } if (version < VERSION_CODES.PENDERGAST) { bumpToPendergast(context); version = VERSION_CODES.PENDERGAST; } preferences.edit(). putInt(PREVIOUS_APP_VERSION, version). apply();
ApplicationUpdatedReceiver case Intent.ACTION_MY_PACKAGE_REPLACED: AppPreferences preferences = AppPreferences.from(context); int version =
preferences. getInt(PREVIOUS_APP_VERSION, VERSION_CODES.NARIM); if (version < VERSION_CODES.ONEILL) { bumpToOneill(context); version = VERSION_CODES.ONEILL; } if (version < VERSION_CODES.PENDERGAST) { bumpToPendergast(context); version = VERSION_CODES.PENDERGAST; } preferences.edit(). putInt(PREVIOUS_APP_VERSION, version). apply();
ApplicationUpdatedReceiver bumpToOneill(context); Notification Sauver un état pour l’écran …
Subir la rage 10
None
None
Conclusion Ça prend du temps Faire le minimum de changements
possible Vous allez oublier des choses Il y aura forcément des déçus
@JeremMartinez Questions ?