Démarrer avec AWS

Créer une application Android

Créer une application Android simple avec AWS Amplify

Module 1 : Créer et déployer une application Android

Dans ce module, vous allez créer une application Android et la déployer dans le cloud en utilisant le service d'hébergement Web AWS Amplify.

Introduction

AWS Amplify propose un flux de travail basé sur Git pour la création, la gestion, l'intégration et le déploiement de backends sans serveur dédiés aux applications Web et mobiles. L'interface en ligne de commande Amplify (Amplify CLI) simplifie la provision et la gestion des services backend, notamment l'authentification d'utilisateurs et les API REST ou GraphQL pour vos applications. Les bibliothèques Amplify vous permettent d'intégrer facilement ces services en ajoutant seulement quelques lignes de code à vos applications.

Nous allons commencer ce module par la création d'une nouvelle application Android permettant d'enregistrer des notes dans un carnet de voyage. Une note se compose d'un titre, d'une description et d'une image. Nous améliorerons cette application au fil des modules.

Ce que vous apprendrez

  • Créer une application Android
  • Mettre à jour la vue principale pour afficher une liste d'articles
  • Créer et tester votre application

Concepts clés

Kotlin Kotlin servira de langage de programmation pour ce tutoriel. Celui-ci permet de réduire en grande partie le code réutilisable et assure en outre la cohérence des types.

Jetpack – Ce tutoriel utilise Android Jetpack, une collection de bibliothèques Android proposant des bonnes pratiques et permettant la rétrocompatibilité de vos applications Android.

 Durée

10 minutes

 Services utilisés

Implémentation

  • Créer un projet Android

    Démarrez Android Studio et choisissez Start a new Android Studio project (Démarrer un nouveau projet Android Studio) depuis l'écran de démarrage :

    AndroidAppTutorial_Modiule1_Image1

    Sous Phone and Tablet (Téléphone et tablette), sélectionnez Basic Activity (Activité de base) et cliquez sur Next (Suivant) :

    AndroidAppTutorial_Modiule1_Image2

    Renseignez le nom de votre projet, par exemple Android Getting Started. Vérifiez que le langage est bien défini sur Kotlin et que le SDK minimal est API 26: Android 8.0 (oreo). Cliquez ensuite sur Finish (Terminer) :

    AndroidAppTutorial_Modiule1_Image3

    Maintenant que le squelette de projet existe, nous devons suivre ces quatre étapes afin de pouvoir exécuter notre application de base :

    1. Supprimer les classes indésirables.
    2. Créer les classes de nos structures de données.
    3. Créer une vue pour afficher les notes individuelles dans la liste.
    4. Modifier l'activité principale pour afficher une liste de notes.
  • Supprimer les fichiers inutiles et ajouter des plug-ins

    Supprimez les quatre fichiers « fragment » sous res/layout et java/com.example.androidgettingstartedfiles (sélectionnez les quatre fichiers puis effectuez un clic droit et choisissez Delete (Supprimer) dans le menu contextuel) :

    AndroidAppTutorial_Modiule1_Image4

    Sous Gradle Scripts, ouvrez build.gradle (Module:app) et ajoutez le plug-in Kotlin Extension.

    plugins {
        id 'com.android.application'
        id 'kotlin-android'
        id 'kotlin-android-extensions' //  <== add this line
    }
  • Créer une nouvelle classe de données UserData

    La classe UserData contient l'état d'utilisateur : un indicateur isSignedIn et une liste de valeurs Note.

    Pour créer une nouvelle classe, cliquez droit sur java/com.example/androidgettingstarted et sélectionnez New -> Kotlin file/class (Nouveau -> Fichier/classe Kotlin). Saisissez le nom UserData.

    AndroidAppTutorial_Modiule1_Image5

    Collez le code ci-dessous dans le fichier fraîchement créé (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
    
        }
    }

    Que venons-nous d'ajouter ?

    • La classe UserData contiendra les données d'utilisateurs, à savoir un indicateur isSignedIn permettant de suivre l'état d'authentification, ainsi qu'une liste d'objets Note.
    • Ces deux propriétés sont mises en œuvre conformément au framework de publication/souscription LiveData. Cela permet à l'interface graphique (GUI) de souscrire les changements et de réagir en fonction. Pour plus d'informations sur LiveData, consultez ce document ou reportez-vous à ce bref tutoriel vidéo. Afin de respecter les bonnes pratiques, la propriété MutableLiveData doit rester privée et seule la propriété en lecture seule LiveData doit être exposée. Du code réutilisable supplémentaire est requis lorsque les données à publier sont une liste servant à informer les observateurs que des composants individuels de la liste ont été modifiés.
    • Nous avons également ajouté la classe de données Note, qui contiendra les données des notes individuelles. Deux propriétés distinctes sont utilisées pour ImageName et Image. Nous étudierons la propriété Image dans un prochain module.
    • Nous avons implémenté le singleton pour l'objet UserData, afin de pouvoir s'y référer partout dans l'application.
  • Ajouter une interface utilisateur graphique (GUI) pour les cellules individuelles de la liste

    La vue de cellules individuelles dans une liste de défilement s'appelle RecyclerView : la vue peut être recyclée lorsque l'utilisateur fait défiler l'écran vers le haut ou le bas et qu'elle n'est plus visible.

    Tout comme pour une vue classique, nous créons des fichiers de disposition XML et une classe Kotlin. Voici à quoi ressemble une cellule individuelle :

    AndroidAppTutorial_Modiule1_Image6

    Pour créer le fichier de disposition, cliquez droit sur res/layout et choisissez New -> Layout Resource File Nouveau -> Fichier de ressource de disposition. Saisissez le nom content_note et ne touchez pas aux autres valeurs, que nous éditerons directement dans le fichier XML.

    AndroidAppTutorial_Modiule1_Image7

    Ouvrez la vue Code pour le fichier nouvellement créé.

    AndroidAppTutorial_Modiule1_Image8

    Dans la vue Code du nouveau fichier (content_note.xml), remplacez le code généré en collant le code fourni ci-après :

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

    Enfin, créez la classe Kotlin : cliquez droit sur java/com.example/androidgettingstarted et sélectionnez New -> Kotlin file/class (Nouveau -> Fichier/classe Kotlin). Saisissez le nom NoteRecyclerViewAdapter.

    AndroidAppTutorial_Modiule1_Image9

    Collez le code ci-dessous dans le fichier fraîchement créé (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)
        }
    }

    Que venons-nous d'ajouter ?
    Le code ci-dessous se compose :

    • D'un fichier XML servant à décrire la disposition du composant sur une cellule représentant une Note. Il affiche l'image, le titre de la note et sa description.
    • Une classe Kotlin de prise en charge. Au moment de la création, celle-ci reçoit un objet de données Note et attribue des valeurs individuelles aux vues correspondantes (image, titre et description).
  • Mettre à jour l'activité principale

    Maintenant que nous avons créé les classes de données (UserData et Note) et la vue de notes individuelles (NoteRecyclerViewAdapter), nous allons nous occuper de la liste des notes sur l'activité principale.

    Ouvrez res/layout/content_main.xml à partir de la liste de fichiers à gauche dans Android Studio et remplacez le code par :

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

    Ouvrez ensuite java/com.example/androidgettingstarted/MainActivity.kt à partir de la même liste, puis remplacez le code par :

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

    Que venons-nous d'ajouter ?

    • la disposition principale est une vue RecyclerView qui gère la liste de cellules individuelles précédemment créée ;
    • la classe d'activité principale observe les changements sur la liste de Notes et crée une vue NoteRecyclerViewAdapter permettant de créer des cellules individuelles.
  • Vérifier les dépendances de build

    Sous Gradle Scripts, ouvrez build.gradle (Modetule:app) et vérifiez que les dépendances générées sont correctes. Les versions des bibliothèques doivent être contrôlées.

    ```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'
    }
  • Générer et tester

    Générez et lancez l'application dans le simulateur. Cliquez sur l'icône Run (Exécuter) ▶️ dans la barre d'outils, ou tapez ^ R.

    AndroidAppTutorial_Modiule1_Image10

    Après quelques instants, l'application démarre dans le simulateur Android, avec un écran initialement vide.

    AndroidAppTutorial_Modiule1_Image11

    En effet, à cette étape, aucune donnée ne peut encore être rendue en exécution. Nous supprimerons l'icône de courrier lors d'une prochaine étape.

Conclusion

Vous avez créé une application Android. Vous pouvez maintenant commencer à la développer avec Amplify !

Ce module vous a-t-il été utile ?

Merci
Merci de nous indiquer ce que vous avez aimé.
Fermer
Nous sommes désolés de vous décevoir.
Quelque chose est-il obsolète, déroutant ou inexact ? Aidez-nous à améliorer ce didacticiel en fournissant des commentaires.
Fermer

Initialiser Amplify