11.14: Un “blog” personale per Android sfruttando Firebase: AddPostActivity pt. 2 (lo storage in Firebase)

Condividi su:

Continuiamo l’implementazione dell’activity dedicata all’aggiunta di un nuovo post all’interno del nostro blog personale. Nello scorso articolo abbiamo visto come sfruttare gli intent impliciti per recuperare un’immagine dalla galleria demandando l’operazione all’app galleria di default, qualsiasi essa sia. Ora ci occuperemo di salvare quest’immagine nel cloud.





All’interno della piattaforma abbiamo il nostro database già quasi del tutto configurato. Sebbene questo permetta di salvare svariati tipi di oggetti, definiti in base alle nostre esigenze, non possiamo sfruttarlo per salvare anche delle immagini. Fortunatamente Firebase offre lo strumento adatto, cioè uno spazio di storage. Le immagini che inseriranno gli utenti all’interno dei loro post andranno qui, mentre nel database salveremo solo un riferimento all’immagine.

Aprendo la console di Firebase, sulla sinistra avrete proprio “Storage”, noterete che altro non è che uno spazio di archiviazione nel cloud, come può essere Google Drive o Dropbox. Come per il database abbiamo due sezioni, una dedicata ai file caricati, l’altra alle regole di scrittura e lettura. Al momento qui non dobbiamo fare nulla, mentre è necessario adeguare il nostro progetto su Android Studio.

Come per l’autenticazione e l’accesso al database, il progetto oltre ad essere collegato e registrato su Firebase, deve anche avere le opportune dipendenze. Avrete ormai notato che l’integrazione di questa piattaforma è modulare, cioè all’interno delle nostre app inseriamo solo le librerie strettamente necessarie alla specifica funzione di Firebase di cui necessitiamo.

Per soddisfare tutte le dipendenze necessarie allo sfruttamento dello storage su Firebase l’operazione è la solita: apriamo l’assistente (“Tools”->”Firebase”), cerchiamo “Storage” e attraverso il punto 2 gli permettiamo di importare automaticamente le librerie necessarie.

Nel momento in cui il nostro progetto può gestire lo storage su Firebase possiamo iniziare a scrivere il codice necessario.

Per prima cosa creiamo un nuovo field all’interno di AddPostActivity, questo conterrà il riferimento alla posizione di storage su Firebase:

private StorageReference mStorage;

Per ottenere il riferimento agiamo come con il database, recuperiamo l’istanza e successivamente il riferimento, tutto all’interno dell'”onCreate()” dell’activity:

mStorage = FirebaseStorage.getInstance().getReference();

All’interno della classe abbiamo il metodo “startPosting()”, richiamato nel momento in cui si verifica l’evento click sul pulsante “SUBMIT”. Negli scorsi articoli, al fine di provarne il funzionamento, abbiamo inserito del codice di prova, che ora non è più necessario, poiché abbiamo tutto ciò che ci serve per salvare un post reale, quindi procediamo:

    private void startPosting() {
        //Recuperiamo il titolo e la descrizione dalle EditText
        final String titleVal = mTitlePost.getText().toString().trim();
        final String descVal = mDescPost.getText().toString().trim();

        //Prima di proseguire controlliamo di avere titolo, post e immagine
        if (!TextUtils.isEmpty(titleVal) && !TextUtils.isEmpty(descVal) && mImageUri != null){
//            //Creiamo un oggetto blog fittizio per testare il funzionamento del codice
//            Blog post = new Blog("Title", "description", "imageurl", "timestamp", "userid");
//            //Memorizziamo l'oggetto Blo nel database e monitoriamo l'esito dell'operazione
//            mPostRef.setValue(post).addOnSuccessListener(new OnSuccessListener<Void>() {
//                @Override
//                public void onSuccess(Void aVoid) {
//                    Toast.makeText(AddPostActivity.this, getResources().getString(R.string.item_added), Toast.LENGTH_LONG).show();
//                }
//            });

            /*
             * Generiamo il path dove andranno salvate le immagini allegate al post.
             * Questo farà riferimento alla posizione "padre" e all'interno conterrà una cartella
             * chiamata "Blog images" con i file memorizzati in nodi figli referenziati grazie al
             * path dell'URI
             */
            StorageReference filePath = mStorage.child("Blog_images").child(mImageUri.getLastPathSegment());
            //Nel path così costruito salviamo il file e aggiungiamo un listener per monitorare l'operazione
            filePath.putFile(mImageUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                /*
                 * Se l'upload del file ha successo, provvediamo a salvare tutte le informazioni
                 * del post all'interno del database real-time
                 */
                @Override
                public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {
                    //Recuperiamo l'url di upload dell'immagine
                    Uri downloadUrl = taskSnapshot.getDownloadUrl();
                    //Creiamo un riferimento ad un nodo figlio del database autogenerato
                    DatabaseReference newPost = mPostRef.push();

                    //All'interno di un'HashMap salviamo tutti i dati del post
                    Map<String, String> dataToSave = new HashMap<>();
                    dataToSave.put("title", titleVal);
                    dataToSave.put("description", descVal);
                    dataToSave.put("image", downloadUrl.toString());
                    dataToSave.put("timeStamp", String.valueOf(System.currentTimeMillis()));
                    dataToSave.put("userID", mUser.getUid());

                    //Salviamo l'HashMap all'interno del database alla posizione referenziata per il nodo figlio
                    newPost.setValue(dataToSave);
                    //Il post è stato salvato, possiamo tornare alla lista post
                    startActivity(new Intent(AddPostActivity.this, PostListActivity.class));
                    finish();
                }
            });
        }
    }

Il post va salvato solo se l’utente ha inserito l’immagine, il titolo e la descrizione del post, quindi adeguiamo l'”if” per comprendere anche il controllo sull’immagine.

Abbiamo il riferimento alla posizione di storage su Firebase, ma noi vogliamo tenere le immagini caricate organizzate. Per far ciò generiamo un riferimento specifico al file caricato con due nodi figli (a loro volta l’uno figlio dell’altro), uno che farà riferimento ad una cartella chiamata “Blog_images” e l’altro al file. Per definire questo sfruttiamo la parte finale del path dell’URI con l’apposito metodo. In questo modo in “filePath” avremo qualcosa del tipo “urlStorageFirebase/Blog_images/image:nomeImmagine”.

Avendo il path possiamo adesso caricarvi l’immagine col metodo “putFile()”, passandovi l’URI del file come parametro. A questa chiamata colleghiamo un listener per monitorare l’esito dell’operazione. Se l’operazione avrà successo, salviamo anche tutti i dati del post all’interno del database.

Per prima cosa recuperiamo l’url del file caricato, poiché è uno dei dati da salvare, questa la troviamo all’interno dell’oggetto passato come parametro al listener e può essere prelevata tramite l’apposito getter: “getDownloadUrl()”.
Vogliamo tenere organizzati anche i post del blog, quindi non li salveremo all’interno del nodo principale (che a sua volta è un nodo del database, avendo usato il metodo “child()” per recuperare il riferimento), ma genereremo automaticamente un nuovo nodo e ne creeremo il riferimento col metodo “push()“. Adesso in “newPost” abbiamo il riferimento al nodo figlio del nodo “Blog” generato appositamente per quel post.

Non resta da fare altro che salvare l’oggetto che conterrà tutti i dati del post, piuttosto che sfruttare le classe “Blog”, lo creiamo attraverso un’HashMap, in questo modo ci assicuriamo che ogni singolo dato sarà sicuramente memorizzato in un nodo a se stante. Per la chiave di ogni dato utilizziamo la stessa stringa usata per i field della classe “Blog”, altrimenti avremo problemi nel momento in cui dovremo recuperare i post dal database. Creata la mappa la salviamo nella posizione del database referenziata con l’apposito metodo e ritorniamo all’activity di visualizzazione di tutti i post.

Conclusioni

Se provate l’app, questa sarà perfettamente funzionante per tutte le parti che abbiamo implementato. Prima di farlo assicuratevi di cancellare l’oggetto salvato precedentemente come test all’interno del database, potete farlo tranquillamente all’interno della console. Inserendo un po’ di post, sarà questa la situazione all’interno del database:

Database

Come vedete all’interno del dabase abbiamo il nodo Blog, che una volta espanso mostra i nodi dei singoli post, contrassegnati da un riferimento specifico generato dal metodo “push()”. Espandendo questo ci ritroviamo con vari nodi ognuno dei quali contiene uno specifico dato del post salvato.

All’interno della console dello storage della piattaforma invece abbiamo:

Storage

In questo caso, come potete vedere dall’intestazione, è stata aperta la cartella “Blog_images” all’interno della quale ci sono le immagini dei vari post salvati.



Possiamo fermarci qui, con questa activity abbiamo praticamente finito, quindi nel prossimo articolo faremo in modo da popolare PostListActivity, anche perché ora abbiamo anche vari post salvati e conosciamo la loro struttura.

Condividi su:

label, , ,

About the author