Dockerfile untuk Ci4 dengan Composer

Dengan case ingin menjalankan composer didalam container php dengan apache

FROM php:8.1-apache

# Install dependencies
RUN apt-get update && apt-get install -y \
    libicu-dev \
    libpq-dev \
    unzip \
    curl \
    zip \

# Install Composer
RUN curl -sS https://getcomposer.org/installer | php -- \
    && mv composer.phar /usr/local/bin/composer

# Aktifkan ekstensi PHP Intl 
RUN docker-php-ext-install intl mysqli pdo pdo_mysql

# Aktifkan mod_rewrite Apache
RUN a2enmod rewrite

# Restart Apache agar perubahan berlaku
RUN service apache2 restart

p9, 2 Oct 2025

Migrasi Android dari API 28 ke API 35: Menghadapi Dependency yang Saling Menggantung

Saya menghadapi sesuatu proses pekerjaan yang mesti dilakukan tapi cukup malas dan menunda untuk dikerjakan. Agak malas karena ngerjain satu hal tapi harus mengerjakan yang lain juga. Kesalahan di satu hal bisa merembet ke yang lain, begitu juga sebaliknya. Proses ini adalah upgrade API level android dan gradle.

Google kini mewajibkan minimal target API level 35 untuk aplikasi yang ingin dirilis atau di-update di Play Store. Bagi banyak developer yang masih bertahan di API 28, migrasi ini bukan sekadar ganti angka—tapi sebuah proses kompleks yang melibatkan dependency, build system, dan refactor kode besar-besaran.

⚠️ Kenapa Migrasi Ini Mendesak?

  • Google Play Policy: Mulai 2025, aplikasi baru dan update harus menargetkan API 35.
  • Banyak aplikasi lama masih di API 28, karena tidak pernah di-update sejak 2019–2020.
  • Perubahan besar di dependency seperti AndroidX, Jetpack, AGP, dan Gradle membuat migrasi tidak bisa dilakukan parsial.

🔄 Tantangan Migrasi: Dependency yang Saling Menggantung

  • Update satu dependency sering memicu error di dependency lain.
  • Banyak library yang sudah deprecated atau tidak kompatibel dengan AGP terbaru.
  • Proses migrasi bisa jadi loop tak berujung kalau tidak dilakukan secara menyeluruh.

🧱 Komponen yang Harus Diupdate Bersamaan

Untuk migrasi yang sukses, kamu harus menyentuh hampir semua lapisan build system:

🔧 File Terkait Gradle & Build System

FileFungsi
build.gradle (project)Versi Gradle Plugin & Kotlin DSL
build.gradle (app)Target SDK, compile SDK, dependency
gradle-wrapper.propertiesVersi Gradle minimum
gradle.propertiesFlag konfigurasi build
libs.versions.tomlManajemen dependency versi modern
settings.gradleKonfigurasi modul dan plugin
AndroidManifest.xmlTarget SDK dan permission yang deprecated
proguard-rules.proPenyesuaian obfuscation untuk library baru

🧹 Refactor Kode: Hadapi Deprecated API

  • Banyak API lama (seperti AsyncTask, getExternalStorageDirectory(), dll) sudah deprecated.
  • Perlu migrasi ke API modern seperti WorkManager, Storage Access Framework, dan ActivityResult API.
  • Gunakan lint dan IDE inspection untuk mendeteksi deprecated usage.

📦 Strategi Migrasi Modular

  1. Audit dependency: Cek versi dan kompatibilitas dengan AGP terbaru.
  2. Update Gradle wrapper dan AGP dulu: Pastikan build system stabil.
  3. Migrasi ke libs.versions.toml: Untuk manajemen versi yang lebih maintainable.
  4. Refactor kode deprecated: Gunakan IDE dan dokumentasi resmi.
  5. Testing bertahap: Gunakan emulator API 35 dan unit test untuk validasi.

🧪 Studi Kasus & Strategi Praktis Migrasi

Untuk menghindari migrasi yang membingungkan dan penuh error, lakukan pendekatan berikut:

  1. Install Android Studio terbaru Pastikan kamu menggunakan versi terbaru agar kompatibel dengan AGP dan SDK level 35.
  2. Buat proyek baru dari template bawaan Gunakan template “Empty Compose Activity” atau “Basic Views” untuk melihat struktur modern.
  3. Review struktur proyek baru Perhatikan versi Gradle, AGP, libs.versions.toml, settings.gradle, dan konfigurasi build.gradle.
  4. Bandingkan dengan proyek lama Identifikasi perbedaan versi, plugin, dan struktur dependency.
  5. Terapkan secara bertahap ke proyek lama Mulai dari update Gradle wrapper, lalu AGP, lalu dependency, lalu refactor kode deprecated.
  6. Gunakan version catalog (libs.versions.toml) Ini akan memudahkan tracking versi dan menghindari konflik antar modul.

Dengan pendekatan ini, kamu bisa belajar dari proyek baru yang sudah sesuai standar modern, lalu menerapkannya ke proyek lama secara sistematis dan minim risiko.

✅ Penutup: Migrasi Bukan Sekadar Update, Tapi Rebirth

Migrasi dari API 28 ke 35 bukan hanya soal memenuhi kebijakan Google, tapi juga kesempatan untuk membersihkan, merapikan, dan memodernisasi proyekmu. Dengan pendekatan modular dan dokumentasi yang rapi, kamu bisa mengubah proses yang menyakitkan jadi investasi jangka panjang.

Kediri, 8 Sep 2025

Belajar Flutter bagi Pengembang Native

Sebagai developer yang sudah terbiasa dengan Java, Kotlin, dan Swift, kamu mungkin sudah sangat akrab dengan XML layout di Android dan Storyboard di iOS. Tapi ketika harus membangun aplikasi lintas platform, muncul pertanyaan besar: Haruskah saya belajar Flutter? Jawabannya: ya, jika kamu ingin efisiensi, modularitas, dan satu codebase untuk dua platform utama.

Blog ini adalah roadmap belajar Flutter yang dirancang khusus untuk kamu yang berasal dari dunia native. Kita akan transisi secara bertahap, tanpa membuang keahlian yang sudah kamu miliki.

🧠 Tahap 1: Memahami Paradigma UI Baru

Flutter menggunakan pendekatan declarative UI berbasis Widget Tree. Ini mirip dengan View Hierarchy di Android atau Scene Graph di iOS.

  • Container = View
  • Text = TextView / UILabel
  • Column = LinearLayout (vertical)
  • Row = LinearLayout (horizontal)
  • Stack = FrameLayout / ZStack

Mulailah dengan membangun layout sederhana menggunakan Scaffold, AppBar, dan BottomNavigationBar. Anggap saja ini seperti membuat Activity atau ViewController.

📐 Tahap 2: Layout & Responsivitas

Kalau kamu terbiasa dengan match_parent, wrap_content, dan AutoLayout, Flutter punya padanannya:

  • Gunakan Expanded, Flexible, dan SizedBox untuk kontrol ukuran.
  • MediaQuery dan LayoutBuilder membantu membuat UI yang adaptif.
  • Hindari dulu animasi atau gesture kompleks—fokus pada layout yang familiar.

Tips: Buat layout nested seperti XML-style agar transisi terasa lebih natural.

🔄 Tahap 3: Navigasi & Lifecycle

Navigasi di Flutter menggunakan Navigator.push() dan pop(), mirip dengan Intent di Android atau segue di iOS.

Lifecycle-nya juga punya padanan:

  • initState() = onCreate() / viewDidLoad()
  • dispose() = onDestroy() / deinit
  • didChangeDependencies() = mirip onResume() atau viewWillAppear()

Dokumentasikan perbandingan lifecycle ini untuk referensi pribadi—sangat membantu saat debugging.

🔥 Tahap 4: Integrasi Firebase & Plugin

Flutter punya ekosistem plugin yang matang, terutama untuk Firebase:

  • firebase_core, firebase_auth, cloud_firestore, firebase_analytics
  • Setup-nya mirip dengan build.gradle dan Info.plist, tapi lewat pubspec.yaml
  • Modularisasi setup agar bisa reuse di proyek lain

Tips: Bandingkan setup Firebase di Flutter vs native untuk insight tambahan.

🧮 Tahap 5: State Management Bertahap

Mulai dari yang paling sederhana:

  • setState() → cocok untuk state lokal
  • Provider → untuk state global yang ringan
  • Riverpod atau Bloc → untuk aplikasi kompleks dan scalable

Jangan langsung lompat ke Bloc atau Redux—biar nggak over-engineered di awal.

🧱 Tahap 6: Modularisasi & Struktur Proyek

Karena kamu suka arsitektur modular, Flutter bisa disusun seperti ini:

Kode

lib/
├── core/
├── shared/
├── features/
│   ├── auth/
│   ├── dashboard/
│   └── settings/

Gunakan pubspec.yaml seperti kamu pakai libs.versions.toml di Gradle. Buat komponen reusable seperti CustomButton, AppTextField, dll.

🔌 Tahap 7: Native Bridge & Optimasi

Kalau kamu butuh akses ke fitur native (sensor, BLE, dll), gunakan Platform Channels:

  • Flutter → Kotlin/Swift → native API
  • Bisa modularisasi channel agar tetap maintainable

Optimasi ukuran APK/IPA:

  • flutter build apk --split-per-abi
  • Deferred loading untuk fitur jarang dipakai
  • Kompres asset dan gunakan tree-shaking

🎯 Kesimpulan: Flutter Bukan Pengganti, Tapi Pelengkap

Flutter bukan berarti meninggalkan Java, Kotlin, atau Swift. Justru, kamu bisa memanfaatkan semua keahlian native untuk membangun aplikasi lintas platform yang efisien dan scalable. Dengan satu codebase, kamu bisa hemat waktu, biaya, dan tenaga—tanpa mengorbankan kualitas.

Kediri, 8 Sep 2025

Emulator Android Studio Tidak Mau Jalan

Saya baru saja pindah laptop dari yang sebelumnya pakai thinkpad x200 dan macbook ke thinkpad t480s, saya pikir menjalankan emulator Android adalah hal sepele yang langsung jalan seperti sebelumnya. Ternyata tidak. Di tengah proses pengujian aplikasi, saya justru terjebak dalam masalah yang membuat saya hampir menyerah: emulator Android tidak mau jalan sama sekali.

Berikut kronologi dan poin-poin kesulitan yang saya hadapi, serta bagaimana akhirnya saya bisa menemukan solusi yang bekerja.

⚠️ 1. Emulator Selalu Berhenti Saat Proses Start

Setiap kali saya mencoba menjalankan emulator dari Android Studio, proses hanya sampai tahap “starting emulator” lalu berhenti begitu saja. Tidak ada error fatal, hanya pesan samar seperti “started new renderthread total 17” sebelum jendela emulator hilang tanpa jejak. Tidak ada log yang jelas, tidak ada crash report. Hanya mati begitu saja dengan pesan terminated.

🔧 2. Virtualization Sudah Diaktifkan di BIOS

Langkah pertama tentu saya cek BIOS. Di ThinkPad T480s, saya pastikan Intel Virtualization Technology dan VT-d sudah aktif. Tapi emulator tetap tidak bisa dijalankan. Ini membuat saya curiga bahwa masalahnya bukan di level BIOS, melainkan di lapisan software atau driver.

📦 3. Install Semua Komponen Emulator di SDK Manager

Saya buka Android Studio → SDK Manager → SDK Tools. Di sana saya install semua yang berkaitan dengan emulator:

  • Android Emulator
  • Emulator Hypervisor Driver
  • Platform SDK terbaru

Namun, hasilnya nihil. Emulator tetap tidak bisa dijalankan. Bahkan mencoba versi SDK yang lebih lama pun tidak membantu.

🧪 4. Coba Buat AVD Berbasis ARM—Tetap Gagal

Saya cari referensi dan menemukan mungkin masalahnya ada di image x86_64, jadi saya coba buat AVD berbasis ARM64 + Google APIs. AVD tidak berhasil dibuat karena setelah berbagai cara tidak ditemukan versi ARM.

🎛️ 5. Uji Coba Mode Grafis: Automatic, Hardware, Software

Saya mulai bereksperimen dengan konfigurasi grafis di AVD Manager:

  • Automatic → emulator tetap mati
  • Hardware → muncul warning bahwa GPU tidak mendukung Vulkan
  • Software → akhirnya emulator bisa jalan!

✅ 6. Solusi: Mode Software adalah Penyelamat

Setelah semua upaya gagal, saya ubah mode grafis emulator ke Software. Hasilnya? Emulator akhirnya bisa berjalan stabil. Memang performanya tidak secepat hardware acceleration, tapi cukup untuk debugging dan pengujian UI.

🎯 Kesimpulan

Masalah emulator Android yang tidak mau jalan bisa berasal dari banyak lapisan: BIOS, driver GPU, SDK configuration, bahkan mode grafis. Dalam kasus saya, mode grafis hardware (Vulkan/OpenGL) tidak kompatibel dengan GPU Intel UHD, dan hanya mode software yang bisa menyelamatkan.

Jika kamu mengalami hal serupa, jangan menyerah. Coba ubah mode grafis, pastikan virtualisasi aktif, dan jangan ragu untuk bereksperimen dengan AVD berbasis ARM atau x86_64. Kadang solusi paling sederhana—seperti memilih mode software—adalah yang paling efektif.

P9, 29 Agustus 2025

Project iOS Error dan Lama Tidak Dibuka

Sudah sekian tahun project-project iOS di macbook tidak saya buka. Masalahnya karena sempat pindah device pakai mini PC, yang sekarang rusak, untuk kegiatan sehari-hari.

Selain itu, Xcode yang sudah lama tidak dibuka minta update versi dimana setelah update bisa jadi banyak hal baru yang saya mungkin tidak sempat untuk eksplore. Belum lagi mac OS yang juga harus update kalau jalanin Xcode, begitu juga sebaliknya, akhirnya karena menghindari perputaran update ini, saya jadi malas buka project-project lama iOS saya.

Kondisi ini tidak mungkin saya biarkan seterusnya. Saya sediakan sumber daya pikiran dan waktu untuk mengurai satu per satu.

sdk doesn’t contain libarclite

Ini adalah pesan error pertama setelah buka project xcode.

Setelah mencari berbagai referensi, diminta untuk menaikkan deployment target di project dan juga podfile. Setelah diupdate, diminta menjalankan pod install.

Entah karena apa ternyata pod tidak dikenali. Akhirnya hapus cocoapods dan install ulang.

Waktu menjalankan install ulang cocoapods pakai gem, ternyata ruby nya pakai versi yang sudah udzur. Mau tidak mau install Ruby yang versi lebih baru

Setelah install Ruby versi terbaru, rupanya tidak langsung aktif, masih nyantol ke versi lama. Selanjutnya atur path agar ruby memakai versi yang barusan diinstall.

Ruby dan gem sudah tidak masalah. Masalah muncul di permission denied di docker. Entah kenapa ada sangkut paut sama docker juga disini. Selanjutnya perbaiki hak akses folder.

Waktu tambah path untuk ruby juga sempat ada masalah, karena petunjuk di referensi untuk mac berbasis ARM sedangkan mac saya masih pakai intell.

Setelah semua dilakukan, ternyata masih error yang sama soal libarclite.

Coba baca lagi dengan seksama dan lebih detail. Saya coba update semua yang berkaitan dengan deployment target, mulai dari project hingga semua dependency. Saya naikkan ke iOS 15 semua. Dan, Alhamdulillah berhasil sehingga aplikasi bisa dibuka kembali dan bisa dijalankan di simulator.