Bir Android uygulaması için arka uç nasıl oluşturulur?
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.
Contents
Ö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:
- Hizmet Olarak Altyapı (IaaS)
- Hizmet Olarak Platform (PaaS)
- Hizmet Olarak Arka Uç (BaaS)
Her seçenek, aşağıdaki resimde gösterildiği gibi farklı soyutlama katmanlarını kapsar.
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
- Kotlin ve Android geliştirme deneyimi.
- Hizmet olarak Mobil Arka Uç hakkında temel anlayış.
- Yerel makinenizde Java ve Android Studio yüklü olmalıdır.
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 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 platformu iki çözüm sunmaktadır:
- Hizmet Olarak Arka Uç (BaaS) – sağlam arka uç çözümü
- 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.
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.
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.
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.
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.
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’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.
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("")
}
}
}
- Parse benzeri nesne kimlikleri oluşturmak için statik
generateObjectId()
yöntemini tanımladık. 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 }
}
}
}
}
- Veri değişikliği durumunda UI güncellemelerini tetiklemek için Compose’un
MutableState
özelliğini kullandık. MutableState
, verilerle doldurduğumuzobjectId
‘ler veNotes
‘lardan oluşan birHarita
tutar.AppViewModel
‘in yalnızca tek bir örneği olduğundan emin olmak için singletonmodelini
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)
}
}
}
Notlar
artıkAppViewModel
‘den alınıyor.- Tıklama olaylarını bileşiklerde tanımlamak yerine, bunları argüman olarak aktardık.
- Kullanıcı arayüzünü tasarlamak için Compose kullandık. Daha şık hale getirmek için
MaterialTheme
‘i Scaffold
düzeniyle birleştirdik.
Uygulamayı şimdi yeniden oluşturursanız, ekranda “sabit kodlanmış” notların listesini görmelisiniz.
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")
}
}
}
- 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. objectId !== null
ise,notu
durumdan alırız ve formu doldururuz.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.- 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.
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
veyour_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()
}
}
}
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.updateToParse()
Parse sunucusundaki mevcut bir notun bilgilerini günceller. Başarılı olursa, değişiklikleri yaptıktan sonra tamamlandığını bildirir.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.