Przejdź do treści
School IT / Przestrzeń do nauki

school-it.pl // android + kotlin // rozdział 1 // lekcja 01

Android Studio i pierwsza aplikacja

Aplikacja na telefon składa się z dwóch części: wyglądu zapisanego w pliku XML i kodu w Kotlinie, który ten wygląd ożywia. W tej lekcji utworzysz pierwszy projekt w Android Studio, poznasz pliki, z których się składa, uruchomisz go na wirtualnym telefonie i zbudujesz własną wizytówkę — ekran z twoimi danymi.

Kotlin XML Android Studio emulator Activity onCreate findViewById 3 × 45 min
CEL LEKCJI

Czego się dziś nauczysz

  • Utworzysz projekt Empty Views Activity w Android Studio.
  • Wskażesz pliki odpowiedzialne za wygląd, kod i ustawienia aplikacji.
  • Uruchomisz aplikację na emulatorze.
  • Zbudujesz ekran z kilku napisów w pliku XML.
  • Zmienisz napis z kodu Kotlin za pomocą findViewById.
TEORIA

Narzędzia

Do pisania aplikacji na Androida potrzebujesz jednego programu — Android Studio. Instalator dociąga resztę. Warto jednak wiedzieć, co jest czym, bo komunikaty o błędach używają tych nazw:

NazwaDo czego służyKiedy o niej usłyszysz
Android StudioEdytor kodu i wyglądu, uruchamianie, wyszukiwanie błędów.Cały czas — to twoje środowisko pracy.
Android SDKBiblioteki Androida i narzędzia do budowania aplikacji.„SDK platform not installed” — brakuje wersji Androida.
GradleProgram, który buduje aplikację z twoich plików.„Gradle sync failed”, przycisk Sync Now.
EmulatorWirtualny telefon na komputerze.Okno Device Manager, wybór urządzenia przed uruchomieniem.

Podgląd to jeszcze nie aplikacja

Android Studio pokazuje podgląd ekranu już podczas pisania XML. To tylko rysunek. Aplikacja działa naprawdę dopiero na emulatorze albo telefonie — tam też wykonuje się kod Kotlin.

TEORIA

Nowy projekt

W Android Studio: File → New → New Project… (na ekranie powitalnym: New Project). Kreator ma dwa kroki.

Krok 1 — szablon. W kategorii Phone and Tablet wybierz Empty Views Activity. Uważaj na podobnie nazwany Empty Activity: ten używa Jetpack Compose, czyli zupełnie innego sposobu budowania ekranu, i nie ma plików XML z wyglądem.

Krok 2 — ustawienia:

PoleWpiszZnaczenie
NameWizytowkaNazwa aplikacji i folderu projektu. Bez polskich znaków i spacji.
Package namepl.schoolit.wizytowkaUnikalny identyfikator aplikacji — odwrócony adres strony + nazwa.
Save locationtwój folderMiejsce na dysku. Unikaj ścieżek z polskimi znakami.
LanguageKotlinJęzyk kodu.
Minimum SDKAPI 24Najstarszy Android, na którym aplikacja się uruchomi (Android 7.0).
Build configuration languageKotlin DSLJęzyk plików Gradle — zostaw domyślny.

Po Finish Android Studio pobiera potrzebne pliki i synchronizuje projekt. Przy pierwszym projekcie trwa to kilka minut — postęp widać na dolnym pasku. Nie zmieniaj niczego, dopóki synchronizacja się nie skończy.

TEORIA

Pliki projektu

Po lewej stronie jest panel Project. Ustaw nad nim widok Android — pokazuje tylko pliki, które edytujesz. Najważniejsze są cztery:

app/
├── manifests/
│   └── AndroidManifest.xmlspis ekranów i ustawień aplikacji
├── kotlin+java/
│   └── pl.schoolit.wizytowka/
│       └── MainActivity.ktkod ekranu
└── res/zasoby (resources)
    ├── layout/
    │   └── activity_main.xmlwygląd ekranu
    └── values/
        └── strings.xmlteksty (lekcja 02)
PlikZa co odpowiada
activity_main.xmlWygląd: jakie kontrolki są na ekranie, jakie mają rozmiary, kolory i teksty. To opis, a nie polecenia wykonywane po kolei.
MainActivity.ktZachowanie: co się dzieje po uruchomieniu ekranu i po kliknięciach.
AndroidManifest.xmlSpis ekranów aplikacji, nazwa, ikona, uprawnienia. Tu jest zapisane, który ekran otwiera się po kliknięciu ikony.
build.gradle.kts (Module :app)Ustawienia budowania: minimalne API, dodatkowe biblioteki.

Ekran aplikacji to w Androidzie aktywność (Activity). Jedna aktywność = jeden plik Kotlin + jeden plik XML. Aplikacja z trzema ekranami ma trzy aktywności — tym zajmiemy się w rozdziale 8.

Trzy widoki pliku XML

Nad otwartym plikiem activity_main.xml po prawej są przyciski Code, Split i Design. W kursie pracujemy w trybie Split: po lewej piszesz XML, po prawej od razu widzisz podgląd.

TEORIA

Jak startuje aplikacja

Gdy dotkniesz ikony aplikacji, Android sprawdza w manifeście, który ekran jest startowy, tworzy tę aktywność i wywołuje jej metodę onCreate. To w niej ekran dostaje swój wygląd:

ikona
użytkownik
uruchamia aplikację
→
AndroidManifest
ekran startowy:
MainActivity
→
onCreate
setContentView(
R.layout.activity_main)
→
ekran
kontrolki z XML
widać na telefonie

setContentView(R.layout.activity_main) czyta plik activity_main.xml, tworzy z niego kontrolki i pokazuje je. R to klasa, którą Android Studio generuje samo — zawiera numer każdego zasobu: R.layout.activity_main to plik wyglądu, R.id.tvPowitanie to kontrolka o identyfikatorze tvPowitanie.

Gdy kod ma coś zmienić na ekranie, najpierw musi znaleźć kontrolkę. Służy do tego findViewById — „znajdź widok po identyfikatorze”:

MainActivity.kt — fragment onCreate
setContentView(R.layout.activity_main)                    // 1. zbuduj ekran z XML
val tvPowitanie = findViewById<TextView>(R.id.tvPowitanie) // 2. znajdź napis
tvPowitanie.text = "Cześć!"                               // 3. zmień jego tekst

W nawiasach ostrych <TextView> mówisz, jakiego rodzaju kontrolki szukasz — wtedy Kotlin wie, że ma ona właściwość text. Kolejność jest ważna: kontrolki istnieją dopiero po setContentView.

TEORIA

Szablon i nasze uproszczenie

Nowy projekt zawiera taki plik MainActivity.kt:

MainActivity.kt — tak wygląda szablon Android Studio
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        enableEdgeToEdge()
        setContentView(R.layout.activity_main)
        ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
            insets
        }
    }
}

Nowe Androidy rysują aplikację na całym ekranie — także pod paskiem stanu (godzina, bateria) i pod paskiem nawigacji. Linie z enableEdgeToEdge i ViewCompat odsuwają treść od tych pasków, żeby nic się pod nimi nie schowało.

W kursie zamiast tych linii używamy jednego atrybutu w XML — android:fitsSystemWindows="true" w głównym układzie. Efekt jest ten sam, a w onCreate zostaje tylko to, co ważne:

MainActivity.kt — wersja kursowa
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}
12:30
Jan Kowalski
Klasa 3TP
bez fitsSystemWindows:
napis wchodzi pod pasek stanu
12:30
Jan Kowalski
Klasa 3TP
z fitsSystemWindows=”true”:
treść zaczyna się pod paskiem

atrybut odsuwa treść od pasków systemu — tak samo jak kod z szablonu

fitsSystemWindows zajmuje padding

Ten atrybut działa w ten sposób, że ustawia układowi padding równy wysokości pasków. Jeśli w tym samym elemencie wpiszesz android:padding="16dp", twój padding zostanie zastąpiony. Dlatego odstęp od krawędzi ekranu w głównym układzie dajemy przez android:layout_margin="16dp".

TEORIA

Emulator i uruchamianie

  1. Otwórz Device Manager (ikona telefonu na prawym pasku albo Tools → Device Manager).
  2. Jeśli lista jest pusta: + → Create Virtual Device → wybierz telefon (np. Pixel) → obraz systemu z najnowszym stabilnym API (pobierz go strzałką) → Finish.
  3. Na górnym pasku Android Studio wybierz to urządzenie z listy i kliknij zielony trójkąt Run 'app’ (Shift+F10).
  4. Pierwsze uruchomienie emulatora trwa dłużej. Nie zamykaj go między kolejnymi uruchomieniami — następne będą szybkie.

Zamiast emulatora możesz użyć własnego telefonu: w ustawieniach telefonu włącz Opcje programisty (siedem dotknięć „Numer kompilacji” w Informacjach o telefonie), w nich Debugowanie USB, podłącz kabel i zaakceptuj komunikat na telefonie.

Okno na dole ekranuCo w nim znajdziesz
BuildBłędy kompilacji — kod jest źle napisany i aplikacja w ogóle się nie uruchomi. Kliknięcie błędu przenosi do linii.
LogcatKomunikaty z działającej aplikacji. Gdy aplikacja się zamyka, szukaj tu czerwonego wpisu FATAL EXCEPTION — kilka linii niżej jest nazwa twojego pliku i numer linii.
PRZYKŁAD

Wizytówka ucznia

Ekran z danymi ucznia: imię i nazwisko, klasa, szkoła i zainteresowania. Wszystko to opisuje XML. Najwyższy napis jest w XML pusty — wpisuje go kod Kotlin w onCreate, żeby było widać, że kod naprawdę działa.

12:30
Cześć! To moja pierwsza aplikacja.
Jan Kowalski
Klasa 3TP · technik programista
Szkoła: ZSMI w Lęborku
Zainteresowania
gry komputerowe, robotyka, rower
aplikacja na emulatorze

pierwsza linia pochodzi z kodu Kotlin, reszta — z pliku XML

Przygotowanie projektu

  1. Utwórz projekt Empty Views Activity z ustawieniami z tabeli wyżej i poczekaj na koniec synchronizacji.
  2. Uruchom projekt bez żadnych zmian. Na ekranie zobaczysz „Hello World!”. Jeśli to działa, środowisko jest gotowe — ewentualne późniejsze błędy będą w twoim kodzie, a nie w instalacji.
  3. Podmień całą zawartość activity_main.xml i MainActivity.kt na kod poniżej. Pierwszą linię package … zostaw taką, jaką utworzył twój projekt.
res/layout/activity_main.xml — pełny plik
<?xml version="1.0" encoding="utf-8"?>
<!-- LinearLayout układa kontrolki jedna pod drugą (szczegóły w lekcji 02) -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:layout_margin="16dp"
    android:fitsSystemWindows="true">

    <!-- pusty napis — tekst wpisze kod Kotlin -->
    <TextView
        android:id="@+id/tvPowitanie"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textSize="16sp"
        android:textStyle="italic"
        android:textColor="#6750A4" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Jan Kowalski"
        android:textSize="28sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Klasa 3TP · technik programista"
        android:textSize="18sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Szkoła: ZSMI w Lęborku"
        android:textSize="18sp" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Zainteresowania"
        android:textSize="16sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="gry komputerowe, robotyka, rower"
        android:textSize="16sp" />

</LinearLayout>
MainActivity.kt — pełny plik
package pl.schoolit.wizytowka

import android.os.Bundle
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // znajdujemy napis po identyfikatorze i wpisujemy do niego tekst
        val tvPowitanie = findViewById<TextView>(R.id.tvPowitanie)
        tvPowitanie.text = "Cześć! To moja pierwsza aplikacja."
    }
}

Co dzieje się po kolei

  • Plik XML ma jeden główny element LinearLayout, a w nim sześć napisów TextView. Pojawią się na ekranie jeden pod drugim, w kolejności z pliku.
  • Pierwszy napis ma identyfikator android:id="@+id/tvPowitanie". Znak + oznacza „utwórz nowy identyfikator”. Pozostałe napisy nie mają id — kod ich nie zmienia, więc go nie potrzebują.
  • layout_width i layout_height musi mieć każda kontrolka: match_parent to „na całą dostępną szerokość”, wrap_content — „tyle, ile potrzebuje treść”.
  • Rozmiar tekstu podajemy w sp, a odstępy w dp. Obie jednostki dopasowują się do gęstości ekranu, więc napis ma podobną wielkość na każdym telefonie.
  • W onCreate najpierw setContentView buduje ekran, potem findViewById znajduje pusty napis, a przypisanie do text zmienia jego treść.
  • Linie import … na górze mówią Kotlinowi, gdzie są używane klasy. Gdy wpiszesz nową klasę i podświetli się na czerwono, kliknij ją i naciśnij Alt+Enter → Import.

Sprawdź trzy rzeczy

  1. Przełącz plik XML w tryb Split. Pierwszy napis w podglądzie jest pusty, a na emulatorze — wypełniony. Podgląd nie wykonuje kodu Kotlin.
  2. Przenieś dwie linie z findViewById nad setContentView. Aplikacja zamknie się zaraz po starcie. Otwórz Logcat i znajdź FATAL EXCEPTION. Przywróć kolejność.
  3. Obróć emulator (przyciski obrotu na jego pasku bocznym). Ekran ułoży się poziomo, a tekst z kodu nadal będzie widoczny — onCreate wykonało się ponownie.
ELEMENTY WBUDOWANE

Zestawienie elementów

ElementTypCo robi
AppCompatActivityklasaKlasa bazowa ekranu; MainActivity po niej dziedziczy.
onCreate(savedInstanceState)metodaWywoływana przez Androida przy tworzeniu ekranu.
super.onCreate(…)wywołanieNajpierw robi swoją pracę klasa bazowa. Musi być pierwszą linią.
setContentView(R.layout.…)metodaBuduje ekran z pliku XML.
findViewById<Typ>(R.id.…)metodaZnajduje kontrolkę po identyfikatorze.
Rklasa generowanaNumery zasobów: R.layout, R.id, R.string…
<TextView> / .textkontrolkaNapis; właściwość text odczytuje i zmienia treść.
android:id="@+id/nazwa"atrybutNadaje kontrolce identyfikator.
match_parent / wrap_contentwartośćRozmiar: jak rodzic / jak treść.
dp, spjednostkiOdstępy i rozmiary / rozmiar tekstu.
android:fitsSystemWindows="true"atrybutOdsuwa treść od paska stanu i nawigacji.
CZĘSTE BŁĘDY

Zanim utkniesz

ObjawPrzyczyna i poprawka
W projekcie jest setContent { … } i brak folderu layoutWybrano szablon Empty Activity (Compose). Utwórz projekt jeszcze raz z Empty Views Activity.
Unresolved reference: tvPowitanieBrak android:id="@+id/tvPowitanie" w XML albo literówka w nazwie. Wielkość liter ma znaczenie.
Aplikacja zamyka się zaraz po starciefindViewById przed setContentView, albo id z innego pliku XML. Szczegóły w Logcat.
Unresolved reference: RBłąd w którymś pliku XML — Android Studio nie wygenerował klasy R. Najpierw popraw błędy XML (okno Build).
Przycisk Run jest szaryTrwa synchronizacja Gradle albo nie wybrano urządzenia.
Treść pod paskiem stanuBrak android:fitsSystemWindows="true" w głównym układzie.
Zmieniona linia package na górze MainActivity.ktKlasa trafia do innego pakietu niż w projekcie — pojawia się Unresolved reference: R albo aplikacja nie startuje. Linia package ma zostać z twojego projektu.
ZADANIA

Zadania

Zadania 1–3 wykonaj w projekcie z lekcji, zadania 4–6 w nowych projektach Empty Views Activity. Wskazówkę otwórz dopiero wtedy, gdy utkniesz.

ZAD 1Moja wizytówka★☆☆

Wpisz do wizytówki swoje dane. Dodaj dwa napisy: „Ulubiony przedmiot: …” i „Kim chcę zostać: …”. Uruchom aplikację i pokaż ją nauczycielowi na emulatorze.

pokaż wskazówkę
  • Skopiuj cały blok <TextView … /> i zmień tylko android:text.
ZAD 2Kolory i rozmiary★☆☆

Imię i nazwisko ma być w kolorze ciemnoniebieskim (#0D47A1) i rozmiarze 32sp, a napis „Zainteresowania” — wyśrodkowany. Dodaj nad imieniem odstęp 32dp.

pokaż wskazówkę
  • Kolor tekstu: android:textColor, wyśrodkowanie tekstu w napisie: android:gravity="center", odstęp nad kontrolką: android:layout_marginTop.
ZAD 3Dwa napisy z kodu★☆☆

Dodaj na dole wizytówki pusty napis z identyfikatorem tvStopka. W onCreate wpisz do niego „Wizytówka wykonana w Android Studio”. Zmień też z kodu tekst imienia i nazwiska — będzie potrzebne mu id.

pokaż wskazówkę
  • Każda kontrolka, którą zmieniasz z kodu, potrzebuje własnego id i własnego findViewById.
ZAD 4Plan dnia★★☆

Nowy projekt PlanDnia. Tytuł „Poniedziałek” i osiem napisów z lekcjami: „1. 8:00 — Matematyka” itd. Lekcje informatyczne mają zielony kolor tekstu. Pod listą lekcji napis z kodu: „Lekcji: 8”.

pokaż wskazówkę
  • Jeśli lekcje nie zmieszczą się na ekranie — to dobry moment, żeby zauważyć, że LinearLayout sam nie przewija. Przewijanie poznasz w lekcji 03.
ZAD 5Szyld sklepu★★☆

Nowy projekt: ekran wymyślonego sklepu. Nazwa sklepu wyśrodkowana, duża, pogrubiona. Pod nią godziny otwarcia na każdy dzień tygodnia, adres i telefon. Tło głównego układu ma kolor #FFF8E1. Z kodu ustaw napis „Dziś otwarte do 18:00”.

pokaż wskazówkę
  • Tło: android:background="#FFF8E1" w LinearLayout. Tekst wyśrodkowany w całej szerokości: match_parent + android:gravity="center".
ZAD 6Detektyw błędów★★★

W kopii projektu z lekcji wprowadź po kolei pięć błędów (za każdym razem tylko jeden): literówka w R.id; usunięty > zamykający znacznik w XML; findViewById przed setContentView; findViewById<TextView> z identyfikatorem nieistniejącym w tym XML, ale istniejącym w innym pliku układu; usunięty import android.widget.TextView. Dla każdego zapisz w tabeli: czy aplikacja się zbudowała, w którym oknie (Build czy Logcat) był komunikat i jak brzmiała jego najważniejsza linia.

pokaż wskazówkę
  • Błędy kompilacji zatrzymują budowanie (okno Build). Błędy działania pozwalają zbudować aplikację, ale zamykają ją na telefonie (okno Logcat, filtr: nazwa twojego pakietu). Drugi plik układu utworzysz przez prawy przycisk na res/layout → New → Layout Resource File.
PODSUMOWANIE

Co trzeba zapamiętać

  • Nowy projekt w kursie to zawsze Empty Views Activity, język Kotlin, minimalne API 24.
  • Wygląd jest w res/layout/activity_main.xml, zachowanie w MainActivity.kt, spis ekranów w AndroidManifest.xml.
  • onCreate uruchamia się przy tworzeniu ekranu; setContentView buduje ekran z XML.
  • Kontrolkę zmienianą z kodu oznacz android:id="@+id/…" i znajdź przez findViewById — zawsze po setContentView.
  • Błędy pisowni pokazuje okno Build, awarie działającej aplikacji — Logcat.

Dokumentacja: Tworzenie projektu, Emulator i urządzenia wirtualne, Aktywności.

Postęp zapisuje się w tej przeglądarce.