App Features
ikona aplikácie, class based komponent, inštalácia modulov tretích strán
Záznam z prednášky
Project Torch Overview
- (slide) Pokračujeme vo výrobe baterky, ktorá bude na svetlo využívať blesk zadnej kamery/fotoaparátu.
Application Icon
(slide) nastaviť ikonu aplikácie
licencia: tango icons (https://commons.wikimedia.org/wiki/Tango_icons)
nahrat do
assets/aktualizovat
app.jsonreštartnúť/znovu načítať aplikáciu v Expo kliente na zariadení/v emulátore
Class Component
(slide) ešte kým máme toho kódu málo, pozrieme sa na to, ako bude vyzerať ako trieda
takto vyzerali komponenty v React-e aj React Native donedávna
import React, { Component } from "react"; import { StyleSheet, View, Button, Image, Pressable } from "react-native"; export default class App extends Component { constructor(props) { super(props); this.state = { isOn: false, }; } toggleState() { const { isOn } = this.state; console.log(">> state change..."); this.setState({ isOn: !isOn }); } render() { const image = this.state.isOn ? require("./assets/bulb_on.png") : require("./assets/bulb_off.png"); return ( <View style={styles.container}> <Pressable onPress={this.toggleState.bind(this)}> <Image source={image} /> </Pressable> <Button onPress={this.toggleState.bind(this)} title={this.state.isOn === true ? "Turn Off" : "Turn On"} /> </View> ); } }
Houston, We Have a Problem!
(slide) Expo nemá možnosť pracovať s bleskom foťáku
expo-camera, ale robí náhľad z foťáku + ovláda blesk, ale nejde len samostatne ovládať blesk
(slide) Kedy sa teda oplatí používať Expo? Aké výhody ponúka?
- Fastest way to build React Native Apps
- You don’t need to know Native Mobile coding
- No Xcode, No Android Studio
- Publish Over The Air (OTA) Updates Instantly
- In-built access to Native APIs
- It is FREE and Open Source
(slide) A kedy sa naopak neoplatí Expo používať? Aké sú nevýhody Expa?
- Not all iOS and Android APIs are available yet
Ak to zhrnieme, tak Expo je výborné, ak ste noví vo vývoji aplikácií pre chytré zariadenia a nemáte (alebo nechcete mať) skúsenosti s natívnym vývojom aplikácií. Ak naopak skúsenosti s natívnym vývojom máte alebo potrebujete vo svojej aplikácii pracovať so súčasťami, ktoré nie sú zatiaľ podporované v Expo SDK, Expu sa vyhnite.
Ejecting from Expo
Nemusíme začínať projekt odznova, ale môžeme spraviť tzv. “eject” z Expa. To vykonáme spustením nasledovného príkazu z koreňového priečinku projektu:
$ expo ejectNásledne prejdeme krátkym dialógom, kde sa nás systém opýta na balík, v ktorom sa bude novovytváraná aplikácia pre Android aj iOS nachádzať. Ako balík uvedieme
sk.tuke.smart.torch.
Running the Project
Podobne, ako v prípade Expo, je aj tu odporúčanie nespúšťať príkazy priamo cez
npm, ale pomocou nástrojanpx.Najprv spustíme Metro Bundler príkazom:
$ npx react-native startJeho podoba síce aktuálne nebude taká sexi ako v prípade Expo-a, ale rovnako bude Metro spustené na pozadí a bude sledovať zmeny v projekte.
V novom termináli spustíme príkaz:
$ npx react-native run-androidTým dôjde:
- k spusteniu emulátora, ak nie je pripojené Android zariadenie
- k zostaveniu aplikácie pre Android
- nainštalovaniu a spusteniu aplikácie na Android zariadení.
Understanding the Android Configuration
na pozadí sa však stalo niečo, čo hneď nevidieť:
- stiahlo sa Android API 29
- aplikácia sa zostavila na základe Android API 29
(slide) pozrime sa teda na konfiguráciu Android projektu
compileSdkVersion, minSdkVersion and targetSdkVersion
(slide) Prvý súbor, ktorý nás bude zaujímať je konfiguračný súbor
build.gradlev priečinkuandroid/. Zaujímať nás bude časť označená akobuildscript:buildscript { ext { buildToolsVersion = "30.0.2" minSdkVersion = 23 compileSdkVersion = 29 targetSdkVersion = 29 } }Význam jednotlivých volieb je nasledovný:
compileSdkVersion- Táto voľba hovorí, akú verziu Android SDK má Gradle použiť pri preklade vašej aplikácie. Odporúča sa používať vždy najnovšiu verziu SDK.minSdkVersion- Označuje minimálnu verziu Android SDK, ktorú má vaša aplikácia podporovať. Rámec React Native podporuje všetky verzie Android-u od 4.1 (od API 16).targetSdkVersion- Označuje verziu Android-u, na ktorú svoju aplikáciu cielite.
To teda znamená, že:
hodnota
compileSdkVersionby mala vždy byť najnovšia dostupná (alebo aspoň nie veľmi pozadu)hodnota
minSdkVersionby mala reprezentovať verziu najstaršieho Android-u, pre ktorý chceme, aby bola aplikácia spätne kompatibilná, v našom prípade teda 23(slide) hodnota
targetSdkVersionby mala reprezentovať verziu systému, na ktorú je aplikácia cielená. A keďže spoločnosť Google stanovila, že do novembra 2020 musia mať aplikácie, ktoré sú publikované na Play Store, nastavenú cieľovú verziu SDK na hodnotu 29 a vyššie, nemáme o čom špekulovať ;)
AndroidManifest.xml
(slide)
Hodnota
targetSdkVersionaminSdkVersionsa budú nachádzať aj vo finálnej aplikácii v súboreAndroidManifest.xml. Ak ich tam pridáte ručne, budú ignorované, nakoľko ich hodnoty budú prepísané nástrojom Gradle na základe konfiguračného súborubuild.gradle.
Application Icon Again
Aplikácia sa teraz spustí bez Expo klienta. Jej funkcionalita zostala síce zachovaná, ale ak sa pozrieme na to, ako tentokrát vyzerá ikona aplikácie, tak v závislosti od rozlíšenia zariadenia môže vyzerať rozlične. To je spôsobené tým, že v prípade Android-a už záleží na tom, na akom zariadení je aplikácia spustená.
V priečinku
android/sa okrem konfigurácie a zdrojových kódov nachádzajú aj zdroje (resources) aplikácie. Medzi zdroje patrí aj ikona aplikácie, tzv. spúšťača aplikácie. Tie sa nachádzajú v priečinkuandroid/app/src/main/res/.V tomto priečinku sa nachádzajú priečinky s rozličnými postfixmi na základe rozlíšení cieľových zariadení:
- xxxhdpi (extra-extra-extra-high) ~ 640dpi
- xxhdpi (extra-extra-high) ~ 480dpi
- xhdpi (extra-high) ~ 320dpi
- hdpi (high) ~ 240dpi
- mdpi (medium) ~ 160dpi
- ldpi (low) ~ 120dpi
Aby sme sa veľmi nenamakali a neupravovali ikonu pre každý jeden typ zvlášť, môžeme na to použiť on-line nástroj Android Asset Studio. Ten obsahuje niekoľko nástrojov, pričom jedným z nich je práve nástroj na tvorbu ikon spúšťačov. Zrejme po vzore tohto online nástroja vzniklo Asset Studio, ktoré je súčasťou aj Android Studia.
Prejdeme teda do Launcher Icon Generator-a, kde nahráme vlastnú ikonu:
Keď budeme spokojní so všetkými úpravami, klikneme na tlačidlo Download ZIP. Stiahneme k sebe balík s upravenými ikonami pre jednotlivé rozlíšenia. Vo vnútri balíka sa nachádza priečinok
res/, ktorý rozbalíme cezres/priečinok v našom projekte.Poznámka
Miesto, kde definujeme, ktorá ikona sa v skutočnosti použije ako ikona aplikácie, sa nachádza v manifeste aplikácie (v súbore
AndroidManifest.xml). Konkrétne sa jedná o atribút elementu<application>v tvare:android:icon="@mipmap/ic_launcher"
Let There be Light!
(slide) React Native nevie priamo ovládať baterku
skúsime vyhľadať vhodný modul cez https://www.npmjs.com/
- react native flashlight
pouzijeme modul react-native-torch
inštalácia modulu
$ npm install --save react-native-torch $ react-native link react-native-torchmôžeme skúsiť teraz aplikáciu preložiť a spustiť
Upozornenie
Môže sa stať, že proces stuhne na časti appDebug. V tom prípade vyskúšajte:
vojdite do priečinku
android/a spustite:$ ./gradlew cleanvyjdite von a znova spustite preklad pomocou
$ npx react-native run-androidreštartnite adb server pomocou
$ adb kill-server $ adb start-server
aktualizovanie kódu pre ošetrenie stlačenia tlačidla:
import Torch from 'react-native-torch'; ... const toggleState = function () { Torch.switchState(!isOn); setIsOn(!isOn); };
Complete Solution
Dnes zmien priamo v kóde veľa nebolo, pretože sme sa venovali viac projektu a jeho nastavení. Kód výsledného komponentu bude teda vyzerať nasledovne:
import React, { useState } from "react"; import { StyleSheet, View, Button, Image, Pressable } from "react-native"; import Torch from "react-native-torch"; export default function App() { const [isOn, setIsOn] = useState(false); var image = isOn ? require("./assets/bulb_on.png") : require("./assets/bulb_off.png"); const toggleState = function () { Torch.switchState(!isOn); setIsOn(!isOn); }; return ( <View style={styles.container}> <Pressable onPress={toggleState}> <Image source={image} /> </Pressable> <Button onPress={toggleState} title={isOn === true ? "Turn Off" : "Turn On"} /> </View> ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", }, });