Przewodnik laboratoryjny

Moja pierwsza aplikacja mobilna

Praktyczny, krok-po-kroku przewodnik prowadzący Cię przez cały cykl produkcji aplikacji — od pierwszego pomysłu aż po publikację w Google Play.

16 kroków
Zespół 3-osobowy
Android / Flutter
Semestr letni

Ten przewodnik opisuje konkretne czynności, które musisz wykonać, żeby ukończyć projekt semestralny z Laboratorium PAM i uzyskać zaliczenie. Każdy krok zawiera listę zadań, wskazówki oraz wymagania, które będą oceniane. Czytaj i realizuj zadania w podanej kolejności.

Faza 1 - Planowanie
1
Start

Wybór tematu, platformy i składu zespołu

~1–2 godziny Przed Lab 4 Product Lead

Zanim napiszesz pierwszą linię kodu, musisz wiedzieć: co budujesz, dla kogo i w jakiej technologii. Poniższe decyzje podejmij razem z zespołem.

Wskazówka Dobry temat to taki, w którym aplikacja bez smartfona (czyli np. jako strona internetowa na komputerze) straciłaby sens. Przykład: aplikacja do skanowania paragonów z aparatu — bez aparatu byłaby bezużyteczna.
2
Wymagany dokument

Dokument wymagań funkcjonalnych (SRS / User Stories)

~3–5 godzin Lab 4 — termin zgłoszenia Product Lead

SRS (Software Requirements Specification) to podstawowy dokument każdego projektu programistycznego. Opisuje co system ma robić, nie jak. W projekcie PAM zastępują go User Stories z kryteriami akceptacji.

Struktura dokumentu SRS / User Stories:

Przykład User Story z kryteriami akceptacji
US-07: Jako zalogowany użytkownik chcę dodać nowe zadanie do listy,
        aby móc śledzić swoje obowiązki.

Kryteria akceptacji:
  ✓ Formularz zawiera pole: tytuł (wymagane), opis, termin, priorytet
  ✓ Po zapisaniu zadanie pojawia się natychmiast na liście
  ✓ Walidacja: tytuł nie może być pusty (komunikat błędu)
  ✓ Zadanie jest persystowane lokalnie (działa offline)
Ważne — termin Dokument SRS / User Stories musisz zaprezentować prowadzącemu na Laboratorium nr 4. Bez zaakceptowanego tematu nie możesz kontynuować projektu.
Faza 2 - Środowisko i repozytorium
3
GitHub

Konfiguracja repozytorium GitHub

~1 godzina Dzień 1 projektu DevOps

Repozytorium GitHub to centralne miejsce pracy całego zespołu. Prawidłowa konfiguracja od początku uchroni Was przed konfliktami i problemami z historią commitów.

Zalecana struktura branchy (Git Flow)
main          ← tylko stabilny, przetestowany kod
develop       ← integracja zmian od wszystkich developerów
feature/xxx   ← nowa funkcja (np. feature/login-screen)
fix/xxx       ← poprawka błędu
release/x.y   ← przygotowanie wydania
4
Setup

Konfiguracja środowiska programistycznego

~2–3 godziny Dzień 1 projektu Frontend Dev

Zanim napiszesz kod, musisz zainstalować i skonfigurować odpowiednie narzędzia. Ten krok wykonuje każdy developer w zespole na swoim komputerze.

Platforma IDE SDK / narzędzia Wymagania sprzętowe
Android (Kotlin) Android Studio Hedgehog+ JDK 17, Android SDK 34+, Emulator 8 GB RAM (16 GB zalecane), 8 GB dysk
Flutter VS Code / Android Studio Flutter SDK 3.x, Dart, Android SDK 8 GB RAM, 10 GB dysk
Backend (Node.js) VS Code / IntelliJ Node.js 20+, npm/yarn, Docker 4 GB RAM
Fizyczne urządzenie (zalecane) Do finałowej prezentacji potrzebujesz fizycznego smartfona z Androidem. Włącz Opcje deweloperskie (7× kliknij Numer kompilacji w Ustawieniach) i aktywuj USB Debugging.
Faza 3 - Projekt i architektura
5
UI/UX

Projekt UI/UX w Figma - wireframy i prototyp

~4–6 godzin Lab 5 — termin oddania Product Lead

Prototyp w Figma pozwala "przetestować" UI bez pisania kodu. Oszczędza to czas — poprawki layoutu w Figmie zajmują minuty, a w kodzie — godziny.

Zasoby Figmy dla Androida Wyszukaj w Community: "Material 3 Design Kit" — gotowe komponenty Androida.
Gesty mobilne Zaplanuj interakcje gestami (swipe, long-press, pull-to-refresh) — to odróżnia aplikację mobilną od webowej.
6
Architektura

Szkielet projektu i architektura MVVM

~2–3 godziny Po Lab 4 Frontend Dev

Architektura MVVM (Model-View-ViewModel) to standard w aplikacjach Android. Rozdziela logikę biznesową od interfejsu użytkownika — kod jest testowalny i łatwy w utrzymaniu.

Zalecana struktura pakietów
com.example.app/
├── data/
│   ├── local/          ← Room DAO, Database, entities
│   ├── remote/         ← Retrofit API, DTOs
│   └── repository/     ← implementacje repozytoriów
├── domain/
│   ├── model/          ← modele domenowe
│   └── usecase/        ← logika biznesowa
├── ui/
│   ├── screens/        ← Composables dla każdego ekranu
│   │   ├── home/
│   │   ├── detail/
│   │   └── settings/
│   ├── components/     ← reużywalne komponenty UI
│   ├── navigation/     ← NavGraph
│   └── theme/          ← kolory, typografia, kształty
└── di/                 ← Hilt / Koin modules
Przykładowy ViewModel (Kotlin + Compose)
@HiltViewModel
class TaskViewModel @Inject constructor(
    private val taskRepository: TaskRepository
) : ViewModel() {

    private val _uiState = MutableStateFlow(TaskUiState())
    val uiState: StateFlow<TaskUiState> = _uiState.asStateFlow()

    fun loadTasks() {
        viewModelScope.launch {
            taskRepository.getTasks().collect { tasks ->
                _uiState.update { it.copy(tasks = tasks, isLoading = false) }
            }
        }
    }
}
7

Organizacja pracy na GitHub

Zanim zaczniesz pisać kod, przygotuj fundamenty dla zespołu.

Faza 4 - Implementacja
8
Nawigacja

Implementacja nawigacji i ekranów

~6–10 godzin Sprint 1 Frontend Dev

Nawigacja to "szkielet" aplikacji łączący wszystkie ekrany. W Jetpack Compose używamy Navigation Compose — deklaratywnego systemu opartego o NavController.

Szkielet NavGraph (Jetpack Compose)
@Composable
fun AppNavGraph(navController: NavHostController) {
    NavHost(navController, startDestination = Screen.Home.route) {
        composable(Screen.Home.route) {
            HomeScreen(onNavigateToDetail = { id ->
                navController.navigate(Screen.Detail.createRoute(id))
            })
        }
        composable(
            Screen.Detail.route,
            arguments = listOf(navArgument("id") { type = NavType.LongType })
        ) { backStackEntry ->
            val id = backStackEntry.arguments?.getLong("id") ?: return@composable
            DetailScreen(itemId = id, onBack = { navController.popBackStack() })
        }
    }
}
9
Dane lokalne

Lokalna baza danych (Room)

~3–5 godzin Sprint 1 Frontend Dev

Room to ORM (Object-Relational Mapper) dla SQLite na Androidzie. Umożliwia przechowywanie danych lokalnie — aplikacja działa offline i jest szybsza.

Przykładowa encja i DAO
@Entity(tableName = "tasks")
data class TaskEntity(
    @PrimaryKey(autoGenerate = true) val id: Long = 0,
    val title: String,
    val description: String,
    val isDone: Boolean = false,
    val createdAt: Long = System.currentTimeMillis()
)

@Dao
interface TaskDao {
    @Query("SELECT * FROM tasks ORDER BY createdAt DESC")
    fun getAllTasks(): Flow<List<TaskEntity>>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun insertTask(task: TaskEntity): Long

    @Delete
    suspend fun deleteTask(task: TaskEntity)
}
10
Backend i API

Backend, uwierzytelnianie i integracja z API

~8–15 godzin Sprint 1–2 DevOps Frontend Dev

Backend zapewnia serwer, bazę danych i API, z którym komunikuje się aplikacja mobilna. Możesz zbudować własny backend (Node.js, Spring Boot, Django) lub skorzystać z gotowej usługi (Firebase, Supabase).

Opcja backenduZaletyWady
Firebase (Google) Szybki start, brak konfiguracji serwera, auth gotowy Uzależnienie od usługi, ograniczone darmowe limity
Node.js + Express Pełna kontrola, łatwy do nauki Trzeba skonfigurować hosting
Supabase Open-source Firebase, PostgreSQL, REST auto-generated Nowa platforma, mniejsza dokumentacja
11
Natywne

Natywne funkcje urządzenia

~4–8 godzin Sprint 2 Frontend Dev

To wyróżnik aplikacji mobilnej, funkcje dostępne tylko na smartfonie. Musisz zaimplementować co najmniej 2 natywne funkcje.

Wymagane (min. 2 z listy):

  • GPS / lokalizacja (FusedLocationProvider)
  • Aparat (CameraX API)
  • Powiadomienia push / lokalne
  • Sensory (akcelerometr, żyroskop)
  • Biometria (odcisk palca / Face Unlock)
  • Bluetooth / BLE

Obowiązkowe kroki:

  • 1
    Zadeklaruj uprawnienia w AndroidManifest.xml.
  • 2
    Poproś o uprawnienia w runtime (nie tylko w manifest).
  • 3
    Obsłuż przypadek odmowy uprawnień przez użytkownika (graceful degradation).
  • 4
    Przetestuj na fizycznym urządzeniu (emulator często nie symuluje sensorów).
Faza 5 - Jakość i testy
Profesjonalne code review
12

Checklista dla reviewera

Kiedy kolega/koleżanka wysyła Ci Pull Request, nie klikaj od razu "Approve". Sprawdź te 4 punkty:

Jak pisać komentarze w PR?

Dobre Review pomaga budować lepszy produkt i lepszą atmosferę w zespole.

Zły komentarz (agresywny/niejasny):
"Zmień to, to jest źle napisane. Nie używamy tu pętli for."
Dobry komentarz (konstruktywny):
"W tym miejscu zamiast pętli for moglibyśmy użyć funkcji .filter { ... }. Kod byłby bardziej czytelny i zgodny z naszym stylem Kotlina. Co o tym sądzisz?"
Wskazówka: Jeśli zmiana dotyczy wizualnej części aplikacji, Reviewer ma prawo poprosić o screenshota lub nagranie ekranu (GIF) w opisie PR. To oszczędza mnóstwo czasu!

Słowniczek reviewera

Możesz używać skrótów, aby przyspieszyć komunikację:

Pamiętaj: Code Review to nie egzamin, to wspólne dbanie o jakość. Najlepsze zespoły to takie, gdzie każdy uczy się od każdego!
13
Testy

Testy jednostkowe i integracyjne

~4–6 godzin Sprint 1–2, równolegle z implementacją Frontend Dev DevOps

Testy zapewniają, że kod działa poprawnie i że przyszłe zmiany niczego nie psują. Wymagane są testy jednostkowe frontendu (≥60% pokrycia logiki) oraz testy integracyjne API (min. 5 scenariuszy).

Przykładowy test jednostkowy ViewModelu (Kotlin)
@ExperimentalCoroutinesApi
class TaskViewModelTest {
    @get:Rule val mainCoroutineRule = MainCoroutineRule()

    private val mockRepository: TaskRepository = mockk()
    private lateinit var viewModel: TaskViewModel

    @Before
    fun setup() {
        every { mockRepository.getTasks() } returns flowOf(listOf(fakeTask))
        viewModel = TaskViewModel(mockRepository)
    }

    @Test
    fun `loadTasks emits tasks in uiState`() = runTest {
        viewModel.loadTasks()
        val state = viewModel.uiState.first()
        assertEquals(1, state.tasks.size)
        assertEquals("Test Task", state.tasks[0].title)
    }
}
Konfiguracja CI/CD z GitHub Actions
14
CI/CD

Konfiguracja CI/CD z GitHub Actions

~2–3 godziny Sprint 1 — jak najwcześniej DevOps

CI/CD (Continuous Integration / Continuous Delivery) automatycznie uruchamia build i testy przy każdym Pull Requeście. Dzięki temu błędy są wykrywane natychmiast.

.github/workflows/android-ci.yml
name: Android CI

on:
  push:
    branches: [ main, develop ]
  pull_request:
    branches: [ main, develop ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build with Gradle
        run: ./gradlew assembleDebug --no-daemon

      - name: Run unit tests
        run: ./gradlew test --no-daemon

Po każdym sukcesie w Actions znajdziesz gotowy plik APK do pobrania.

Dlaczego to jest ważne?

W profesjonalnych zespołach nikt nie wysyła APK "mailem". Dzięki GitHub Actions:

  1. Zawsze masz pewność, że kod w gałęzi main jest poprawny.
  2. Product Lead może pobrać najnowszą wersję aplikacji (APK) prosto z GitHuba, by pokazać ją prowadzącemu.
  3. Eliminujesz problem "u mnie działa" — środowisko CI jest czyste i powtarzalne.
Protip na zaliczenie: Pokaż prowadzącemu zakładkę Insights -> Contributors na GitHubie oraz historię udanych buildów w Actions. To dowód na realną, systematyczną pracę zespołu!
Faza 6 — Publikacja i dokumentacja
15
Build

Podpisany build APK / AAB

~1–2 godziny Sprint 2 Frontend Dev

Każda aplikacja Android musi być podpisana cyfrowo przed dystrybucją. Google Play wymaga formatu AAB (Android App Bundle). Keystore to Twój "podpis deweloperski" — przechowuj go bezpiecznie i nigdy nie wrzucaj do repozytorium!

Bezpieczeństwo keystore Plik .jks i hasła dodaj do .gitignore. Jeśli stracisz keystore, nie będziesz mógł aktualizować aplikacji w Google Play! Trzymaj kopię zapasową w bezpiecznym miejscu (np. zaszyfrowany plik w chmurze).
16
Dokumentacja

Dokumentacja projektu

~3–4 godziny Sprint 2 — przed prezentacją Product Lead

Dobra dokumentacja to znak profesjonalnego projektu. Jest oceniana i wymagana do publikacji w Google Play. Nie zostawiaj jej na ostatnią chwilę.

17
Google Play

Publikacja w Google Play Store

~2–3 godziny Sprint 2 — przed Lab 8 Product Lead DevOps

Publikacja w Google Play to finał projektu. Wymaga jednorazowej opłaty rejestracyjnej (25 USD) i weryfikacji konta. Możesz opublikować na kanale testowym (Internal Testing) — nie wymaga pełnego przeglądu Google.

Kanał Internal Testing vs. Production Internal Testing nie wymaga recenzji ze strony Google i jest dostępny natychmiast. Wystarczy do zaliczenia projektu. Publikacja na Production może potrwać kilka dni.
18
Prezentacja

Prezentacja projektu na Lab 8

10–15 minut prezentacji Laboratoria nr 8 — ostatnie lub przedostatnie zajęcia Cały zespół

Ostatni krok — zaprezentowanie gotowej aplikacji prowadzącemu. Prezentacja powinna pokazać zarówno produkt (demo aplikacji), jak i proces (GitHub, CI/CD).

Klucz do dobrej oceny Stabilna, działająca aplikacja > efektowna ale niedokończona. Priorytetuj niezawodność podstawowych funkcji nad liczbą dodatkowych ficzerów.

Jesteś gotowy, powodzenia!

Jeśli ukończyłeś wszystkie 18 kroków, Twoja aplikacja jest gotowa do zaliczenia. Projekt semestralny PAM to realne doświadczenie produkcji oprogramowania mobilnego — umiejętności, które będą cenne w Twojej karierze.

16kroków
15+User Stories
5+ekranów
20+Issues GitHub
10+testów
1publikacja Google Play