Como criar um backend para um aplicativo Android?
Neste artigo, falaremos sobre o Android, um dos sistemas operacionais mais populares. Veremos os prós e os contras do desenvolvimento do Android, as opções de backend para aplicativos móveis e ensinaremos a você como criar seu próprio backend móvel.
Contents
- 1 Principais conclusões
- 2 O que é o Android?
- 3 Benefícios do desenvolvimento do Android
- 4 Limitações do desenvolvimento do Android
- 5 Opções de back-end para aplicativos Android
- 6 Como criar um backend para um aplicativo Android?
- 7 Conclusão
Principais conclusões
- Domínio do Android: O Android, como um sistema operacional de código aberto, alimenta cerca de 70% dos dispositivos móveis com mais de três bilhões de usuários ativos.
- Opções de back-end para aplicativos: Para back-ends de aplicativos móveis, os desenvolvedores podem optar por infraestrutura como serviço (IaaS), plataforma como serviço (PaaS) ou back-end como serviço (BaaS).
- Etapas para criar seu backend: Forneceremos um tutorial detalhado sobre como criar um backend do Android usando uma plataforma BaaS e o código-fonte até o final do artigo.
O que é o Android?
O Android é um sistema operacional gratuito e de código aberto baseado em Linux. Ele foi projetado principalmente para dispositivos móveis, como smartphones e tablets, mas agora também é usado em smart TVs, sistemas incorporados, consoles de jogos, etc.
O desenvolvimento do Android começou em 2003 pela Android Inc. A empresa inicialmente queria criar um sistema operacional para câmeras digitais, mas rapidamente mudou para o desenvolvimento de sistemas operacionais móveis para atingir um mercado mais amplo.
Em 2005, a empresa foi adquirida pelo Google, juntamente com seus funcionários. A primeira versão do Android foi lançada em 2008.
Embora o Android seja de código aberto, a maioria dos dispositivos móveis executa a versão proprietária do Google. Sua versão vem pré-instalada com softwares como o Google Chrome, YouTube, Google TV e Gmail.
Devido às ótimas opções de personalização do Android, muitos fabricantes também personalizam o Android para representar melhor sua empresa. É por isso que o Android do OnePlus é bem diferente do Android do Pixel.
O Android tem sido o sistema operacional mais popular desde 2013. Ele é usado por cerca de 70% dos dispositivos móveis e tem mais de três bilhões de usuários ativos mensais.
Além disso, a Google Play Store oferece acesso a mais de três milhões de aplicativos móveis. Continue lendo para saber como criar um backend para um aplicativo Android.
Benefícios do desenvolvimento do Android
Vamos explorar algumas das vantagens do desenvolvimento para Android.
Plataforma cruzada
Ao desenvolver para o Android, você pode atingir uma ampla gama de dispositivos. Isso inclui telefones celulares, wearables, smart TVs, consoles de jogos e muito mais. Se você sabe como codificar um aplicativo móvel, não terá problemas para desenvolver um aplicativo para dispositivos portáteis ou smart TVs.
Mercado enorme
Conforme apresentado anteriormente, o Android detém uma participação de mercado maior, com 70%, em comparação com o iOS, com 30%. Ao desenvolver aplicativos para Android, você poderá automaticamente obter acesso a um público mais amplo.
Além disso, os aplicativos Android são conhecidos por seu baixo investimento e alto retorno sobre o investimento. Ao contrário do iOS, também não há taxas anuais de desenvolvedor envolvidas.
Personalização
Os dispositivos Android são altamente personalizáveis em comparação com outros sistemas operacionais. Eles permitem que você altere praticamente qualquer coisa que possa imaginar.
Além disso, o Android permite que você integre facilmente seu aplicativo a outros serviços de terceiros.
Comunidade
O Android é apoiado por uma enorme comunidade de desenvolvedores de código aberto. Além disso, ele vem com muitas ferramentas amigáveis ao desenvolvedor, como Android Studio, ADB e Logcat, que permitem codificar aplicativos facilmente.
Se você tiver algum problema, há várias plataformas em que pode encontrar ajuda, incluindo GitHub, StackOverflow, Reddit e outras comunidades voltadas para o Android.
Limitações do desenvolvimento do Android
Aqui estão alguns dos contras do desenvolvimento do Android.
Segurança
O Android é menos seguro que o iOS e não segue protocolos de segurança rígidos. Como o Android é de código aberto, as vulnerabilidades de segurança são detectadas semanalmente. Isso dá aos hackers a capacidade de explorar essas vulnerabilidades antes que elas sejam corrigidas.
Os dispositivos Android também podem ser enraizados para obter acesso de superusuário. Embora isso torne seu dispositivo mais avançado, também é arriscado, pois desativa algumas medidas de segurança incorporadas.
Complexidade
Os dispositivos Android vêm em diferentes formas e tamanhos e, embora isso seja ótimo, pode ser uma grande desvantagem ao desenvolver aplicativos Android para vários tipos de dispositivos.
Para garantir que seu aplicativo seja compatível com o maior número possível de dispositivos, você terá que incorporar o design responsivo, pensar no hardware de diferentes dispositivos e assim por diante.
Os aplicativos premium têm menos sucesso na Google Play Store em comparação com a App Store. Não é segredo que os usuários do Android tendem a gastar menos em aplicativos do que os usuários do iOS. Se estiver trabalhando em um aplicativo premium primeiro, considere o Android como sua segunda opção.
Opções de back-end para aplicativos Android
Qual é o melhor backend para aplicativos Android? Os back-ends para aplicativos móveis podem ser hospedados em sua própria infraestrutura ou implantados nos serviços de nuvem. Os modelos de computação em nuvem mais populares para back-ends móveis incluem:
- Infraestrutura como serviço (IaaS)
- Plataforma como serviço (PaaS)
- Backend como serviço (BaaS)
Cada opção abrange diferentes camadas de abstração, conforme ilustrado na imagem abaixo.
Vamos examinar cada opção em detalhes para ajudá-lo a selecionar o modelo de nuvem mais adequado para seus aplicativos de back-end.
Infraestrutura como serviço (IaaS)
A infraestrutura como serviço (IaaS) é o modelo de computação em nuvem menos abstraído. Nesse modelo, o fornecedor oferece aos usuários recursos virtualizados, como servidores, redes, armazenamento e sistemas operacionais, por meio de APIs de alto nível ou painéis de controle intuitivos.
O melhor da IaaS é que ela oferece aos usuários controle total sobre toda a infraestrutura. A IaaS é o modelo mais flexível e dimensionável, mas também o mais difícil de gerenciar. Se você escolher essa opção, provavelmente precisará de um ou dois administradores de sistemas.
Alguns exemplos de IaaS são o Amazon Web Services, o Google Cloud Platform e o Azure.
Plataforma como serviço (PaaS)
A PaaS (Platform as a Service) é um modelo de computação em nuvem projetado para ajudar os usuários a desenvolver, gerenciar e implementar aplicativos.
Além de fornecer infraestrutura, a PaaS vem com ferramentas fáceis de usar para desenvolver, personalizar e testar aplicativos.
Ao utilizar a PaaS, você poderá se concentrar no seu software e na experiência do usuário sem se preocupar com a infraestrutura subjacente.
Além disso, a PaaS garantirá que seu aplicativo seja dimensionado sob demanda, cuidará dos backups, etc. As desvantagens da PaaS são o menor nível de controle, o risco de dependência do fornecedor e os custos comparativamente mais altos.
As plataformas PaaS mais populares incluem Heroku, Render e Digital Ocean App Platform.
Backend como serviço (BaaS)
O Backend as a Service (BaaS) automatiza a parte de backend do desenvolvimento, fornecendo uma solução de backend completa.
Os recursos de BaaS incluem gerenciamento de usuários, bancos de dados, autenticação, integrações sociais, notificações por push, APIs, SDKs e muito mais.
O BaaS oferece a você todas as vantagens do IaaS e do PaaS, ao mesmo tempo em que fornece funcionalidades adicionais. As equipes que utilizam o BaaS tendem a lançar seus produtos mais rapidamente, reduzir os custos de engenharia e criar softwares melhores.
As desvantagens do BaaS incluem um nível mais baixo de controle e personalização e a possibilidade de dependência do fornecedor para plataformas de código não aberto.
Exemplos de BaaS incluem Back4app, AWS Amplify e Firebase.
Como criar um backend para um aplicativo Android?
Nesta seção do artigo, veremos como criar um aplicativo backend baseado no Back4app e conectar-se a ele a partir de um aplicativo Android.
Pré-requisitos
- Experiência com Kotlin e desenvolvimento Android.
- Conhecimento básico de Backend móvel como serviço.
- Java e Android Studio instalados em seu computador local.
O que é o Back4app?
O Back4app é uma excelente plataforma para criar backends para aplicativos modernos e acelerar o processo de desenvolvimento.
Ele vem bem equipado com recursos úteis do lado do servidor, como gerenciamento de usuários, bancos de dados em tempo real, integrações sociais, funções do Cloud Code, notificações push, APIs e muito mais!
Ao usar o Back4app, você poderá terceirizar grande parte do trabalho de back-end e se concentrar nos aspectos críticos do seu aplicativo, além de acelerar o desenvolvimento do back-end de um aplicativo Android.
Não haverá necessidade de lidar com a infraestrutura subjacente de seu backend, servidor de backend, dimensionamento, manutenção, etc.
Mais importante ainda, o Back4app oferece um nível gratuito que é ótimo para experimentar e testar a plataforma. À medida que seu aplicativo cresce, você pode fazer upgrade para planos premium mediante o pagamento de uma taxa mensal.
Introdução ao projeto
Neste artigo, criaremos um aplicativo simples de anotações. O aplicativo permitirá que os usuários adicionem, editem e excluam notas. As anotações serão armazenadas no banco de dados do Back4app e manipuladas por meio do Parse SDK.
Usaremos a linguagem de programação Kotlin para criar o aplicativo. Para a interface do usuário, utilizaremos o Jetpack Compose, o kit de ferramentas moderno do Android para criar interfaces do usuário nativas.
Criar o aplicativo Back4app
Como primeira etapa para desenvolver um backend para um aplicativo Android, você precisará de uma conta no Back4app. Se ainda não tiver uma, vá em frente e registre-se.
Ao fazer login na sua conta Back4app, você será redirecionado para a visualização do aplicativo. Clique em “Build new app” (Criar novo aplicativo) para iniciar o processo de criação do aplicativo.
A plataforma Back4app oferece duas soluções:
- Backend as a Service (BaaS) – solução robusta de backend
- Contêineres como serviço (CaaS): plataforma para gerenciar contêineres (especialmente aplicativos da Web)
Considerando que estamos criando um backend para um aplicativo móvel, escolheremos o “Backend as a Service”.
Dê ao seu aplicativo um nome bonito e informativo, selecione “NoSQL” como o banco de dados e clique em “Create”. Essa é uma etapa importante para implementar um backend para um aplicativo Android.
A Back4app levará algum tempo para preparar tudo o que é necessário para seu aplicativo. Isso inclui o banco de dados, o gerenciamento de usuários, o dimensionamento, as configurações, etc. Quando o aplicativo estiver pronto, você será redirecionado para a visualização do banco de dados do aplicativo.
Projetar o banco de dados
Continuando, vamos projetar o banco de dados. Essa é uma etapa necessária para desenvolver um backend para um aplicativo Android.
Como estamos criando um aplicativo simples de notas, precisaremos apenas de uma classe. Clique em “Create a class” (Criar uma classe), chame-a de Note (Nota
), ative “Public Read and Write” (Leitura e gravação públicas) e clique em “Create class & add columns” (Criar classe e adicionar colunas).
Em seguida, adicione os três campos a seguir à classe recém-criada:
+-------------+-------------+--------------------+----------+
| Data type | Name | Default value | Required |
+-------------+-------------+--------------------+----------+
| String | icon | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
| String | title | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
| String | content | <leave blank> | yes |
+-------------+-------------+--------------------+----------+
Por fim, clique no botão “Add row” (Adicionar linha) e preencha seu banco de dados com alguns dados de amostra. Se não tiver nenhuma ideia, você também pode importar esse despejo de dados.
Ótimo, isso é tudo para o backend.
Código Frontend
Nesta seção do artigo, faremos o bootstrap de um novo aplicativo Android, configuraremos um ViewModel, implementaremos a interface do usuário, instalaremos e configuraremos o Parse SDK e, por fim, buscaremos dados do banco de dados em tempo real do Back4app.
Projeto Init
Conforme mencionado na seção de pré-requisitos, as etapas a seguir exigirão que você tenha o Android Studio instalado. Se você ainda não o tiver, faça o download.
Comece abrindo o Android Studio e clicando no botão “New Project” (Novo projeto).
Em seguida, selecione “Empty Activity” (Atividade vazia) como seu modelo de projeto e clique em “Next” (Avançar).
Para criar seu projeto, você deve fornecer um nome e um nome de pacote. Sugiro que você use AndroidApp
como o nome do projeto e o nome de domínio reverso como o pacote do projeto.
Depois de configurar tudo, clique em “Finish” (Concluir) para criar o projeto.
O Android Studio levará cerca de dois minutos para preparar tudo o que for necessário. Isso inclui a criação da estrutura de arquivos do projeto, a configuração do Gradle, a instalação de dependências etc.
Quando seu projeto estiver pronto, use o explorador para navegar até MainActivity.kt e substituir seu conteúdo:
// 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)
}
}
}
}
}
Certifique-se de sempre substituir pelo nome real do pacote.
Por fim, tente executar o aplicativo clicando no botão verde de reprodução ou em Shift + F10
no teclado. Se tudo correr bem, o emulador deverá ser iniciado e você deverá ver a mensagem Back4app rocks
na tela.
ViewModel
Para gerenciar o estado global do nosso aplicativo, utilizaremos um ViewModel
. Mas, antes disso, temos de criar uma classe de dados Note
com os mesmos atributos da classe do nosso banco de dados Back4app.
Crie uma classe de dados chamada Note
:
// 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("")
}
}
}
- Definimos o método estático
generateObjectId()
para gerar IDs de objeto do tipo Parse. objectId
é anulável, pois mais tarde assumiremos que, seobjectId == null
, o objeto ainda não foi salvo no banco de dados.
Em seguida, crie uma classe AppViewModel
com o seguinte conteúdo:
// 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 }
}
}
}
}
- Usamos o
MutableState
do Compose para acionar atualizações da IU em caso de alteração de dados. - O
MutableState
contém ummapa
deobjectIds
eNotes
, que preenchemos com dados. - Para garantir que haja apenas uma única instância do
AppViewModel
, usamos o padrão singleton.
Agora podemos acessar a instância do AppViewModel
em nossas atividades por meio de AppViewModel.getInstance()
.
Atividade principal
Em seguida, substitua o conteúdo do MainActivity.kt pelo seguinte código para exibir as anotações:
// 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)
}
}
}
- As
notas
agora estão sendo obtidas doAppViewModel
. - Em vez de definir os eventos de clique em composables, nós os passamos como argumentos.
- Usamos o Compose para projetar a interface do usuário. Para torná-la mais elegante, incorporamos o
MaterialTheme
ao layoutdo Scaffold
.
Se você reconstruir o aplicativo agora, deverá ver a lista de notas “codificadas” na tela.
Atividade do formulário de notas
Nesta seção, adicionaremos uma nova atividade que permitirá aos usuários adicionar e editar notas.
Comece criando uma nova classe chamada FormActivity
com o seguinte conteúdo:
// 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")
}
}
}
- Esse formulário é usado para adicionar e editar notas. Para determinar a ação, comparamos
objectId == null
. No caso denull
, é uma ação de adição, caso contrário, é uma ação de edição. - Se
objectId !== null
, buscaremos anota
do estado e preencheremos o formulário. - Para que
o MutableState
funcionasse corretamente, tivemos que tratar seu conteúdo como imutável. É por isso que, às vezes, copiamos o conteúdo em vez de modificá-lo. - Tratamos o estado do formulário Compose por meio de
mutableStateOf()
.
Em seguida, registre o FormActivity
na parte inferior do aplicativo
no 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>
Por fim, crie um novo Intent
em onNoteListItemClick
e onNoteAddClick
em 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)
},
)
}
}
}
Não se esqueça de importar o Intent
na parte superior do arquivo:
import android.content.Intent
Se você reconstruir o aplicativo, perceberá que agora temos um aplicativo em funcionamento. O aplicativo nos permite adicionar notas, editá-las e excluí-las.
O único problema é que reiniciar o aplicativo redefine seu estado (para as notas “codificadas”).
Na próxima seção, conectaremos o aplicativo ao backend do Back4app. Isso nos permitirá manter o estado e sincronizá-lo entre vários dispositivos.
Instalar o Parse SDK
Como você deve saber, o Back4app é baseado na plataforma Parse. Se quisermos interagir com o banco de dados do Back4app ou com o Back4app em geral, teremos de instalar o Parse SDK.
Comece adicionando o repositório do JitPack ao 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" }
}
}
Em seguida, adicione o Android Parse SDK ao build.gradle do nível do aplicativo:
// app/build.gradle
dependencies {
// ...
implementation "com.github.parse-community.Parse-SDK-Android:parse:4.2.0"
}
Sincronize as configurações do Gradle e verifique se não há erros.
Configurar o Parse SDK
Para se conectar ao backend do Back4app, você terá de fornecer ao Parse SDK o ID do aplicativo e a chave do cliente. Para obter suas credenciais, navegue até o aplicativo Back4app e selecione “App Settings > Security & Keys” (Configurações do aplicativo > Segurança e chaves) na barra lateral.
Em seguida, adicione-os ao seu strings.xml da seguinte forma:
<!-- 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>
Certifique-se de substituir
your_parse_app_id
eyour_parse_client_key
por suas credenciais.
Em seguida, modifique seu AndroidManifest.xml para habilitar o acesso à Internet e anexar metadados de credenciais:
<!-- 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>
A última coisa que temos de fazer é inicializar o Parse. Para garantir que o Parse seja inicializado antes de qualquer atividade, criaremos uma nova classe chamada App
, que herda da classe Application
.
Crie o App.kt e inicialize o Parse da seguinte forma:
// 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()
)
}
}
Em seguida, registre a classe App
no AndroidManifest.xml:
<!-- app/src/main/AndroidManifest.xml -->
<application
android:name=".App"
...
>
<!-- ... -->
</application>
Reconstrua o aplicativo mais uma vez e verifique se há erros na janela Logcat. Se não houver erros, a conexão com o Back4app foi bem-sucedida.
Carregar notas do Back4app
A última coisa que precisamos fazer antes de concluir nosso aplicativo é carregar as anotações do banco de dados do Back4app e ver como usar o Parse na prática.
Comece navegando até o AppViewModel
. Remova os dados do mapa e adicione o bloco de inicialização
:
// 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 {
// ...
}
}
Esse código usa o Parse SDK para buscar as anotações nos bancos de dados, transformá-las na classe de dados Note
e salvá-las no mapa.
Em seguida, adicione os três métodos a seguir ao Note
:
// 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()
adiciona uma nova nota ao servidor Parse com seus detalhes. Se for bem-sucedido, ele armazena o identificador exclusivo da nota e avisa quando terminar.updateToParse()
atualiza as informações de uma nota existente no servidor do Parse. Se for bem-sucedido, ele sinaliza a conclusão após fazer as alterações.deleteFromParse()
remove uma nota salva do servidor do Parse. Se for bem-sucedido, ele confirmará a exclusão quando terminar.
Por fim, modifique os métodos de clique em FormActivity
para invocar os métodos recém-definidos:
// 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()
}
},
)
}
}
}
É isso aí!
O aplicativo agora está totalmente funcional e sincronizado com o backend do Back4app. Experimente brincar com o aplicativo alterando os dados e verificando se as alterações são refletidas na visualização do banco de dados.
Conclusão
Neste artigo, criamos com sucesso um backend móvel e nos conectamos a ele a partir do nosso aplicativo Android. Usamos a solução BaaS da Back4app para o backend e, no frontend, utilizamos o Kotlin com o Jetpack Compose.
A esta altura, você já deve ter uma boa compreensão de como funcionam os back-ends móveis e deve ser capaz de criar o seu próprio. Veja o código-fonte final no repositório back4app-android-app.