Jak se chystáme na 100 milionů stažených aplikací

V Livesportu vyvíjíme více než 150 aplikací, které si stáhlo už přes 50 milionů sportovních nadšenců po celém světě. To mimo jiné znamená, že bychom jen těžko hledali model smartphonu nebo tabletu, na kterém naši aplikaci nikdo nespustil. Například na hodně specifickém indickém trhu to může být docela divočina — a i v takové divočině se musíme vyznat, když chceme překonat 100 milionů downloads.

I proto všechny naše aplikace píšeme v nativním kódu. Samozřejmě jsme zkusili aplikace tvořit jednotně v Xamarinu, ale výsledné kódy jsou méně efektivní. Aplikace pak běží pomaleji — to je problém vždy, ale u telefonu s nejnovější verzí Androidu a pouhými 512 MB RAM by to byl problém zásadní. Na některých trzích (například v Indii) je přitom právě tahle kombinace parametrů hodně rozšířená. Zároveň pochopitelně platí, že psát u funkčně prakticky stejných aplikací kód dvakrát by bylo neefektivní.

Základní “business logiku”, jakousi definující funkční kostru všech našich aplikací, vytvoříme jen jednou v podobě knihovny v Javě. Její kód můžeme přímo využít v aplikacích pro Android a díky J2ObjC z něj snadno vytvoříme i Objective C kód pro iOS. Tuhle code base bychom chtěli v budoucnu přepsat do Kotlinu, protože by pak nativně běžela v Androidu a díky Kotlin Native by se snadno zkompilovala pro iOS. Na stabilní verzi Kotlin Native ale ještě čekáme.

Těch zmíněných 150 aplikací jsou různé varianty Livesportu pro různé země. Neliší se jen jazykem, ale i výběrem sportů, nastavením a někdy i přizpůsobeným zobrazením.

V tomto počtu jsou navíc i speciální “jednosportové” aplikace. Takové množství aplikací samozřejmě nelze vyrábět paralelně samostatně, potřebovali bychom celou armádu programátorů, a to by ani ekonomicky nedávalo smysl. Navíc, nemalá část kódu je vždy společná pro všechny aplikace.

Ve vývoji tak pracujeme na jednotlivých balíčcích s různou funkčností a ty pak použijeme ve všech aplikacích, kde danou funkcionalitu potřebujeme. Využíváme k tomu Android Flavours a iOS Xcode Targets, ve kterých máme nadefinované složení každé ze sto padesáti aplikací.

Ve chvíli, kdy vydáváme nový release, je necháme automaticky vytvořit z již předpřipravených jednotlivých aktualizovaných součástí. Proces je to víceméně automatický a díky tomu máme hotové nové buildy všech aplikací za zhruba 14 hodin.

Díky multidimenzionalitě Flavours se najednou vybuildují nejen verze pro Google Play, ale i naše apk verze, které nabízíme ke stažení. Volně dostupné apk soubory v sobě obsahují funkce, které Google Play nepovoluje, jako jsou například odkazy na videa. Apk verze jsou tak bohatší než ty z aplikačního obchodu. Do operačního systému iOS se aplikace jinak než skrze App Store nedostane, takže tam rozšířenou verzi nenabízíme.

Zautomatizovali jsme i nahrávání nových verzí do aplikačních obchodů. Dřív nám trvalo nahrání několika desítek aplikací i celou noc, což nebylo schůdné. Proto jsme si pro upload do AppStore upravili patřičnou binárku Xcode a aplikace uploadujeme dávkově. Tenzo kód sice musíme aktualizovat ve stejném rytmu, jako Apple aktualizuje Xcode, ale i tak to spoustu času i práce ušetří.

Jenkins — nástroj na automatické buildování aplikací

Upload u Google Play býval takřka manuální záležitostí, bylo dokonce potřeba pro každou aplikaci vyplnit formulář. To jsme obešli virtuálním prohlížečem, který formuláře automatizovaně vyplňoval informacemi z databáze. Poté co Google uvolnil API, to ale funguje výborně i bez našich “hacků”.

Testování

Testování kódu i hotové aplikace by mělo být samozřejmostí vždy. V případě aplikací pro Android vstupuje do procesu neznámá v podobě specifických úprav operačních systémů a launcherů u telefonů různých výrobců.

V Livesportu proto máme několik desítek různých zařízení, na kterých probíhají UI espresso testy — tedy vlastně automatizovaná zkouška uživatelského používání aplikace.

V testovací sadě telefonů a tabletů máme jak zástupce různých firem a kategorií, tak i vytipované “problémové kusy”. Ty vždy doplňujeme na základě reportů o pádech (a jiných nefunkčnostech) aplikace, které se nám z klientských zařízení vracejí. Pokud se u některého zařízení vyskytne při vydání nové verze větší míra “crash reportů”, kupujeme dané zařízení a zjišťujeme, v čem je problém. Někdy pomůže jen úprava nastavení daného modelu, takže například u telefonů Huawei/Honor uživatele aplikace proaktivně upozorní, že si musí v nastavení telefonu u naší aplikace povolit běh na pozadí, jinak mu po uspání telefonu nebudou chodit notifikace.

Notifikace

Samotné doručování notifikací, tedy upozornění uživatele na novou informaci skrze notifikační centrum telefonu, bývá z hlediska vývoje snadné. Zpravidla se objedná u externí služby, která dodávání vybraných upozornění vybraným uživatelům zařídí. Jenže přesně takhle jsme to v Livesportu udělat nemohli, zejména kvůli zcela nedostatečné rychlosti. Například populární služba Urban Airship nám v roce 2013 garantovala doručení do dvaceti sekund, což bylo i tehdy pro naše uživatele, kteří očekávají notifikaci takřka okamžitě, nedostačující. Zároveň je odeslání notifikace tímto způsobem ukrutně drahé. Jedna notifikace jednomu uživateli tehdy vyšla zhruba na půl centu, a pokud bychom vzali v úvahu tehdejší počet našich aktivních uživatelů a vynásobili ho počtem notifikací, vyšlo by hrozivé číslo. A to bylo tehdy.

Letos — pro představu — jsme jen v průběhu finále mistrovství světa ve fotbale poslali přes 38 milionů notifikací.

Celý systém notifikací jsme si proto postavili sami a dostali se na méně než polovinu doručovacího času, který nám byl komerčně nabídnut. Ani s tím ještě nejsme zcela spokojeni, ale bohužel už výrazně narážíme na limity technologií i samotného způsobu, jak s nimi pracujeme.

Informace o jednotlivých uživatelích a jejich volbách a nastavení udržujeme v databázi MongoDB. Tuhle databázi nám aktualizují sami uživatelé tím, že uloží své nastavení v aplikaci. V téhle databázi, respektive zvolené datové struktuře, umíme i extrémně rychle vyhledávat, takže snadno zjistíme seznam uživatelů, kteří mají společný nějaký “interest”. Potud je vše v pořádku. Jenže získat data k těmto uživatelům, patřícím k jednotlivým identifikátorům, nelze dostatečně rychle.

Ono to tedy šlo, dokud jsme měli do 15 milionů uživatelů. Dnešní počet dokáže vygenerovat až 20 000 požadavků za sekundu a takový nápor už musíme řešit chytře, ne silou.

Využíváme proto server s databázovou cachí Redis, ze které lze data dostat velmi rychle, zejména díky tomu, že tam data “předehříváme” v rámci operační paměti a to navíc ve struktuře uzpůsobené pro rychlé čtení. Máme tak vlastně připravené (a stále aktualizované) seznamy uživatelů na různé kanály a kombinace interestů, aby byly při vysílání pertinentní notifikace okamžitě k dispozici a nemuselo se na ně čekat.

Budoucnost

Směrů vývoje do budoucna je kromě již zmíněných celá řada. Pro obsazení další významné části indického trhu například potřebujeme připravit naše aplikace pro systém Android Go. V Indii je hodně populární, běží totiž i na levných telefonech s malým výkonem. Aplikace pro něj pak musí být extrémně malé, zcela jinak pracují s daty a musí si vystačit s minimální operační pamětí. I proto hledáme nové mobilní vývojáře, abychom se tomuhle zajímavému segmentu mohli naplno věnovat.

V portfoliu aplikací nám také pořád chybí atletika. Opět je to zejména z kapacitních důvodů. Oproti sportům, které naše aplikace již pokrývají, vyžaduje atletika zcela jinou logiku, jinak pracuje s daty, uživatel jinak přistupuje k výsledkům atd. Lehce také experimentujeme s virtuální realitou, i když v téhle oblasti zatím nic seriózního neplánujeme. Nicméně právě VR by mohla umožnit uživatelům například kombinovat stream z daného utkání s veškerými statistikami hráčů, družstva atd. V současnosti totiž neexistuje platforma, na které by divák mohl zároveň sledovat jak zápas, tak vybrané statistické údaje.


Zaujalo tě, co v Livesportu děláme? Přidej se k nám!