Conceitos básicos da AWS

Criar uma aplicação Android

Criar uma aplicação Android simples usando o AWS Amplify

Módulo 1: Criar e implantar um aplicativo Android

Neste módulo, você criará uma aplicação Android e a implantará na nuvem usando o serviço de hospedagem na Web do AWS Amplify.

Introdução

O AWS Amplify fornece um fluxo de trabalho baseado em Git para criar, gerenciar, integrar e implantar back-ends sem servidor para aplicações móveis e Web. A CLI do Amplify fornece uma interface de usuário simples baseada em texto para provisionar e gerenciar serviços de back-end, como autenticação de usuário ou API REST ou GraphQL para suas aplicações. As Bibliotecas do Amplify permitem integrar facilmente esses serviços de back-end com apenas algumas linhas de código em suas aplicações.

Neste módulo, começaremos criando uma aplicação Android nova para fazer anotações (notas) de viagem. Uma nota é composta de um título, uma descrição e uma imagem. Vamos aprimorar essa aplicação nos próximos módulos.

O que você aprenderá

  • Criar uma aplicação Android
  • Atualizar a visualização principal para exibir uma lista de itens
  • Compilar e testar sua aplicação

Conceitos principais

Kotlin a Kotlin foi escolhida como a linguagem de programação deste tutorial porque permite reduzir muito do código padronizado e foi projetada para segurança de tipo (type safety).

Jetpack – este tutorial usa o Jetpack do Android, uma coleção de bibliotecas do Android que incorporam as melhores práticas e garantem compatibilidade com versões anteriores em seus aplicativos Android.

 Tempo para a conclusão

10 minutos

 Serviços usados

Implementação

  • Criar um projeto do Android

    Inicie o Android Studio e selecione Start a new Android Studio project (Iniciar um novo projeto do Android Studio) na tela inicial:

    AndroidAppTutorial_Modiule1_Image1

    EmPhone and Tablet (Telefone e tablet), selecione Basic Activity (Atividade básica) e clique em Next (Avançar):

    AndroidAppTutorial_Modiule1_Image2

    Digite um nome para o projeto, por exemplo Conceitos básicos do Android. Verifique se a linguagem é Kotlin e se o SDK mínimo é API 26: Android 8.0 (oreo) e clique em Finish (Concluir):

    AndroidAppTutorial_Modiule1_Image3

    Com a estrutura do projeto pronta, seguimos quatro etapas para colocar nosso aplicativo básico em execução:

    1. Excluir classes e arquivos indesejados e adicionar plug-ins
    2. Criar classes para manter nossas estruturas de dados
    3. Criar uma visualização para manter uma nota individual na lista
    4. Modificar a MainActivity para exibir uma lista de notas
  • Excluir arquivos desnecessários e adicionar plug-ins

    Em res/layout e java/com.example.androidgettingstarted, exclua os quatro arquivos de fragmento (selecione os quatro arquivos, clique com o botão direito e escolha Delete [Excluir] no menu contextual):

    AndroidAppTutorial_Modiule1_Image4

    Em Gradle Scripts (Scripts do Gradle), abra build.gradle (Module:app) e adicione o plug-in de extensão Kotlin.

    plugins {
        id 'com.android.application'
        id 'kotlin-android'
        id 'kotlin-android-extensions' //  <== add this line
    }
  • Criar uma classe de dados UserData

    A classe UserData armazena o estado do usuário: um sinalizador isSignedIn e uma lista de valores de nota.

    Para criar uma classe nova, clique com o botão direito em java/com.example/androidgettingstarted e selecione New (Novo) -> Kotlin file/class (Arquivo/classe Kotlin). Digite UserData como o nome.

    AndroidAppTutorial_Modiule1_Image5

    Cole o código abaixo no arquivo recém-criado (UserData.kt)

    package com.example.androidgettingstarted
    
    import android.graphics.Bitmap
    import android.util.Log
    import androidx.lifecycle.LiveData
    import androidx.lifecycle.MutableLiveData
    
    // a singleton to hold user data (this is a ViewModel pattern, without inheriting from ViewModel)
    object UserData {
    
        private const val TAG = "UserData"
    
        //
        // observable properties
        //
    
        // signed in status
        private val _isSignedIn = MutableLiveData<Boolean>(false)
        var isSignedIn: LiveData<Boolean> = _isSignedIn
    
        fun setSignedIn(newValue : Boolean) {
            // use postvalue() to make the assignation on the main (UI) thread
            _isSignedIn.postValue(newValue)
        }
    
        // the notes
        private val _notes = MutableLiveData<MutableList<Note>>(mutableListOf())
    
        // please check https://stackoverflow.com/questions/47941537/notify-observer-when-item-is-added-to-list-of-livedata
        private fun <T> MutableLiveData<T>.notifyObserver() {
            this.postValue(this.value)
        }
        fun notifyObserver() {
            this._notes.notifyObserver()
        }
    
        fun notes() : LiveData<MutableList<Note>>  = _notes
        fun addNote(n : Note) {
            val notes = _notes.value
            if (notes != null) {
                notes.add(n)
                _notes.notifyObserver()
            } else {
                Log.e(TAG, "addNote : note collection is null !!")
            }
        }
        fun deleteNote(at: Int) : Note?  {
            val note = _notes.value?.removeAt(at)
            _notes.notifyObserver()
            return note
        }
    
        fun resetNotes() {
            this._notes.value?.clear()  //used when signing out
            _notes.notifyObserver()
        }
    
    
        // a note data class
        data class Note(val id: String, val name: String, val description: String, var imageName: String? = null) {
            override fun toString(): String = name
    
            // bitmap image
            var image : Bitmap? = null
    
        }
    }

    O que acabamos de adicionar?

    • A classe UserData é responsável por armazenar os dados do usuário, ou seja, um sinalizador isSignedIn para acompanhar o status de autenticação atual e uma lista de objetos Note.
    • Essas duas propriedades são implementadas de acordo com a estrutura de trabalho de publicação/assinatura do LiveData. Isso permite que a interface gráfica do usuário (GUI) assine as alterações e reaja de acordo. Para saber mais sobre o LiveData, você pode ler este documento ou seguir este breve tutorial em vídeo. Para seguir a melhor prática, mantenha a propriedade MutableLiveData privada e exponha apenas a propriedade LiveData somente leitura. É necessário algum código padronizado adicional quando os dados a publicar são uma lista, para garantir que os observadores sejam notificados quando componentes individuais na lista forem modificados.
    • Também adicionamos uma nota data class, apenas para armazenar os dados de notas individuais. Duas propriedades distintas são usadas para ImageName e Image. Image será tratado em um módulo subsequente.
    • O padrão de projeto singleton foi implementado para o objeto UserData, pois permite que sejam feitas referências a ele de qualquer lugar na aplicação apenas com UserData.
  • Adicionar GUI para células individuais na lista

    Células individuais em uma lista de rolagem são chamadas de RecyclerView, pois a visualização pode ser reciclada quando o usuário rola para cima e para baixo, e a visualização não está mais visível na tela.

    Assim como em uma visualização normal, criamos arquivos XML de layout e uma classe Kotlin. Esta é a aparência de uma célula:

    AndroidAppTutorial_Modiule1_Image6

    Para criar o arquivo de layout, clique com o botão direito em res/layout e selecione New -> Layout Resource File (Novo -> Arquivo de recursos de layout). Digite content_note como o nome e mantenha todos os outros valores, pois vamos editar diretamente o arquivo XML.

    AndroidAppTutorial_Modiule1_Image7

    Abra a visualização Code (Código) do arquivo recém-criado.

    AndroidAppTutorial_Modiule1_Image8

    Na visualização Code (Código) do arquivo novo recém-criado (content_note.xml), cole o código abaixo para substituir o código gerado:

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:paddingVertical="16dp">
    
        <ImageView
            android:id="@+id/image"
            android:layout_width="100dp"
            android:layout_height="match_parent"
            android:padding="8dp"
            android:scaleType="centerCrop"
            android:src="@drawable/ic_launcher_background" />
    
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginLeft="5dp"
            android:orientation="vertical">
    
            <TextView
                android:id="@+id/name"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Title"
                android:textSize="20sp"
                android:textStyle="bold" />
    
            <TextView
                android:id="@+id/description"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="Title"
                android:textSize="15sp" />
    
        </LinearLayout>
    </LinearLayout>

    Por fim, crie a classe Kotlin: clique com o botão direito em java/com.example/androidgettingstarted e selecione New -> Kotlin file/class (Novo -> Arquivo/classe Kotlin). Digite NoteRecyclerViewAdapter como o nome.

    AndroidAppTutorial_Modiule1_Image9

    Cole o código abaixo no arquivo recém-criado (NoteRecyclerViewAdapter.kt)

    package com.example.androidgettingstarted
    
    import android.view.LayoutInflater
    import android.view.View
    import android.view.ViewGroup
    import android.widget.ImageView
    import android.widget.TextView
    import androidx.recyclerview.widget.RecyclerView
    
    // this is a single cell (row) in the list of Notes
    class NoteRecyclerViewAdapter(
        private val values: MutableList<UserData.Note>?) :
        RecyclerView.Adapter<NoteRecyclerViewAdapter.ViewHolder>() {
    
        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val view = LayoutInflater.from(parent.context)
                .inflate(R.layout.content_note, parent, false)
            return ViewHolder(view)
        }
    
        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    
            val item = values?.get(position)
            holder.nameView.text = item?.name
            holder.descriptionView.text = item?.description
    
            if (item?.image != null) {
                holder.imageView.setImageBitmap(item.image)
            }
        }
    
        override fun getItemCount() = values?.size ?: 0
    
        inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
            val imageView: ImageView = view.findViewById(R.id.image)
            val nameView: TextView = view.findViewById(R.id.name)
            val descriptionView: TextView = view.findViewById(R.id.description)
        }
    }

    O que acabamos de adicionar?
    O código acima é composto de

    • um arquivo xml de layout que descreve o layout do componente em uma célula que representa uma nota. Ele exibe a imagem, além do título e a descrição da nota.
    • uma classe Kotlin de suporte. Recebe um objeto de dados de nota no momento da criação e atribui valores individuais às visualizações correspondentes (imagem, título e descrição)
  • Atualizar a atividade principal

    Agora que temos as classes de dados (UserData e Note) e a visualização da nota (NoteRecyclerViewAdapter), criaremos a lista de notas na atividade principal.

    Na lista de arquivos à esquerda do Android Studio, abra res/layout/content_main.xml e substitua o código por este conteúdo:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:id="@+id/frameLayout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/item_list"
            android:name="com.example.myapplication.ItemListFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_marginTop="60dp"
    
            android:paddingHorizontal="8dp"
            android:paddingVertical="8dp"
            app:layoutManager="LinearLayoutManager"
            tools:context=".MainActivity"
            tools:listitem="@layout/content_note" />
    
    </FrameLayout>

    Na lista de arquivos à esquerda do Android Studio, abra java/com.example/androidgettingstarted/MainActivity.kt e substitua o código por este conteúdo:

    package com.example.androidgettingstarted
    
    import android.os.Bundle
    import android.util.Log
    import androidx.appcompat.app.AppCompatActivity
    import androidx.lifecycle.Observer
    import androidx.recyclerview.widget.ItemTouchHelper
    import androidx.recyclerview.widget.RecyclerView
    import kotlinx.android.synthetic.main.activity_main.*
    import kotlinx.android.synthetic.main.content_main.*
    
    class MainActivity : AppCompatActivity() {
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            setSupportActionBar(toolbar)
    
            // prepare our List view and RecyclerView (cells)
            setupRecyclerView(item_list)
        }
    
        // recycler view is the list of cells
        private fun setupRecyclerView(recyclerView: RecyclerView) {
    
            // update individual cell when the Note data are modified
            UserData.notes().observe(this, Observer<MutableList<UserData.Note>> { notes ->
                Log.d(TAG, "Note observer received ${notes.size} notes")
    
                // let's create a RecyclerViewAdapter that manages the individual cells
                recyclerView.adapter = NoteRecyclerViewAdapter(notes)
            })
        }
    
        companion object {
            private const val TAG = "MainActivity"
        }
    }

    O que acabamos de adicionar?

    • o layout principal é um RecyclerView que gerencia a lista de células individuais que criamos anteriormente
    • a classe de atividade principal observa as alterações na lista de notas e cria um NoteRecyclerViewAdapter para criar células individuais.
  • Verificar as dependências de compilação

    Em Gradle Scripts, abra build.gradle (Module:app) e verifique se as dependências geradas estão corretas. As `versões das bibliotecas` precisam ser verificadas.

    ```gradle
    dependencies {
        implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
        implementation 'androidx.core:core-ktx:1.3.2'
        implementation 'androidx.appcompat:appcompat:1.2.0'
        implementation 'com.google.android.material:material:1.2.1'
        implementation 'androidx.constraintlayout:constraintlayout:2.0.2'
        implementation 'androidx.navigation:navigation-fragment-ktx:2.3.1'
        implementation 'androidx.navigation:navigation-ui-ktx:2.3.1'
        testImplementation 'junit:junit:4.+'
        androidTestImplementation 'androidx.test.ext:junit:1.1.2'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    }
  • Compilar e testar

    Agora compile e inicie o aplicativo no simulador. Clique no ícone Run (Executar) ▶️ na barra de ferramentas ou digite ^ R.

    AndroidAppTutorial_Modiule1_Image10

    Após algum tempo, o aplicativo é iniciado no simulador Android, com uma tela inicial vazia.

    AndroidAppTutorial_Modiule1_Image11

    Nesse estágio, não há dados a serem renderizados em tempo de execução. Eliminaremos o ícone de e-mail em uma etapa posterior.

Conclusão

Você criou um aplicativo Android com êxito. Você está pronto para começar a criar com o Amplify!

Este módulo foi útil?

Agradecemos a sua atenção
Gostaríamos de saber do que você gostou.
Fechar
Desculpe por ter desapontado
Encontrou algo desatualizado, confuso ou incorreto? Envie seus comentários para nos ajudar a melhorar este tutorial.
Fechar

Inicializar o Amplify