Nozioni di base su AWS

Creazione di un'applicazione Android

Creazione di un'applicazione Android semplice utilizzando AWS Amplify

Modulo 1: Creazione e distribuzione di un'applicazione Android

In questo modulo, creerai un'applicazione Android e la distribuirai nel cloud tramite il servizio di hosting Web di AWS Amplify.

Introduzione

AWS Amplify fornisce un flusso di lavoro basato su Git per creare, gestire, integrare e distribuire back-end serverless per applicazioni Web e per dispositivi mobili. L'interfaccia a riga di comando (CLI) Amplify mette a disposizione una semplice interfaccia utente basata su testo per offrire e gestire servizi di back-end, ad esempio l'autenticazione utente o l'API REST o GraphQL per le tue applicazioni. Le librerie Amplify consentono una facile integrazione di questi servizi di back-end con l'aggiunta di poche righe di codice alle tue applicazioni.

In questo modulo, inizieremo creando una nuova applicazione Android per prendere note di viaggio. Una nota è composta da un titolo, una descrizione e un'immagine. Miglioreremo questa applicazione nei seguenti moduli.

Avrai modo di approfondire i seguenti aspetti

  • Creazione di un'applicazione Android
  • Aggiornamento della visualizzazione principale per mostrare un elenco di elementi
  • Creazione e test dell'applicazione

Concetti chiave

Kotlin - Kotlin è stato scelto come linguaggio di programmazione per questo tutorial perché consente di ridurre di molto il codice boilerplate ed è stato progettato considerando la sicurezza del tipo.

Jetpack - Questo tutorial utilizza Jetpack di Android, un insieme di librerie Android che incorpora le best practice e fornisce compatibilità con le versioni precedenti nelle applicazioni Android.

 Tempo richiesto per il completamento

10 minuti

 Servizi utilizzati

Implementazione

  • Creazione di un progetto Android

    Avvia Android Studio e seleziona Start a new Android Studio project (Inizia un nuovo progetto Android Studio) dalla splash screen:

    AndroidAppTutorial_Modiule1_Image1

    In Phone and Tablet (Telefono e tablet), seleziona Basic Activity (Attività di base) e fai clic su Next (Avanti):

    AndroidAppTutorial_Modiule1_Image2

    Digita un nome per il progetto, ad esempio Android Getting Started (Nozioni di base su Android). Assicurati che il linguaggio sia Kotlin e che l'SDK minimo sia API 26: Android 8.0 (oreo), quindi fai clic su Finish (Fine):

    AndroidAppTutorial_Modiule1_Image3

    Una volta creata la bozza del progetto, dobbiamo eseguire quattro passaggi per fare in modo che la nostra applicazione di base funzioni:

    1. Eliminazione di classi e file indesiderati e aggiunta di plug-in
    2. Creazione di classi per contenere le nostre strutture di dati
    3. Creazione di una visualizzazione per contenere una singola nota dell'elenco
    4. Modifica della MainActivity per visualizzare un elenco di note
  • Eliminazione di file non necessari e aggiunta di plug-in

    In res/layout e java/com.example.androidgettingstarted, elimina i quattro file fragment (seleziona i 4 file, fai clic con il tasto destro del mouse e scegli Delete (Elimina) dal menu contestuale):

    AndroidAppTutorial_Modiule1_Image4

    In Gradle Scripts (Script Gradle), apri build.gradle (Module:app) e aggiungi il plug-in Kotlin Extension.

    plugins {
        id 'com.android.application'
        id 'kotlin-android'
        id 'kotlin-android-extensions' //  <== add this line
    }
  • Creazione di una classe di dati UserData

    La classe UserData contiene lo stato dell'utente, un flag isSignedIn e un elenco di valori Note.

    Per creare una nuova classe, fai clic con il tasto destro del mouse su java/com.example/androidgettingstarted e seleziona New (Nuovo) -> Kotlin file/class (File/classe Kotlin). Digita UserData come nome.

    AndroidAppTutorial_Modiule1_Image5

    Incolla il codice in basso nel nuovo file appena creato (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
    
        }
    }

    Che cosa abbiamo aggiunto?

    • La classe UserData deve contenere i dati dell'utente, ovvero un flag isSignedIn per tenere traccia dello stato di autenticazione corrente e un elenco di oggetti Note.
    • Queste due proprietà sono implementate in base al framework di pubblicazione/sottoscrizione di LiveData. Permette all'interfaccia utente grafica (GUI) di sottoscrivere le modifiche e di reagire di conseguenza. Per ulteriori informazioni su LiveData, puoi leggere questa documentazione o seguire questo breve tutorial video. Per seguire la best practice, mantieni privata la proprietà MutableLiveData e mostra esclusivamente la proprietà LiveData di sola lettura. Quando i dati da pubblicare corrispondono a un elenco, è necessario un codice boilerplate aggiuntivo per garantire che gli osservatori siano avvisati quando i singoli componenti dell'elenco vengono modificati.
    • Abbiamo anche aggiunto una classe di dati note, solo per contenere i dati delle singole note. Due proprietà diverse vengono utilizzate per ImageName e Image. Image verrà esaminata in un modulo successivo.
    • È stato implementato il singolo modello di progettazione per l'oggetto UserData, in quanto può essere utilizzato come riferimento da qualsiasi punto dell'applicazione solo con UserData.
  • Aggiunta della GUI per le singole celle nell'elenco

    Le singole celle di un elenco a scorrimento sono chiamate RecyclerView, in quanto la visualizzazione può essere riciclata quando l'utente scorre lo schermo verso l'alto e verso il basso e la visualizzazione non è più visibile.

    Proprio come una normale visualizzazione, creiamo file XML di layout e una classe Kotlin. Una singola cella avrà questo aspetto:

    AndroidAppTutorial_Modiule1_Image6

    Per creare il file di layout, fai clic con il tasto destro del mouse su res/layout e seleziona New (Nuovo) -> Layout Resource File (File risorse di layout). Digita content_note come nome e lascia tutti gli altri valori, in quanto modificheremo direttamente il file XML.

    AndroidAppTutorial_Modiule1_Image7

    Apri la visualizzazione Codice per il file appena creato.

    AndroidAppTutorial_Modiule1_Image8

    Nella visualizzazione Codice del nuovo file appena creato (content_note.xml), sostituisci il codice generato incollando il codice in basso:

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

    Infine, crea la classe Kotlin: fai clic con il tasto destro del mouse su java/com.example/androidgettingstarted e seleziona New (Nuovo) -> Kotlin file/class (File/classe Kotlin). Digita NoteRecyclerViewAdapter come nome.

    AndroidAppTutorial_Modiule1_Image9

    Incolla il codice in basso nel nuovo file appena creato (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)
        }
    }

    Che cosa abbiamo aggiunto?
    Il codice sopra è composto da

    • un file xml di layout che descrive il layout del componente in una cella che rappresenta una nota. Visualizza l'immagine, il titolo e la descrizione della nota.
    • una classe Kotlin di supporto. Riceve un oggetto dati Note al momento della creazione e assegna singoli valori alle visualizzazioni corrispondenti (immagine, titolo e descrizione)
  • Aggiornamento dell'attività principale

    Ora che abbiamo le classi di dati (UserData e Note) e la visualizzazione delle singole note (NoteRecyclerViewAdapter), creiamo l'elenco di note nell'attività principale.

    Dall'elenco di file a sinistra di Android Studio, apri res/layout/content_main.xml e sostituisci il codice con questo contenuto:

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

    Dall'elenco di file a sinistra di Android Studio, apri java/com.example/androidgettingstarted/MainActivity.kt e sostituisci il codice con questo contenuto:

    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"
        }
    }

    Che cosa abbiamo aggiunto?

    • il layout principale è una RecyclerView che gestisce l'elenco delle singole celle che abbiamo creato in precedenza
    • la classe di attività principale osserva le modifiche nell'elenco di note e genera un NoteRecyclerViewAdapter per creare singole celle.
  • Verifica delle dipendenze delle build

    In Gradle Scripts (Script Gradle), apri build.gradle (Module:app) e verifica che le dipendenze generate siano corrette. È necessario controllare le 'versioni delle librerie'.

    ```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'
    }
  • Creazione e test

    Ora crea e avvia l'applicazione nel simulatore. Fai clic sull'icona Run (Esegui) ▶️ nella barra degli strumenti o digita ^ R.

    AndroidAppTutorial_Modiule1_Image10

    Dopo qualche istante, l'applicazione parte nel simulatore Android con una schermata inizialmente vuota.

    AndroidAppTutorial_Modiule1_Image11

    In questa fase, non ci sono dati di cui eseguire il rendering al runtime. Elimineremo l'icona della posta in una fase successiva.

Conclusione

Hai creato correttamente un'applicazione Android. Ora sei pronto per iniziare a creare con Amplify.

Questo modulo è stato utile?

Grazie
Facci sapere cosa ti è piaciuto.
Chiudi
Spiacenti di non esserti stati d'aiuto
C'è qualcosa di obsoleto, ambiguo o approssimativo? Aiutaci a migliorare questo tutorial con il tuo feedback.
Chiudi

Inizializzazione di Amplify