Skip to content

🛠️ Mini Proyek: Data, Jaringan & Perangkat

⭐⭐⭐ · 6–8 jam

Apa yang akan kamu bangun

Pelacak Kualitas Udara — aplikasi yang membaca posisimu lewat GPS, mengambil data kualitas udara terdekat dari API publik, lalu menyimpan setiap pembacaan ke basis data lokal sehingga kamu punya riwayat harian yang bisa dibuka kapan saja, termasuk saat sedang tidak ada sinyal.

Bagian II hanya berisi tiga bab, tetapi ketiganya jarang muncul bersamaan di aplikasi latihan biasa. Aplikasi ini memaksa ketiganya bertemu di satu alur: GPS memberi koordinat (Bab 16), koordinat itu menjadi parameter permintaan HTTP (Bab 14), dan hasilnya harus bertahan setelah aplikasi ditutup (Bab 15). Kalau salah satu gagal, kamu harus memutuskan apa yang ditampilkan — dan itu justru inti pelajarannya.

Untuk sumber datanya, pakai API kualitas udara publik yang gratis dan tidak menuntut proses pendaftaran berbelit. OpenAQ menyediakan data stasiun pemantau berdasarkan koordinat; API cuaca mana pun yang menyertakan indeks kualitas udara juga sah dipakai. Yang penting bukan API-nya, melainkan bagaimana kamu memperlakukan responsnya: memeriksa kode status sebelum mengurai, memberi nilai cadangan pada field yang bisa saja tidak ada, dan mengubah SocketException menjadi kalimat yang dimengerti manusia.

Satu fitur sengaja ditambahkan supaya kamera ikut terpakai secara wajar: setiap entri riwayat boleh dilampiri satu foto catatan — langit saat pengukuran, tangkapan layar, apa pun. Ini membawa masalah menarik yang dibahas di Bab 15: foto dari kamera mendarat di direktori sementara yang bisa dibersihkan sistem kapan saja, jadi kamu harus menyalinnya ke direktori dokumen dan menyimpan jalurnya, bukan gambarnya, ke dalam SQLite.

Prasyarat

Selesaikan dulu:

Requirement fungsional

  • Tombol "Ukur sekarang" mengambil lokasi perangkat, memanggil API, dan menampilkan hasilnya: nilai indeks, kategori (baik/sedang/tidak sehat), dan nama lokasi terdekat.
  • Setiap pembacaan yang berhasil otomatis tersimpan ke basis data lokal bersama waktu dan koordinatnya.
  • Layar riwayat menampilkan seluruh pembacaan terurut dari yang terbaru, dan bisa dibuka penuh tanpa koneksi internet.
  • Dari layar detail sebuah entri, pengguna bisa melampirkan satu foto dari kamera. Foto muncul di entri itu dan tetap ada setelah aplikasi ditutup lalu dibuka lagi.
  • Menghapus entri riwayat juga menghapus berkas fotonya dari penyimpanan.
  • Aplikasi menampilkan ringkasan sederhana dari riwayat: rata-rata tujuh hari terakhir, plus nilai tertinggi dan terendah. Boleh berupa deretan batang yang kamu gambar sendiri dengan Container — tidak perlu pustaka grafik.
  • Keempat keadaan ditangani dengan tampilan yang berbeda: sedang memuat, gagal, kosong, dan ada data.
  • Kalau izin lokasi ditolak permanen, aplikasi menjelaskan situasinya dan menyediakan tombol menuju pengaturan sistem — bukan sekadar diam atau meminta ulang tanpa henti.

Requirement teknis

  • Seluruh kode HTTP berada di kelas layanan terpisah. Widget tidak boleh mengimpor package:http/http.dart.
  • Model punya fromJson dan toJson, dan melewati as num sebelum .toDouble() saat mengurai angka dari JSON.
  • Setiap permintaan jaringan memakai .timeout(), dan SocketException serta TimeoutException diterjemahkan menjadi pesan berbahasa Indonesia yang bisa ditindaklanjuti.
  • Basis data dibuka sekali lewat pola singleton, dengan jalur yang dibangun memakai p.join().
  • Semua kueri yang menyertakan nilai memakai whereArgs. Tidak ada penyambungan string ke dalam SQL, satu pun.
  • DateTime disimpan sebagai millisecondsSinceEpoch, dan foto disimpan sebagai jalur berkas setelah disalin ke direktori dokumen.
  • Foto diperkecil pada titik pengambilan dengan maxWidth dan imageQuality.
  • Ketersediaan layanan GPS dan status izin diperiksa sebagai dua hal terpisah, karena keduanya bisa gagal sendiri-sendiri.
  • Setiap await yang diikuti sentuhan ke context atau setState didahului pemeriksaan mounted.

Checklist penerimaan

  • Menyalakan mode pesawat, membuka aplikasi, dan membuka riwayat: seluruh data lama tetap tampil, dan tombol ukur memberi pesan gagal yang jelas — bukan layar merah.
  • Menutup paksa aplikasi lalu membukanya lagi: riwayat dan foto masih utuh.
  • Menolak izin lokasi, lalu memberikannya lagi dari pengaturan: aplikasi pulih tanpa perlu diinstal ulang.
  • flutter analyze bersih, dan tidak ada print yang tertinggal di jalur kode utama.
  • Kamu bisa menunjukkan di kode, dalam waktu kurang dari satu menit, tempat respons API diubah menjadi objek model.

Tantangan ekstra (opsional)

  • Tambahkan notifikasi lokal terjadwal yang mengingatkan mengukur setiap pagi pada jam yang bisa diatur pengguna.
  • Simpan pengaturan (ambang peringatan, jam pengingat) di SharedPreferences, dan biarkan aplikasi menandai pembacaan yang melewati ambang itu.
  • Tambahkan kolom catatan ke tabel — lalu naikkan version basis data dan tulis onUpgrade yang benar, sehingga pengguna lama tidak kehilangan datanya.

Terjebak?

Kalau macet, pisahkan masalahnya. Uji dulu pemanggilan API dengan koordinat tetap yang kamu tulis langsung di kode — kalau itu bekerja, masalahnya ada di lokasi, bukan di jaringan. Baca ulang Bab 14 untuk urusan respons, dan Bab 16 untuk urusan izin. Kalau masih macet di satu bagian spesifik, itu wajar: proyek ini memang dirancang untuk memaksamu mengingat kembali konsep yang sudah dibahas, bukan menghafalnya.

Rangkuman pembelajaran pribadi, disusun ulang dari beberapa kursus Flutter.