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.json
reš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 ={this.toggleState.bind(this)} onPress={this.state.isOn === true ? title"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 eject
Ná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 start
Jeho 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-android
Tý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.gradle
v 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
compileSdkVersion
by mala vždy byť najnovšia dostupná (alebo aspoň nie veľmi pozadu)hodnota
minSdkVersion
by 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
targetSdkVersion
by 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
targetSdkVersion
aminSdkVersion
sa 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-torch
môž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 clean
vyjdite von a znova spustite preklad pomocou
$ npx react-native run-android
reš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 () { .switchState(!isOn); TorchsetIsOn(!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 () { .switchState(!isOn); TorchsetIsOn(!isOn); ; } return ( <View style={styles.container}> <Pressable onPress={toggleState}> <Image source={image} /> </Pressable> <Button ={toggleState} onPress={isOn === true ? "Turn Off" : "Turn On"} title/> </View> ; ) } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: "#fff", alignItems: "center", justifyContent: "center", , }; })