Bagaimana cara membuat backend untuk aplikasi Android?

Sampul Aplikasi Android Back4app

Dalam artikel ini, kita akan membahas tentang Android – salah satu sistem operasi yang paling populer. Kita akan melihat pro dan kontra pengembangan Android, opsi backend untuk aplikasi mobile, dan mengajari Anda cara membuat backend mobile Anda sendiri.

Hal-hal Penting yang Dapat Dipetik

  • Dominasi Android: Android, sebagai OS sumber terbuka, mendukung sekitar 70% perangkat seluler dengan lebih dari tiga miliar pengguna aktif.
  • Opsi Backend untuk Aplikasi: Untuk backend aplikasi seluler, pengembang dapat memilih Infrastructure as a Service (IaaS), Platform as a Service (PaaS), atau Backend as a Service (BaaS).
  • Langkah-langkah untuk membangun backend Anda: Kami akan memberikan tutorial mendetail tentang cara membuat backend Android menggunakan platform BaaS dan kode sumbernya di akhir artikel.

Apa itu Android?

Android adalah sistem operasi berbasis Linux yang gratis dan sumber terbuka. Sistem operasi ini terutama dirancang untuk perangkat seluler seperti ponsel cerdas dan tablet, tetapi sekarang juga digunakan untuk TV pintar, sistem tertanam, konsol game, dan lain-lain.

Pengembangan Android dimulai pada tahun 2003 oleh Android Inc. Perusahaan ini awalnya ingin membuat OS untuk kamera digital, tetapi dengan cepat beralih ke pengembangan OS seluler untuk menjangkau pasar yang lebih luas.

Pada tahun 2005, perusahaan ini diakuisisi oleh Google beserta para karyawannya. Versi pertama Android dirilis pada tahun 2008.

Meskipun Android adalah sumber terbuka, sebagian besar perangkat seluler menjalankan versi milik Google. Versi mereka sudah terinstal dengan perangkat lunak seperti Google Chrome, YouTube, Google TV, dan Gmail.

Karena opsi kustomisasi Android yang luar biasa, banyak produsen juga menguliti Android untuk merepresentasikan perusahaan mereka dengan lebih baik. Inilah sebabnya mengapa Android OnePlus terlihat sangat berbeda dari Pixel Android.

Android telah menjadi sistem operasi paling populer sejak tahun 2013. Sistem operasi ini digunakan oleh sekitar 70% perangkat seluler dan memiliki lebih dari tiga miliar pengguna aktif bulanan.

Selain itu, Google Play Store memberi Anda akses ke lebih dari tiga juta aplikasi seluler. Teruslah membaca untuk mempelajari cara membuat backend untuk aplikasi Android.

Manfaat pengembangan Android

Mari kita jelajahi beberapa keuntungan mengembangkan untuk Android.

Lintas platform

Dengan mengembangkan untuk Android, Anda bisa menargetkan berbagai macam perangkat. Itu termasuk ponsel, perangkat yang dapat dikenakan, TV pintar, konsol game, dan banyak lagi. Jika Anda tahu cara membuat kode aplikasi seluler, Anda tidak akan mengalami masalah dalam mengembangkan aplikasi perangkat yang dapat dikenakan atau TV pintar.

Pasar yang sangat besar

Seperti yang telah diperkenalkan sebelumnya, Android memiliki pangsa pasar yang lebih besar yaitu 70%, dibandingkan dengan iOS yang hanya 30%. Dengan mengembangkan aplikasi Android, Anda secara otomatis dapat memperoleh akses ke audiens yang lebih luas.

Selain itu, aplikasi Android dikenal dengan investasi yang rendah dan laba atas investasi yang tinggi. Tidak seperti iOS, tidak ada biaya pengembang tahunan.

Kemampuan penyesuaian

Perangkat Android sangat mudah dikustomisasi dibandingkan dengan sistem operasi lainnya. Perangkat ini memungkinkan Anda untuk mengubah apa pun yang dapat Anda bayangkan.

Selain itu, Android memungkinkan Anda untuk mengintegrasikan aplikasi Anda dengan layanan pihak ketiga lainnya dengan mudah.

Komunitas

Android didukung oleh komunitas pengembang sumber terbuka yang sangat besar. Selain itu, Android hadir dengan banyak alat yang ramah pengembang seperti Android Studio, ADB, dan Logcat yang memungkinkan Anda membuat aplikasi dengan mudah.

Jika Anda mengalami kesulitan, ada beberapa platform di mana Anda dapat menemukan bantuan, termasuk GitHub, StackOverflow, Reddit, dan komunitas khusus Android lainnya.

Keterbatasan pengembangan Android

Berikut ini adalah beberapa kekurangan dari pengembangan Android.

Keamanan

Android kurang aman dibandingkan iOS dan tidak mengikuti protokol keamanan yang ketat. Karena Android merupakan sumber terbuka, kerentanan keamanan terdeteksi setiap minggu. Hal ini memberikan kemampuan kepada para peretas untuk mengeksploitasi kerentanan ini sebelum ditambal.

Perangkat Android juga bisa di-root untuk mendapatkan akses pengguna super. Meskipun membuat perangkat Anda lebih kuat, hal ini juga berisiko karena menonaktifkan beberapa langkah keamanan bawaan.

Kompleksitas

Perangkat Android hadir dalam berbagai bentuk dan ukuran, dan meskipun itu bagus, hal ini bisa menjadi kelemahan besar ketika mengembangkan aplikasi Android untuk berbagai jenis perangkat.

Untuk memastikan aplikasi Anda kompatibel dengan sebanyak mungkin perangkat, Anda harus menggabungkan desain responsif, memikirkan perangkat keras perangkat yang berbeda, dan sebagainya.

Aplikasi premium

Aplikasi premium kurang sukses di Google Play Store dibandingkan dengan App Store. Bukan rahasia lagi bahwa pengguna Android cenderung membelanjakan lebih sedikit untuk aplikasi daripada pengguna iOS. Jika Anda sedang mengerjakan aplikasi premium, pertimbangkan Android sebagai pilihan kedua.

Opsi backend untuk aplikasi Android

Apa backend terbaik untuk aplikasi Android? Backend untuk aplikasi seluler dapat di-host di infrastruktur Anda sendiri atau diterapkan ke layanan cloud. Model komputasi awan yang paling populer untuk backend seluler meliputi:

  1. Infrastruktur sebagai Layanan (IaaS)
  2. Platform sebagai Layanan (PaaS)
  3. Backend sebagai Layanan (BaaS)

Setiap opsi mencakup lapisan abstraksi yang berbeda, seperti yang digambarkan dalam gambar di bawah ini.

Lapisan Abstraksi IaaS vs PaaS vs BaaS

Mari kita lihat setiap opsi secara mendetail untuk membantu Anda memilih model cloud yang paling sesuai untuk aplikasi backend Anda.

Infrastruktur sebagai Layanan (IaaS)

Infrastructure as a Service (IaaS) adalah model komputasi awan yang paling tidak abstrak. Dalam model ini, vendor menawarkan sumber daya tervirtualisasi kepada pengguna, seperti server, jaringan, penyimpanan, dan sistem operasi, melalui API tingkat tinggi atau dasbor intuitif.

Hal terbaik tentang IaaS adalah IaaS memberi pengguna kendali penuh atas seluruh infrastruktur mereka. IaaS adalah model yang paling fleksibel dan dapat diskalakan, tetapi juga yang paling sulit untuk dikelola. Jika Anda memilih opsi ini, kemungkinan besar Anda akan membutuhkan satu atau dua SysAdmin.

Beberapa contoh IaaS adalah Amazon Web Services, Google Cloud Platform, dan Azure.

Platform sebagai Layanan (PaaS)

Platform as a Service (PaaS) adalah model komputasi awan yang dirancang untuk membantu pengguna mengembangkan, mengelola, dan menerapkan aplikasi.

Selain menyediakan infrastruktur, PaaS hadir dengan alat yang mudah digunakan untuk mengembangkan, menyesuaikan, dan menguji aplikasi.

Dengan memanfaatkan PaaS, Anda akan dapat fokus pada perangkat lunak dan pengalaman pengguna tanpa perlu mengkhawatirkan infrastruktur yang mendasarinya.

Selain itu, PaaS akan memastikan skala aplikasi Anda sesuai permintaan, menangani pencadangan, dan lain-lain. Kelemahan PaaS adalah tingkat kontrol yang lebih rendah, risiko penguncian vendor, dan biaya yang relatif lebih tinggi.

Platform PaaS yang paling populer termasuk Heroku, Render, dan Digital Ocean App Platform.

Backend sebagai Layanan (BaaS)

Backend as a Service (BaaS) mengotomatiskan bagian backend pengembangan dengan menyediakan solusi backend yang lengkap.

Fitur BaaS mencakup manajemen pengguna, basis data, otentikasi, integrasi sosial, pemberitahuan push, API, SDK, dan banyak lagi.

BaaS memberi Anda semua keuntungan dari IaaS dan PaaS sambil menyediakan fungsi tambahan. Tim yang memanfaatkan BaaS cenderung merilis produk mereka lebih cepat, memangkas biaya rekayasa, dan membangun perangkat lunak yang lebih baik.

Kelemahan BaaS termasuk tingkat kontrol dan kustomisasi yang lebih rendah dan kemungkinan penguncian vendor untuk platform non-open source.

Contoh BaaS termasuk Back4app, AWS Amplify, dan Firebase.

Bagaimana cara membuat backend untuk aplikasi Android?

Pada bagian artikel ini, kita akan melihat cara membuat aplikasi backend berbasis Back4app dan menghubungkannya dari aplikasi Android.

Prasyarat

Apa itu Back4app?

Back4app adalah platform yang sangat baik untuk membangun backend untuk aplikasi modern dan mempercepat proses pengembangan.

Dilengkapi dengan fitur-fitur sisi server yang berguna seperti manajemen pengguna, basis data real-time, integrasi sosial, fungsi Cloud Code, pemberitahuan push, API, dan masih banyak lagi!

Dengan menggunakan Back4app, Anda akan dapat melakukan off-source sebagian besar pekerjaan backend dan fokus pada aspek-aspek penting dari aplikasi Anda dan mempercepat pengembangan backend aplikasi Android.

Anda tidak perlu berurusan dengan infrastruktur yang mendasari backend Anda, server backend, penskalaan, pemeliharaan, dan lain-lain.

Yang paling penting, Back4app menawarkan tingkat gratis yang sangat bagus untuk bereksperimen dan menguji platform. Seiring dengan pertumbuhan aplikasi Anda, Anda bisa meningkatkan ke paket premium dengan biaya bulanan.

Pengenalan Proyek

Pada artikel ini, kita akan membuat aplikasi catatan sederhana. Aplikasi ini akan memungkinkan pengguna untuk menambah, mengedit, dan menghapus catatan. Catatan akan disimpan dalam database Back4app dan dimanipulasi melalui Parse SDK.

Kita akan menggunakan bahasa pemrograman Kotlin untuk membangun aplikasi. Untuk UI, kita akan menggunakan Jetpack Compose – toolkit modern Android untuk membuat UI native.

Aplikasi Catatan Android Back4app

Buat Aplikasi Back4app

Sebagai langkah pertama untuk mengembangkan backend untuk aplikasi Android, Anda memerlukan akun Back4app. Jika Anda belum memilikinya, silakan mendaftar.

Saat Anda masuk ke akun Back4app, Anda akan diarahkan ke tampilan aplikasi. Klik “Buat aplikasi baru” untuk menginisialisasi proses pembuatan aplikasi.

Back4app Bangun Aplikasi Baru

Platform Back4app menawarkan dua solusi:

  1. Backend sebagai Layanan (BaaS) – solusi backend yang kuat
  2. Containers as a Service (CaaS) – platform untuk mengelola kontainer (terutama aplikasi web)

Mengingat kita membangun backend untuk aplikasi seluler, kita akan menggunakan “Backend sebagai Layanan”.

Solusi BaaS Back4app

Berikan nama yang bagus dan informatif pada aplikasi Anda, pilih “NoSQL” sebagai basis data, dan klik “Buat”. Ini adalah langkah penting untuk menerapkan backend untuk aplikasi Android.

Back4app akan membutuhkan waktu beberapa saat untuk mempersiapkan semua yang diperlukan untuk aplikasi Anda. Ini termasuk database, manajemen pengguna, penskalaan, konfigurasi, dan lain-lain. Setelah aplikasi Anda siap, Anda akan diarahkan ke tampilan basis data aplikasi Anda.

Tampilan Basis Data Back4app

Merancang Basis Data

Selanjutnya, mari kita mendesain database. Ini adalah langkah yang diperlukan untuk mengembangkan backend aplikasi Android.

Karena kita membuat aplikasi catatan sederhana, kita hanya membutuhkan satu kelas. Silakan klik “Buat kelas”, beri nama Catatan, aktifkan “Baca dan Tulis Publik”, dan klik “Buat kelas & tambahkan kolom”.

Back4app Membuat Kelas Basis Data

Selanjutnya, tambahkan tiga bidang berikut ke kelas yang baru dibuat:

+-------------+-------------+--------------------+----------+
| Data type   | Name        | Default value      | Required |
+-------------+-------------+--------------------+----------+
| String      | icon        | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | title       | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+
| String      | content     | <leave blank>      | yes      |
+-------------+-------------+--------------------+----------+

Terakhir, klik tombol “Tambah baris” dan isi database Anda dengan beberapa contoh data. Jika Anda tidak memiliki ide, Anda juga dapat mengimpor data dump ini.

Back4app Mengisi Basis Data

Bagus, itu saja untuk backend.

Kode Frontend

Pada bagian artikel ini, kita akan melakukan bootstrap aplikasi Android baru, menyiapkan ViewModel, mengimplementasikan UI, menginstal dan mengonfigurasi Parse SDK, dan yang terakhir adalah mengambil data dari basis data waktu nyata Back4app.

Proyek Init

Seperti yang disebutkan di bagian prasyarat, langkah-langkah berikut ini mengharuskan Anda menginstal Android Studio. Jika Anda belum memilikinya, unduhlah.

Mulailah dengan membuka Android Studio dan klik tombol “Proyek Baru”.

Indeks Android Studio

Kemudian pilih “Aktivitas Kosong” sebagai templat proyek Anda, dan klik “Berikutnya”.

Untuk membuat proyek Anda, Anda harus memberikan nama dan nama paket. Saya sarankan Anda menggunakan AndroidApp sebagai nama proyek Anda dan nama domain terbalik sebagai paket proyek Anda.

Setelah Anda mengkonfigurasi semuanya, klik “Selesai” untuk membuat proyek.

Pengaturan Proyek Android Studio

Android Studio akan membutuhkan waktu sekitar dua menit untuk mempersiapkan semua yang diperlukan. Hal ini termasuk membuat struktur file proyek, menyiapkan Gradle, menginstal dependensi, dll.

Setelah proyek Anda siap, gunakan penjelajah untuk menavigasi ke MainActivity.kt dan mengganti isinya:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            MaterialTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background,
                ) {
                    Text(text = "Back4app rocks!", fontSize = 18.sp)
                }
            }
        }
    }
}

Pastikan untuk selalu mengganti dengan nama paket Anda yang sebenarnya.

Terakhir, coba jalankan aplikasi dengan mengklik tombol play berwarna hijau atau Shift + F10 pada keyboard Anda. Jika semuanya berjalan dengan baik, emulator akan mulai berjalan, dan Anda akan melihat pesan Back4app rocks di layar.

Aplikasi Android Pertama

LihatModel

Untuk mengelola keadaan global aplikasi kita, kita akan menggunakan ViewModel. Namun sebelum itu, kita harus membuat kelas data Note dengan atribut yang sama dengan yang ada di database Back4app.

Buat kelas data bernama Catatan:

// app/src/main/java.<your_package_name>/Note.kt

package <your.package.name>

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    companion object {
        fun generateObjectId(): String {
            val chars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
            return (1..10).map { chars.random() }.joinToString("")
        }
    }
}
  1. Kami mendefinisikan metode statis generateObjectId() untuk menghasilkan ID objek seperti Parse.
  2. objectId dapat di-null-kan karena kita akan mengasumsikan bahwa jika objectId == null, maka objek tersebut belum disimpan ke dalam database.

Selanjutnya, buat kelas AppViewModel dengan konten berikut:

// app/src/main/java.<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf(
        "7IggsqFAKt" to Note(
            objectId = "7IggsqFAKt",
            icon = "\uD83D\uDE80",
            title = "Deploy app",
            content = "Go ahead and deploy your backend to Back4app.",
        ),
        "eFRNm0hTat" to Note(
            objectId = "eFRNm0hTat",
            icon = "\uD83C\uDFA8",
            title = "Design website",
            content = "Design the website for the conference.",
        ),
        "uC7hTQmG5F" to Note(
            objectId = "uC7hTQmG5F",
            icon = "\uD83D\uDC42",
            title = "Attend meeting",
            content = "Attend meeting with the team to discuss the conference.",
        ),
    ))

    companion object {
        @Volatile
        private var instance: AppViewModel? = null

        fun getInstance(): AppViewModel {
            return instance ?: synchronized(this) {
                instance ?: AppViewModel().also { instance = it }
            }
        }
    }
}
  1. Kami menggunakan MutableState dari Compose untuk memicu pembaruan UI jika terjadi perubahan data.
  2. MutableState menyimpan sebuah Peta objectIdsdan Notes, yang kita isi dengan data.
  3. Untuk memastikan bahwa hanya ada satu contoh AppViewModel, kami menggunakan pola tunggal.

Kita sekarang dapat mengakses instance AppViewModel dalam aktivitas kita melalui AppViewModel.getInstance().

Kegiatan Utama

Selanjutnya, ganti konten MainActivity.kt dengan kode berikut untuk menampilkan catatan:

// app/src/main/java.<your_package_name>/MainActivity.kt

package <your.package.name>

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp

class MainActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val context = this as Context

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // TODO: Open note edit form
                },
                onNoteAddClick = {
                    // TODO: Open note create form
                },
            )
        }
    }
}

@Composable
fun MainActivityContent(
    viewModel: AppViewModel,
    onNoteListItemClick: (note: Note) -> Unit,
    onNoteAddClick: () -> Unit,
) {
    val notes = viewModel.notes.value
    MaterialTheme {
        Scaffold(
            topBar = { TopAppBar(title = { Text("My Notes") }) },
            floatingActionButton = {
                ExtendedFloatingActionButton(
                    onClick = { onNoteAddClick() },
                    icon = { Icon(Icons.Filled.Add, contentDescription = "Add") },
                    text = { Text("Add") }
                )
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteList(notes, onNoteListItemClick = { onNoteListItemClick(it) })
            }
        }
    }
}

@Composable
fun NoteListItem(note: Note, onNoteListItemClick: (note: Note) -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .clickable(onClick = { onNoteListItemClick(note) })
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        Text(text = note.icon, fontSize = 32.sp, modifier = Modifier.size(48.dp))
        Spacer(modifier = Modifier.width(8.dp))
        Column {
            Text(text = note.title, fontSize = 18.sp)
            Spacer(modifier = Modifier.height(4.dp))
            Text(
                text = note.content,
                fontSize = 14.sp,
                maxLines = 1,
                overflow = TextOverflow.Ellipsis,
            )
        }
    }
}

@Composable
fun NoteList(notes: Map<String, Note>, onNoteListItemClick: (note: Note) -> Unit) {
    LazyColumn {
        items(notes.entries.toList()) { (_, note) ->
            NoteListItem(note = note, onNoteListItemClick = onNoteListItemClick)
        }
    }
}
  1. Catatan sekarang diambil dari AppViewModel.
  2. Alih-alih mendefinisikan peristiwa klik di composable, kami meneruskannya sebagai argumen.
  3. Kami menggunakan Compose untuk mendesain UI. Untuk membuatnya lebih apik, kami menggabungkan MaterialTheme dengan tata letak Perancah.

Jika Anda membangun ulang aplikasi sekarang, Anda akan melihat daftar catatan “hard-coded” di layar.

Daftar Aplikasi Catatan Back4app

Aktivitas Formulir Catatan

Di bagian ini, kita akan menambahkan aktivitas baru yang memungkinkan pengguna untuk menambah dan mengedit catatan.

Mulailah dengan membuat kelas baru bernama FormActivity dengan konten berikut:

// app/src/main/java.<your_package_name>/FormActivity.kt

package <your.package.name>

import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material3.Button
import androidx.compose.material3.ExtendedFloatingActionButton
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp

class FormActivity : ComponentActivity() {
    private val viewModel = AppViewModel.getInstance()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        val objectId = intent.getStringExtra("objectId")
        val note = if (objectId !== null) viewModel.notes.value[objectId] else null

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.objectId = Note.generateObjectId()
                    viewModel.notes.value += (newNote.objectId!! to newNote)
                    finish()
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    viewModel.notes.value += (updatedNote.objectId!! to updatedNote)
                    finish()
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    finish()
                },
            )
        }
    }
}

@Composable
fun FormActivityContent(
    note: Note?,
    onNoteAddClick: (icon: String, title: String, content: String) -> Unit,
    onNoteSaveClick: (icon: String, title: String, content: String) -> Unit,
    onNoteDeleteClick: () -> Unit,
) {
    MaterialTheme {
        Scaffold(
            topBar = {
                TopAppBar(title = { Text(note?.let { "Edit Note" } ?: ("Add Note")) })
            },
            floatingActionButton = {
                if (note !== null) {
                    ExtendedFloatingActionButton(
                        onClick = { onNoteDeleteClick() },
                        icon = { Icon(Icons.Filled.Delete, "Delete") },
                        text = { Text("Delete") },
                    )
                }
            },
        ) { contentPadding ->
            Box(modifier = Modifier.padding(contentPadding)) {
                NoteForm(note = note, onNoteSave = { icon, title, content ->
                    if (note === null) {
                        onNoteAddClick(icon, title, content)
                    } else {
                        onNoteSaveClick(icon, title, content)
                    }
                })
            }
        }
    }
}

@Composable
fun NoteForm(
    note: Note?,
    onNoteSave: (icon: String, title: String, content: String) -> Unit
) {
    var icon by remember { mutableStateOf(TextFieldValue(note?.icon ?: "")) }
    var title by remember { mutableStateOf(TextFieldValue(note?.title ?: "")) }
    var content by remember { mutableStateOf(TextFieldValue(note?.content ?: "")) }
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
    ) {
        TextField(
            label = { Text(text = "Icon") },
            value = icon,
            onValueChange = { icon = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Title") },
            value = title,
            onValueChange = { title = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        TextField(
            label = { Text(text = "Content") },
            value = content,
            onValueChange = { content = it },
            modifier = Modifier.fillMaxWidth()
        )
        Spacer(modifier = Modifier.height(16.dp))
        Button(
            onClick = { onNoteSave(icon.text, title.text, content.text) },
            Modifier.fillMaxWidth()
        ) {
            Text(text = "Save")
        }
    }
}
  1. Formulir ini digunakan untuk menambahkan dan mengedit catatan. Untuk menentukan tindakan, kita membandingkan objectId == null. Dalam kasus null, ini adalah aksi tambah, jika tidak, aksi edit.
  2. Jika objectId !== null, kita akan mengambil catatan dari state dan mengisi form.
  3. Agar MutableState dapat bekerja dengan baik, kita harus memperlakukan isinya sebagai sesuatu yang tidak dapat diubah. Inilah sebabnya mengapa kita terkadang menyalin isinya dan bukan memodifikasinya.
  4. Kita menangani keadaan form Compose melalui mutableStateOf().

Selanjutnya, daftarkan FormActivity di bagian bawah aplikasi di AndroidManifest.xml:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <application>
        <!-- ... -->
        <activity android:name=".FormActivity"/>
    </application>

</manifest>

Terakhir, buat Intent baru pada onNoteListItemClick dan onNoteAddClick di MainActivity.kt:

// app/src/main/java.<your_package_name>/MainActivity.kt

class MainActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            MainActivityContent(
                viewModel = viewModel,
                onNoteListItemClick = {
                    // triggers the edit action, since `objectId` is provided
                    val intent = Intent(context, FormActivity::class.java)
                    intent.putExtra("objectId", it.objectId)
                    context.startActivity(intent)
                },
                onNoteAddClick = {
                    // triggers the add action, since no `objectId` is present
                    val intent = Intent(context, FormActivity::class.java)
                    context.startActivity(intent)
                },
            )
        }
    }
}

Jangan lupa untuk mengimpor Intent di bagian atas file:

import android.content.Intent

Jika Anda membangun ulang aplikasi, Anda akan melihat bahwa kita sekarang memiliki aplikasi yang berfungsi. Aplikasi ini memungkinkan kita untuk menambahkan catatan, mengedit, dan menghapusnya.

Satu-satunya masalah adalah memulai ulang aplikasi akan menyetel ulang statusnya (ke catatan “kode keras”).

Pada bagian selanjutnya, kita akan menghubungkan aplikasi ke backend Back4app. Hal itu akan memungkinkan kita untuk mempertahankan status dan menyinkronkannya di antara beberapa perangkat.

Pratinjau Pengeditan Aplikasi Catatan Android

Instal Parse SDK

Seperti yang Anda ketahui, Back4app didasarkan pada platform Parse. Jika kita ingin berinteraksi dengan database Back4app atau Back4app secara umum, kita harus menginstal Parse SDK.

Mulailah dengan menambahkan repositori JitPack ke settings.gradle:

// settings.gradle

pluginManagement {
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}
dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        // ...
        maven { url "https://jitpack.io" }
    }
}

Selanjutnya, tambahkan Android Parse SDK ke build.gradle di tingkat aplikasi:

// app/build.gradle

dependencies {
    // ...
    implementation "com.github.parse-community.Parse-SDK-Android:parse:4.2.0"
}

Sinkronkan pengaturan Gradle dan pastikan tidak ada kesalahan.

Mengkonfigurasi Parse SDK

Untuk terhubung ke backend Back4app, Anda harus memberikan ID aplikasi dan kunci klien Anda kepada Parse SDK. Untuk mendapatkan kredensial Anda, buka aplikasi Back4app Anda dan pilih “Pengaturan Aplikasi > Keamanan & Kunci” di bilah sisi.

Kemudian tambahkan ke strings.xml Anda seperti ini:

<!-- app/src/main/res/values/strings.xml -->

<resources>
    <string name="app_name">back4app-android-app</string>
    <string name="back4app_server_url">https://parseapi.back4app.com/</string>
    <string name="back4app_app_id">your_parse_app_id</string>
    <string name="back4app_client_key">your_parse_client_key</string>
</resources>

Pastikan untuk mengganti your_parse_app_id dan your_parse_client_key dengan kredensial Anda.

Selanjutnya, modifikasi AndroidManifest.xml Anda untuk mengaktifkan akses internet dan melampirkan metadata kredensial:

<!-- app/src/main/AndroidManifest.xml -->

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <!-- these two permissions enable internet access -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application>
        <!-- ... -->

        <!-- newly added metadata -->
        <meta-data
            android:name="com.parse.SERVER_URL"
            android:value="@string/back4app_server_url" />
        <meta-data
            android:name="com.parse.APPLICATION_ID"
            android:value="@string/back4app_app_id" />
        <meta-data
            android:name="com.parse.CLIENT_KEY"
            android:value="@string/back4app_client_key" />
    </application>

</manifest>

Hal terakhir yang harus kita lakukan adalah menginisialisasi Parse. Untuk memastikan Parse diinisialisasi sebelum aktivitas apa pun, kita akan membuat kelas baru bernama App, yang diwarisi dari kelas Application.

Buat App.kt dan inisialisasi Parse seperti ini:

// app/src/main/java/<your_package_name>/App.kt

package <your.package.name>

import android.app.Application
import com.parse.Parse

class App : Application() {
    override fun onCreate() {
        super.onCreate()

        Parse.initialize(
            Parse.Configuration.Builder(this)
                .applicationId(getString(R.string.back4app_app_id))
                .clientKey(getString(R.string.back4app_client_key))
                .server(getString(R.string.back4app_server_url))
                .build()
        )
    }
}

Kemudian daftarkan kelas App di AndroidManifest.xml:

<!-- app/src/main/AndroidManifest.xml -->

<application
    android:name=".App"
    ...
>
    <!-- ... -->
</application>

Bangun kembali aplikasi sekali lagi dan periksa jendela Logcat untuk mengetahui adanya kesalahan. Jika tidak ada kesalahan, koneksi ke Back4app telah berhasil.

Memuat Catatan dari Back4app

Hal terakhir yang harus kita lakukan sebelum aplikasi kita selesai adalah memuat catatan dari basis data Back4app dan melihat bagaimana cara menggunakan Parse dalam praktiknya.

Mulailah dengan menavigasi ke AppViewModel. Hapus data dari peta dan tambahkan blok init:

// app/src/main/java/<your_package_name>/AppViewModel.kt

package <your.package.name>

import androidx.compose.runtime.MutableState
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel

class AppViewModel : ViewModel() {
    val notes: MutableState<Map<String, Note>> = mutableStateOf(mapOf())

    init {
        val query = com.parse.ParseQuery.getQuery<com.parse.ParseObject>("Note")
        query.orderByDescending("createdAt")
        query.findInBackground { notes, e ->
            if (e == null) {
                for (parseNote in notes) {
                    val note = Note(
                        objectId = parseNote.objectId,
                        icon = parseNote.getString("icon")!!,
                        title = parseNote.getString("title")!!,
                        content = parseNote.getString("content")!!,
                    )
                    this.notes.value += (note.objectId!! to note)
                }
            } else {
                println("Error: ${e.message}")
            }
        }
    }

    companion object {
        // ...
    }
}

Kode ini menggunakan Parse SDK untuk mengambil catatan dari database, mengubahnya menjadi kelas data Catatan, dan menyimpannya ke peta.

Selanjutnya, tambahkan tiga metode berikut ini ke Catatan:

// app/src/main/java/<your_package_name>/Note.kt

package <your.package.name>

import com.parse.ParseObject
import com.parse.ParseQuery

data class Note(
    var objectId: String? = null,
    var icon: String,
    var title: String,
    var content: String,
) {
    fun addToParse(callback: (objectId: String) -> Unit) {
        if (objectId !== null) throw Exception("Note is already saved to Parse!")

        val parseNote = ParseObject("Note")
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            objectId = parseNote.objectId
            callback(parseNote.objectId)
        }
    }

    fun updateToParse(callback: (objectId: String) -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.put("icon", icon)
        parseNote.put("title", title)
        parseNote.put("content", content)

        parseNote.saveInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback(parseNote.objectId)
        }
    }

    fun deleteFromParse(callback: () -> Unit) {
        if (objectId === null) throw Exception("Note hasn't been saved to Parse yet!")

        val query = ParseQuery.getQuery<ParseObject>("Note")
        val parseNote = query.get(objectId)
        parseNote.deleteInBackground {
            if (it !== null) throw Exception("Error: ${it.message}")
            callback()
        }
    }
}
  1. addToParse() menambahkan catatan baru ke server Parse dengan rinciannya. Jika berhasil, ia akan menyimpan pengenal unik catatan dan memberitahukan ketika selesai.
  2. updateToParse() memperbarui informasi catatan yang sudah ada di server Parse. Jika berhasil, ini menandakan penyelesaian setelah membuat perubahan.
  3. deleteFromParse() menghapus catatan yang tersimpan dari server Parse. Jika berhasil, ini akan mengonfirmasi penghapusan setelah selesai.

Terakhir, modifikasi metode klik di FormActivity untuk memanggil metode yang baru didefinisikan:

// app/src/main/java/<your_package_name>/NoteFormActivity.kt

class FormActivity : ComponentActivity() {
    // ...

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...

        setContent {
            FormActivityContent(
                note,
                onNoteAddClick = { icon: String, title: String, content: String ->
                    if (note !== null) return@FormActivityContent
                    val newNote = Note(
                        icon = icon,
                        title = title,
                        content = content,
                    )
                    newNote.addToParse {
                        viewModel.notes.value += (it to newNote)
                        finish()
                    }
                },
                onNoteSaveClick = { icon: String, title: String, content: String ->
                    if (note === null) return@FormActivityContent
                    val updatedNote = note.copy()
                    updatedNote.icon = icon
                    updatedNote.title = title
                    updatedNote.content = content
                    updatedNote.updateToParse {
                        viewModel.notes.value += (it to updatedNote)
                        finish()
                    }
                },
                onNoteDeleteClick = {
                    if (note === null) return@FormActivityContent
                    viewModel.notes.value = viewModel.notes.value.filter {
                        it.value.objectId != note.objectId
                    }
                    note.deleteFromParse {
                        finish()
                    }
                },
            )
        }
    }
}

Itu dia!

Aplikasi sekarang sudah berfungsi penuh dan tersinkronisasi ke backend Back4app. Cobalah bermain-main dengan aplikasi dengan mengubah data dan periksa apakah perubahan tersebut tercermin dalam tampilan database.

Kesimpulan

Pada artikel ini, kita telah berhasil membangun backend seluler dan menghubungkannya dari aplikasi Android. Kami menggunakan solusi BaaS Back4app untuk backend, dan di frontend, kami menggunakan Kotlin dengan Jetpack Compose.

Sekarang, Anda seharusnya sudah memiliki pemahaman yang cukup baik tentang cara kerja backend seluler dan dapat membangun backend Anda sendiri. Lihat kode sumber akhir di repo back4app-android-app.


Leave a reply

Your email address will not be published.