Bir Android uygulaması için arka uç nasıl oluşturulur?

Back4app Android Uygulama Kapağı

Bu makalede, en popüler işletim sistemlerinden biri olan Android hakkında konuşacağız. Android geliştirmenin artılarını ve eksilerini, mobil uygulamalar için arka uç seçeneklerini inceleyeceğiz ve size kendi mobil arka ucunuzu nasıl oluşturacağınızı öğreteceğiz.

Önemli Çıkarımlar

  • Android’in Hakimiyeti: Açık kaynaklı bir işletim sistemi olan Android, üç milyardan fazla aktif kullanıcısıyla mobil cihazların yaklaşık %70’ine güç sağlıyor.
  • Uygulamalar için Arka Uç Seçenekleri: Mobil uygulama arka uçları için geliştiriciler Hizmet Olarak Altyapı (IaaS), Hizmet Olarak Platform (PaaS) veya Hizmet Olarak Arka Uç (BaaS) seçeneklerini tercih edebilir.
  • Arka ucunuzu oluşturmak için adımlar: Makalenin sonunda bir BaaS platformu ve kaynak kodu kullanarak bir Android arka ucunun nasıl yapılacağına dair ayrıntılı bir eğitim vereceğiz.

Android nedir?

Android, ücretsiz ve açık kaynaklı Linux tabanlı bir işletim sistemidir. Öncelikle akıllı telefonlar ve tabletler gibi mobil cihazlar için tasarlanmıştır, ancak artık akıllı TV’ler, gömülü sistemler, oyun konsolları vb. için de kullanılmaktadır.

Android’in geliştirilmesine 2003 yılında Android Inc. tarafından başlanmıştır. Şirket başlangıçta dijital kameralar için bir işletim sistemi oluşturmak istedi ancak daha geniş bir pazara ulaşmak için hızla mobil işletim sistemi geliştirmeye yöneldi.

2005 yılında şirket, çalışanlarıyla birlikte Google tarafından satın alındı. Android’in ilk sürümü 2008 yılında piyasaya sürüldü.

Android açık kaynaklı olmasına rağmen, çoğu mobil cihaz Google’ın tescilli sürümünü çalıştırmaktadır. Bu sürüm Google Chrome, YouTube, Google TV ve Gmail gibi yazılımlarla önceden yüklenmiş olarak geliyor.

Android’in harika özelleştirme seçenekleri nedeniyle, birçok üretici de şirketlerini daha iyi temsil etmek için Android’i kaplıyor. OnePlus Android’in Pixel Android’den oldukça farklı görünmesinin nedeni budur.

Android 2013 yılından bu yana en popüler işletim sistemi olmuştur. Mobil cihazların yaklaşık %70’i tarafından kullanılmaktadır ve aylık üç milyardan fazla aktif kullanıcısı vardır.

Bunun da ötesinde, Google Play Store üç milyondan fazla mobil uygulamaya erişmenizi sağlar. Bir Android uygulaması için nasıl arka uç oluşturulacağını öğrenmek için okumaya devam edin.

Android geliştirmenin faydaları

Android için geliştirme yapmanın bazı avantajlarını keşfedelim.

Çapraz platform

Android için geliştirme yaparak geniş bir cihaz yelpazesini hedefleyebilirsiniz. Buna cep telefonları, giyilebilir cihazlar, akıllı TV’ler, oyun konsolları ve daha fazlası dahildir. Bir mobil uygulamayı nasıl kodlayacağınızı biliyorsanız, giyilebilir cihaz veya akıllı TV uygulaması geliştirmekte sorun yaşamazsınız.

Devasa bir pazar

Daha önce de belirtildiği gibi, Android %70 ile iOS’a kıyasla %30 ile daha büyük bir pazar payına sahiptir. Android uygulamaları geliştirerek otomatik olarak daha geniş bir kitleye erişim sağlayabilirsiniz.

Bunun da ötesinde, Android uygulamaları düşük yatırım ve yüksek yatırım getirisi ile bilinir. Ayrıca iOS’un aksine yıllık geliştirici ücretleri de söz konusu değildir.

Özelleştirilebilirlik

Android cihazlar diğer işletim sistemlerine kıyasla son derece özelleştirilebilir. Neredeyse hayal edebileceğiniz her şeyi değiştirmenize izin verirler.

Ayrıca Android, uygulamanızı diğer 3. taraf hizmetlerle kolayca entegre etmenize olanak tanır.

Topluluk

Android, açık kaynaklı geliştiricilerden oluşan büyük bir topluluk tarafından desteklenmektedir. Dahası, Android Studio, ADB ve Logcat gibi uygulamaları kolayca kodlamanıza olanak tanıyan birçok geliştirici dostu araçla birlikte gelir.

Eğer takılırsanız, GitHub, StackOverflow, Reddit ve diğer Android merkezli topluluklar da dahil olmak üzere yardım bulabileceğiniz çeşitli platformlar vardır.

Android geliştirmenin sınırlamaları

İşte Android geliştirmenin bazı dezavantajları.

Güvenlik

Android, iOS’a göre daha az güvenlidir ve katı güvenlik protokollerini takip etmez. Android açık kaynaklı olduğu için güvenlik açıkları haftalık olarak tespit edilmektedir. Bu da bilgisayar korsanlarına bu güvenlik açıklarını yamalanmadan önce istismar etme olanağı verir.

Android cihazlar süper kullanıcı erişimi elde etmek için de root edilebilir. Cihazınızı daha güçlü hale getirirken, bazı yerleşik güvenlik önlemlerini devre dışı bıraktığı için de risklidir.

Karmaşıklık

Android cihazlar farklı şekil ve boyutlara sahiptir ve bu harika olsa da, birden fazla cihaz türü için Android uygulamaları geliştirirken büyük bir dezavantaj olabilir.

Uygulamanızın mümkün olduğunca çok cihazla uyumlu olmasını sağlamak için duyarlı tasarım kullanmanız, farklı cihazların donanımlarını göz önünde bulundurmanız vb. gerekir.

Premium uygulamalar

Premium uygulamalar Google Play Store ‘da App Store‘a kıyasla daha az başarılı. Android kullanıcılarının iOS kullanıcılarına göre uygulamalara daha az harcama yapma eğiliminde olduğu bir sır değil. Premium öncelikli bir uygulama üzerinde çalışıyorsanız, Android’i ikinci tercihiniz olarak düşünün.

Android uygulamaları için arka uç seçenekleri

Bir Android uygulaması için en iyi arka uç nedir? Mobil uygulamalar için arka uçlar kendi altyapınızda barındırılabilir veya bulut hizmetlerine dağıtılabilir. Mobil arka uçlar için en popüler bulut bilişim modelleri şunlardır:

  1. Hizmet Olarak Altyapı (IaaS)
  2. Hizmet Olarak Platform (PaaS)
  3. Hizmet Olarak Arka Uç (BaaS)

Her seçenek, aşağıdaki resimde gösterildiği gibi farklı soyutlama katmanlarını kapsar.

IaaS vs PaaS vs BaaS Soyutlama Katmanları

Arka uç uygulamalarınız için en uygun bulut modelini seçmenize yardımcı olmak için her bir seçeneği ayrıntılı olarak inceleyelim.

Hizmet Olarak Altyapı (IaaS)

Hizmet Olarak Altyapı (IaaS) en az soyutlanmış bulut bilişim modelidir. Bu modelde satıcı, kullanıcılara sunucular, ağ, depolama ve işletim sistemleri gibi sanallaştırılmış kaynakları üst düzey API’ler veya sezgisel gösterge tabloları aracılığıyla sunar.

IaaS ile ilgili en iyi şey, kullanıcılara tüm altyapıları üzerinde tam kontrol sağlamasıdır. IaaS en esnek ve ölçeklenebilir modeldir ancak aynı zamanda yönetilmesi en zor modeldir. Bu seçeneği seçerseniz, büyük olasılıkla bir veya iki SysAdmin’e ihtiyacınız olacaktır.

IaaS’ın birkaç örneği Amazon Web Services, Google Cloud Platform ve Azure‘dur.

Hizmet Olarak Platform (PaaS)

Hizmet Olarak Platform (PaaS), kullanıcıların uygulama geliştirmesine, yönetmesine ve dağıtmasına yardımcı olmak için tasarlanmış bir bulut bilişim modelidir.

PaaS, altyapı sağlamanın yanı sıra uygulamaları geliştirmek, özelleştirmek ve test etmek için kullanıcı dostu araçlarla birlikte gelir.

PaaS kullanarak, altta yatan altyapı hakkında endişelenmeden yazılımınıza ve kullanıcı deneyiminize odaklanabileceksiniz.

Ayrıca PaaS, uygulamanızın talep üzerine ölçeklenmesini sağlar, yedeklemelerle ilgilenir vb. PaaS’ın dezavantajları ise daha düşük kontrol seviyesi, satıcıya kilitlenme riski ve nispeten daha yüksek maliyetlerdir.

En popüler PaaS platformları arasında Heroku, Render ve Digital Ocean App Platform bulunmaktadır.

Hizmet Olarak Arka Uç (BaaS)

Hizmet Olarak Arka Uç (BaaS), tam teşekküllü bir arka uç çözümü sağlayarak geliştirmenin arka uç kısmını otomatikleştirir.

BaaS özellikleri arasında kullanıcı yönetimi, veritabanları, kimlik doğrulama, sosyal entegrasyonlar, anlık bildirimler, API’ler, SDK‘lar ve daha fazlası yer alır.

BaaS size IaaS ve PaaS’ın tüm avantajlarını sunarken ek işlevler de sağlar. BaaS’tan yararlanan ekipler ürünlerini daha hızlı piyasaya sürme, mühendislik maliyetlerini azaltma ve daha iyi yazılımlar oluşturma eğilimindedir.

BaaS’ın dezavantajları arasında daha düşük kontrol ve özelleştirme seviyesi ve açık kaynaklı olmayan platformlar için satıcı kilitlenmesi olasılığı yer alır.

BaaS örnekleri arasında Back4app, AWS Amplify ve Firebase bulunmaktadır.

Bir Android uygulaması için arka uç nasıl yapılır?

Bu makale bölümünde, Back4app tabanlı bir arka uç uygulamasının nasıl oluşturulacağına ve bir Android uygulamasından bu uygulamaya nasıl bağlanılacağına bakacağız.

Ön Koşullar

Back4app nedir?

Back4app, modern uygulamalar için arka uçlar oluşturmak ve geliştirme sürecini hızlandırmak için mükemmel bir platformdur.

Kullanıcı yönetimi, gerçek zamanlı veritabanları, sosyal entegrasyonlar, Cloud Code işlevleri, push bildirimleri, API’ler ve daha fazlası gibi kullanışlı sunucu tarafı özellikleriyle iyi bir şekilde donatılmıştır!

Back4app’i kullanarak, arka uç çalışmalarının çoğunu dış kaynak olarak kullanabilir ve uygulamanızın kritik yönlerine odaklanabilir ve bir Android uygulaması arka uç geliştirmesini hızlandırabilirsiniz.

Arka ucunuzun temel altyapısı, arka uç sunucusu, ölçeklendirme, bakım vb. ile uğraşmanıza gerek kalmayacaktır.

En önemlisi, Back4app, platformu denemek ve test etmek için harika olan ücretsiz bir katman sunar. Uygulamanız büyüdükçe, aylık bir ücret karşılığında premium planlara yükseltebilirsiniz.

Proje Tanıtımı

Bu makalede, basit bir not uygulaması oluşturacağız. Uygulama, kullanıcıların not eklemesine, düzenlemesine ve silmesine olanak tanıyacak. Notlar Back4app veritabanında saklanacak ve Parse SDK aracılığıyla manipüle edilecektir.

Uygulamayı oluşturmak için Kotlin programlama dilini kullanacağız. Kullanıcı arayüzü için, Android’in yerel kullanıcı arayüzleri oluşturmaya yönelik modern araç seti olan Jetpack Compose ‘u kullanacağız.

Back4app Android Notlar Uygulaması

Back4app Uygulaması Oluşturun

Bir Android uygulaması için arka uç geliştirmenin ilk adımı olarak bir Back4app hesabına ihtiyacınız olacak. Eğer bir hesabınız yoksa, devam edin ve kaydolun.

Back4app hesabınıza giriş yaptığınızda, uygulama görünümüne yönlendirileceksiniz. Uygulama oluşturma sürecini başlatmak için “Yeni uygulama oluştur” seçeneğine tıklayın.

Back4app Yeni Uygulama Oluştur

Back4app platformu iki çözüm sunmaktadır:

  1. Hizmet Olarak Arka Uç (BaaS) – sağlam arka uç çözümü
  2. Containers as a Service (CaaS) — konteynerleri (özellikle web uygulamaları) yönetmek için platform

Bir mobil uygulama için arka uç oluşturduğumuzu düşünürsek, “Hizmet Olarak Arka Uç” seçeneğini tercih edeceğiz.

Back4app BaaS Çözümü

Uygulamanıza güzel ve bilgilendirici bir isim verin, veritabanı olarak “NoSQL “i seçin ve “Oluştur “a tıklayın. Bu, bir Android uygulaması için bir arka uç dağıtmak için önemli bir adımdır.

Back4app’in uygulamanız için gereken her şeyi hazırlaması biraz zaman alacaktır. Buna veritabanı, kullanıcı yönetimi, ölçeklendirme, yapılandırmalar vb. dahildir. Uygulamanız hazır olduğunda, uygulamanızın veritabanı görünümüne yönlendirileceksiniz.

Back4app Veritabanı Görünümü

Veritabanı Tasarımı

Devam edelim, veritabanını tasarlayalım. Bu, bir Android uygulaması için arka uç geliştirmek için gerekli bir adımdır.

Basit bir not uygulaması oluşturduğumuz için yalnızca bir sınıfa ihtiyacımız olacak. Devam edin ve “Sınıf oluştur “a tıklayın, adını Not koyun, “Genel Okuma ve Yazma “yı etkinleştirin ve “Sınıf oluştur ve sütun ekle “ye tıklayın.

Back4app Veritabanı Oluşturma Sınıfı

Ardından, yeni oluşturulan sınıfa aşağıdaki üç alanı ekleyin:

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

Son olarak, “Satır ekle” düğmesine tıklayın ve veritabanınızı bazı örnek verilerle doldurun. Herhangi bir fikriniz yoksa, bu veri dökümünü de içe aktarabilirsiniz.

Back4app Veritabanını Doldur

Harika, arka uç için bu kadar.

Kod Ön Yüzü

Bu makale bölümünde, yeni bir Android uygulamasını önyükleyeceğiz, bir ViewModel kuracağız, kullanıcı arayüzünü uygulayacağız, Parse SDK’yı yükleyip yapılandıracağız ve son olarak Back4app gerçek zamanlı veritabanından veri alacağız.

Init Projesi

Önkoşullar bölümünde belirtildiği gibi, aşağıdaki adımlar Android Studio’nun yüklü olmasını gerektirecektir. Henüz sahip değilseniz, indirin.

Android Studio’yu açıp “Yeni Proje” düğmesine tıklayarak başlayın.

Android Studio Dizini

Ardından proje şablonunuz olarak “Boş Faaliyet “i seçin ve “İleri “ye tıklayın.

Projenizi oluşturmak için bir ad ve bir paket adı sağlamalısınız. Projenizin adı olarak AndroidApp ‘ı ve projenizin paketi olarak da ters alan adını kullanmanızı öneririm.

Her şeyi yapılandırdıktan sonra, projeyi oluşturmak için “Son” düğmesine tıklayın.

Android Studio Proje Ayarları

Android Studio’nun gerekli her şeyi hazırlaması yaklaşık iki dakika sürecektir. Buna proje dosya yapısını oluşturmak, Gradle’ı ayarlamak, bağımlılıkları yüklemek vb. dahildir.

Projeniz hazır olduğunda, MainActivity.kt dosyasına gitmek için gezgini kullanın ve içeriğini değiştirin:

// 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)
                }
            }
        }
    }
}

Her zaman değiştirdiğinizden emin olun gerçek paket adınız ile.

Son olarak, yeşil oynat düğmesine veya klavyenizdeki Shift + F10 tuşlarına tıklayarak uygulamayı çalıştırmayı deneyin. Her şey yolunda giderse, emülatör başlamalı ve ekranda Back4app rocks mesajını görmelisiniz.

Android İlk Uygulama

ViewModel

Uygulamamızın global durumunu yönetmek için bir ViewModel kullanacağız. Ancak bundan önce, Back4app veritabanımızdakiyle aynı niteliklere sahip bir Note veri sınıfı oluşturmamız gerekiyor.

Note adında bir veri sınıfı oluşturun:

// 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. Parse benzeri nesne kimlikleri oluşturmak için statik generateObjectId() yöntemini tanımladık.
  2. objectId nullable’dır, çünkü daha sonra objectId == null ise nesnenin henüz veritabanına kaydedilmediğini varsayacağız.

Ardından, aşağıdaki içeriğe sahip bir AppViewModel sınıfı oluşturun:

// 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. Veri değişikliği durumunda UI güncellemelerini tetiklemek için Compose’un MutableState özelliğini kullandık.
  2. MutableState, verilerle doldurduğumuz objectId‘ler ve Notes‘lardan oluşan bir Harita tutar.
  3. AppViewModel‘in yalnızca tek bir örneği olduğundan emin olmak için singleton modelini kullandık.

Artık aktivitelerimizdeki AppViewModel örneğine AppViewModel.getInstance() aracılığıyla erişebiliriz.

Ana Faaliyet

Devam edersek, notları görüntülemek için MainActivity.kt içeriğini aşağıdaki kodla değiştirin:

// 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. Notlar artık AppViewModel‘den alınıyor.
  2. Tıklama olaylarını bileşiklerde tanımlamak yerine, bunları argüman olarak aktardık.
  3. Kullanıcı arayüzünü tasarlamak için Compose kullandık. Daha şık hale getirmek için MaterialThemei Scaffold düzeniyle birleştirdik.

Uygulamayı şimdi yeniden oluşturursanız, ekranda “sabit kodlanmış” notların listesini görmelisiniz.

Back4app Notlar Uygulama Listesi

Not Formu Etkinliği

Bu bölümde, kullanıcıların not eklemesine ve düzenlemesine olanak tanıyan yeni bir etkinlik ekleyeceğiz.

Aşağıdaki içeriğe sahip FormActivity adında yeni bir sınıf oluşturarak başlayın:

// 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. Bu form hem not eklemek hem de notları düzenlemek için kullanılır. Eylemi belirlemek için objectId == null değerini karşılaştırırız. Null olması durumunda, bu bir ekleme eylemidir, aksi takdirde bir düzenleme eylemidir.
  2. objectId !== null ise, notu durumdan alırız ve formu doldururuz.
  3. MutableState ‘in düzgün çalışması için içeriğini değişmez olarak ele almamız gerekiyordu. Bu yüzden bazen içerikleri değiştirmek yerine kopyaladık.
  4. Compose form durumunu mutableStateOf() aracılığıyla ele aldık.

Ardından, AndroidManifest.xml‘de uygulamanın altındaki FormActivity ‘yi kaydedin:

<?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>

Son olarak, MainActivity.kt dosyasında onNoteListItemClick ve onNoteAddClick üzerinde yeni bir Intent oluşturun:

// 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)
                },
            )
        }
    }
}

Dosyanın üst kısmındaki Intent ‘i içe aktarmayı unutmayın:

import android.content.Intent

Uygulamayı yeniden oluşturursanız, artık çalışan bir uygulamamız olduğunu fark edeceksiniz. Uygulama not eklememize, bunları düzenlememize ve silmemize olanak tanıyor.

Tek sorun, uygulamanın yeniden başlatılmasının durumunu (“sabit kodlu” notlara) sıfırlamasıdır.

Bir sonraki bölümde, uygulamayı Back4app arka ucuna bağlayacağız. Bu, durumu kalıcı hale getirmemize ve birden fazla cihaz arasında senkronize etmemize olanak tanıyacak.

Android Notlar Uygulaması Düzenleme Önizlemesi

Parse SDK’yı yükleyin

Bildiğiniz gibi, Back4app Parse platformuna dayanmaktadır. Back4app veritabanı veya genel olarak Back4app ile etkileşime geçmek istiyorsak, Parse SDK’yı yüklememiz gerekir.

JitPack deposunu settings.gradle dosyasına ekleyerek başlayın:

// settings.gradle

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

Ardından, Android Parse SDK’sını uygulama düzeyinin build.gradle dosyasına ekleyin:

// app/build.gradle

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

Gradle ayarlarını senkronize edin ve hata olmadığından emin olun.

Parse SDK’yı Yapılandırma

Back4app arka ucuna bağlanmak için Parse SDK’ya uygulama kimliğinizi ve istemci anahtarınızı sağlamanız gerekir. Kimlik bilgilerinizi almak için Back4app uygulamanıza gidin ve kenar çubuğunda “Uygulama Ayarları > Güvenlik ve Anahtarlar “ı seçin.

Ardından bunları strings.xml dosyanıza şu şekilde ekleyin:

<!-- 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>

your_parse_app_id ve your_parse_client_key öğelerini kimlik bilgilerinizle değiştirdiğinizden emin olun.

Ardından, internet erişimini etkinleştirmek ve kimlik bilgileri meta verilerini eklemek için AndroidManifest.xml dosyanızı değiştirin:

<!-- 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>

Yapmamız gereken son şey Parse’ı başlatmak. Parse’ın herhangi bir faaliyetten önce başlatıldığından emin olmak için, Application sınıfından miras alan App adında yeni bir sınıf oluşturacağız.

App.kt dosyasını oluşturun ve Parse’ı aşağıdaki gibi başlatın:

// 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()
        )
    }
}

Ardından App sınıfını AndroidManifest.xml dosyasına kaydedin:

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

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

Uygulamayı bir kez daha yeniden oluşturun ve Logcat penceresinde herhangi bir hata olup olmadığını kontrol edin. Hata yoksa Back4app ile bağlantı başarılı olmuştur.

Back4app’ten Notlar Yükleyin

Uygulamamız tamamlanmadan önce yapmamız gereken son şey, Back4app veritabanından notları yüklemek ve Parse’ı pratikte nasıl kullanacağımıza bakmaktır.

AppViewModel‘e giderek başlayın. Haritadan verileri kaldırın ve init bloğunu ekleyin:

// 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 {
        // ...
    }
}

Bu kod, notları veritabanlarından almak için Parse SDK’yı kullanır, bunları Not veri sınıfına dönüştürür ve haritaya kaydeder.

Ardından, aşağıdaki üç yöntemi Note‘a ekleyin:

// 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() Parse sunucusuna ayrıntılarıyla birlikte yeni bir not ekler. Başarılı olursa, notun benzersiz tanımlayıcısını saklar ve tamamlandığında bildirimde bulunur.
  2. updateToParse() Parse sunucusundaki mevcut bir notun bilgilerini günceller. Başarılı olursa, değişiklikleri yaptıktan sonra tamamlandığını bildirir.
  3. deleteFromParse() kaydedilmiş bir notu Parse sunucusundan kaldırır. Başarılı olursa, bittiğinde silme işlemini onaylar.

Son olarak, yeni tanımlanan yöntemleri çağırmak için FormActivity ‘deki tıklama yöntemlerini değiştirin:

// 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()
                    }
                },
            )
        }
    }
}

Bu kadar!

Uygulama artık tamamen çalışıyor ve Back4app arka ucuyla senkronize edildi. Verileri değiştirerek ve değişikliklerin veritabanı görünümüne yansıtılıp yansıtılmadığını kontrol ederek uygulamayla oynamayı deneyin.

Sonuç

Bu makalede, başarılı bir şekilde bir mobil arka uç oluşturduk ve Android uygulamamızdan ona bağlandık. Arka uç için Back4app’in BaaS çözümünü kullandık ve ön uçta Jetpack Compose ile Kotlin’i kullandık.

Şimdiye kadar, mobil arka uçların nasıl çalıştığına dair yeterli bir anlayışa sahip olmalı ve kendi arka ucunuzu oluşturabilmelisiniz. Son kaynak kodunu back4app-android-app reposunda görüntüleyin.


Leave a reply

Your email address will not be published.