11.19: Un “blog” personale per Android sfruttando Firebase: conclusioni

Condividi su:

Abbiamo praticamente tutto, non ci resta che salvare l’immagine del profilo dell’utente registrato nel cloud e rifinire qualche dettaglio, dopodiché quest’app potrà definirsi completa.





La rifinitura dei dettagli la lascio a voi, al momento occupiamoci di completare la parte relativa alla creazione dell’account. L’activity completa e modificata a tale scopo avrà il seguente codice:

public class CreateAccountActivity extends AppCompatActivity {
    private ImageButton avatarPic;
    private EditText firstNameET;
    private EditText lastNameET;
    private EditText emailET;
    private EditText passwordET;
    private Button createActBT;
    private FirebaseDatabase DB;
    private DatabaseReference DBRef;
    private FirebaseAuth mAuth;
    private StorageReference mFBStorage;
    private final static int GALLERY_CODE = 1;
    private Uri resultUri = null;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_create_account);

        /*
         * Recupero di istanze e riferimenti necessari da Firebase
         */
        DB = FirebaseDatabase.getInstance();
        DBRef = DB.getReference().child("Users");
        mAuth = FirebaseAuth.getInstance();
        mFBStorage = FirebaseStorage.getInstance().getReference().child("Blog_Profile_Pics");

        /*
         * Istanziazione di tutti i widget presenti all'interno del layout
         */
        firstNameET = (EditText) findViewById(R.id.firstNameAct);
        lastNameET = (EditText) findViewById(R.id.lastNameAct);
        emailET = (EditText) findViewById(R.id.emailAct);
        passwordET = (EditText) findViewById(R.id.passwordAct);
        createActBT = (Button) findViewById(R.id.createAccountAct);
        avatarPic = (ImageButton) findViewById(R.id.avatarAct);

        avatarPic.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //Cliccando sull'ImageButton richiamiamo il metodo per l'aggiunta di un avatar
                addAvatar();
            }
        });

        //Setting del listener sul pulsante  per avviare la procedura di creazione account
        createActBT.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                createnewAct();
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        /*
         * Metodo invocato quando l'utente ha selezionato l'immagine profilo dalla galleria.
         * Qui dobbiamo prelevare l'immagine e utilizzarla
         */
        super.onActivityResult(requestCode, resultCode, data);
        //Controlliamo che la richiesta sia andata a buon fine
        if (requestCode == GALLERY_CODE && resultCode == RESULT_OK){
            //Preleviamo l'URI dell'immagine dai dati ricevuti
            Uri mImageUri = data.getData();
            //Crop dell'immagine attraverso l'apposita libreria
            CropImage.activity(mImageUri)
                    .setAspectRatio(1, 1)
                    .setGuidelines(CropImageView.Guidelines.ON)
                    .start(this);
        }

        //Recupero dell'immagine "croppata"
        if (requestCode == CropImage.CROP_IMAGE_ACTIVITY_REQUEST_CODE) {
            CropImage.ActivityResult result = CropImage.getActivityResult(data);
            if (resultCode == RESULT_OK) {
                resultUri = result.getUri();
                avatarPic.setImageURI(resultUri);
            } else if (resultCode == CropImage.CROP_IMAGE_ACTIVITY_RESULT_ERROR_CODE) {
                Exception error = result.getError();
            }
        }
    }

    private void addAvatar() {
        /*
         * Confezioniamo l'intent per poter aprire la galleria e permettere la selezione di un immagine
         */
        Intent galleryIntent = new Intent();
        galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
        galleryIntent.setType("image/*");
        //Predisponiamo l'activity a ricevere dei dati da quella chiamata
        startActivityForResult(galleryIntent, GALLERY_CODE);
    }

    private void createnewAct() {
        /*
         * Recupero delle informazioni inserite all'interno delle EditText
         */
        final String name = firstNameET.getText().toString().trim();
        final String lName = lastNameET.getText().toString().trim();
        String eMail = emailET.getText().toString().trim();
        String pwd = passwordET.getText().toString().trim();

        //Controllo che tutti i campi siano stati compilati
        if (!TextUtils.isEmpty(name) && !TextUtils.isEmpty(lName)
                && !TextUtils.isEmpty(eMail) && !TextUtils.isEmpty(pwd)){
            //Creazione dell'account tramite apposito metodo, con listener sull'esito
            mAuth.createUserWithEmailAndPassword(eMail, pwd).addOnSuccessListener(new OnSuccessListener<AuthResult>() {
                @Override
                public void onSuccess(AuthResult authResult) {
                    if (authResult != null){
                        /*
                         * Se la creazione dell'account ha avuto successo, si memorizzano tutti i
                         * dati dell'utente all'interno del database e si direziona l'utente
                         * verso l'activity con la lista di post
                         */
                        //Generiamo il path dell'immagine profilo da salvare
                        StorageReference imagePath = mFBStorage.child(resultUri.getLastPathSegment());
                        //Salviamo l'immagine e monitoriamo l'esito dell'operazione
                        imagePath.putFile(resultUri).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() {
                            @Override
                            public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) {

                                String userID = mAuth.getCurrentUser().getUid();
                                DatabaseReference currentUserDBRef = DBRef.child(userID);
                                currentUserDBRef.child("firstName").setValue(name);
                                currentUserDBRef.child("lastName").setValue(lName);
                                currentUserDBRef.child("avatar").setValue(resultUri.toString());
                                Intent intent = new Intent(CreateAccountActivity.this, PostListActivity.class);
                                //Aggiungiamo un flag all'intent che non fa altro che porre l'activity
                                //destinataria nuovamente in cima allo stack, se già avviata, piuttosto che
                                //avviarne un'altra istanza, terminando contestualmente tutte le altre activity
                                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                                startActivity(intent);

                            }
                        });
                    }
                }
            });
        }else{
            //ToDo: codice per gestire il mancato inserimento di tutti i dati
        }
    }
}

A quello che già avevamo abbiamo aggiunto un field dedicato per un’oggetto StorageReference, che, come abbiamo già visto, è quello che contiene il riferimento allo storage del cloud di Firebase. Per ottenere questo riferimento abbiamo quindi recuperato l’istanza, il riferimento allo spazio di archiviazione e quello ad un suo elemento figlio, che sarà la cartella in cui memorizzeremo le immagini. All’interno dello spazio di storage avremo quindi due cartelle, una dedicata alle immagini dei post, l’altra alle immagini profilo.

Fatto ciò abbiamo modificato il metodo di creazione account. Piuttosto che salvare direttamente tutti i dati nel database, nel caso in cui la creazione dell’account abbia successo, ci premuriamo per prima cosa di caricare l’immagine nel cloud. Per farlo generiamo il path dell’immagine, aggiungendo un elemento figlio (che avrà l’ultima parte dell’URI del file) al path generale creato prima. Otterremo così il riferimento alla specifica immagine.
Dopo di ciò possiamo salvare l’immagine all’interno di questo riferimento richiamando il metodo “putFile()” e passandovi come parametro l’URI dell’immagine croppata. Aggiungiamo un listener in cascata per monitorare l’esito di questa operazione. Se avrà successo, salveremo tutti i dati all’interno del database. Il codice di questa parte è identico a quello utilizzato precedentemente, tranne che per il nodo relativo all’avatar, in cui adesso salviamo la stringa dell’URI dell’immagine.

Se vi è sfuggito qualcosa, confrontate questa versione del file con quella precedente, così da avere a vista le modifche effettuate.


Conclusioni

L’app ora è completa e funzionante, mancano svariati dettagli, se spulciate all’interno del codice noterete infatti una serie di commenti “ToDo”. Se volete continuare ad esercitarvi, sta a voi completare l’app, ad esempio gestendo tutte le situazioni in cui l’esito delle varie operazioni effettuate non va a buon fine.
Potete aggiungere un’activity di dettaglio per i post, infatti se ricordate abbiamo collegato anche un listener alle view della RecyclerView.
Un altro spunto potrebbe essere quello di gestire la situazione in cui l’utente non aggiunge un avatar nel momento in cui si registra. La modalità più semplice potrebbe essere quella di caricare un’immagine apposita ed effettuare un controllo sull’ImageButton, così da salvare il riferimento all’immagine profilo di default all’interno del database. Altrimenti potete ricavare l’URI dell’immagine risorsa settata sull’ImageView e caricare quella nel caso l’utente non ne avesse scelto una propria; questa modalità però presenta un’inefficienza, verrà caricata sempre la stessa immagine, erodendo spazio inutilmente.
Anche i layout non sono il massimo, ad esempio immagini troppo grandi vengono gestite male, quindi potete giocare un po’ con le proprietà per sistemare il tutto.

Abbiamo finito con questo lungo capitolo dedicato a Firebase. Ovviamente Firebase offre anche molto altro e sarebbe necessario un blog apposito solo per lui. Abbiamo imparato però ad utilizzarlo, quindi non dovrebbe essere difficile, col supporto della documentazione, implementare anche le altre feature.

Dal prossimo articolo passeremo ad altro e nello specifico ci dedicheremo a Google Maps e quindi alla localizzazione.

Condividi su:

label, , ,

About the author