oriol mèlich pons aplicació android appxi treball de fi de...

59
Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE GRAU dirigit per David Girbau Sala Grau en Enginyeria de serveis i sistemes de telecomunicacions Tarragona 2018

Upload: others

Post on 23-Jun-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

Oriol Mèlich Pons

Aplicació Android Appxi

TREBALL DE FI DE GRAU

dirigit per David Girbau Sala

Grau en Enginyeria de serveis i sistemes de telecomunicacions

Tarragona

2018

Page 2: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

1

Índex

1. Introducció ................................................................................................................................ 2

1.1. App Taxi .............................................................................................................................. 2

1.2. Competències ..................................................................................................................... 2

1.3. Objectius ............................................................................................................................ 3

1.4. Organització memòria ........................................................................................................ 3

2. Disseny de l’APP ........................................................................................................................ 4

2.1. Esquema de l’aplicació ....................................................................................................... 4

2.2. Desenvolupament aplicació ............................................................................................... 5

2.3. Configuració ....................................................................................................................... 6

2.3.1. Manifest ...................................................................................................................... 6

2.3.2. Gradle .......................................................................................................................... 8

2.4. Classes .............................................................................................................................. 10

2.4.1. Conceptes bàsics de l’entorn Android....................................................................... 11

2.4.2. Java class ................................................................................................................... 12

2.4.3. Activitys ..................................................................................................................... 14

2.5. Permisos ........................................................................................................................... 38

2.6. Diagrames de relacions .................................................................................................... 39

2.7. Diagrama de seqüència .................................................................................................... 41

3. BBDD........................................................................................................................................ 42

3.1. Organització ..................................................................................................................... 42

3.1.1. Pla Firebas ................................................................................................................. 42

3.1.2. Utilitats que ens proporciona Firebase ..................................................................... 44

3.1.3. Sincronització firebase-aplicació ............................................................................... 49

3.2. Comunicació ..................................................................................................................... 50

4. Resultats .................................................................................................................................. 52

5. Conclusions i línies futures ...................................................................................................... 56

5.1. Conclusions ...................................................................................................................... 56

5.1.1 Conclusió personal ..................................................................................................... 56

5.1.2 Retrospectiva dels objectius plantejats i assolits. ...................................................... 57

5.2. Línies futures .................................................................................................................... 57

6. Referències .............................................................................................................................. 58

Page 3: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

2

1. Introducció

1.1. App Taxi

Tot comença amb la necessitat persónal en un viatge on havíem d’utilitzar el taxi com a mitjà de

transport molt recurrent, i comunicar-nos parlant no era una opció. En aquest punt vaig veure

un buit molt gran en un sistema que se l’acusa d’estar molt obsolet. El mon del taxi funciona

d’una manera molt arcaica i cal adaptar-lo a les noves tecnologies.

Mirant l’oferta que tenim al mercat de les aplicacions relacionades amb el taxi, veiem una gran

varietat de programes, la més important d’elles és Mytaxi[1], però la majoria es queden a la

superfície, es limiten a fer una trucada a la centraleta de taxis, t’ubiquen i t’envien un vehicle.

El que fan és simplement estalviar-te una trucada telefònica.

En aquesta aplicació, pretenc anar més enllà.

Vull dissenyar una aplicació que beneficiï tant als usuaris dels taxi, com als propis taxistes. Als

clients, donant-los facilitats per trobar el seu mitja de transport de manera fàcil i eficaç, amb

una comunicació directe en tot moment amb el taxi sol·licitat i un càlcul de taxes, en funció del

temps i la distancia a recórrer; i als taxistes facilitant-los una eina que els faci transmetre

confiança als seus clients, i al mateix temps els aconsegueixi el màxim número de carreres.

1.2. Competències

Per dur a terme aquest projecte calen nocions de com estructurar els objectes i les classes Java

i tenir coneixements bàsics d’extensible markup lenguage (XML), per a la nostra interfície gràfica

i poder-ho relacionar amb la part Java.

També necessito saber com funciona una base de dades no relacional, ja que utilitzaré

Firebase[2], i d’aquesta aplicació que ens ofereix Google, a part de la base de dades a temps

real, que és part del nucli de l’ aplicació, també utilitzaré Firebase Authenticator. Per tant caldrà

saber moure’s en l’entorn de les interfícies de programació d’aplicacions (APIs) i utilitzar els kits

de desenvolupament de software (SDKs).

Finalment hauré de conèixer profundament com funciona i com està estructurat l’Android

Studio[3], ja que els entorns de desenvolupament integrat (IDE) ajuden i faciliten molt les coses

a l’hora de desenvolupar i simular, i també hauré de saber com gestionar la part tant del projecte

en si, com del manifest i els gradles.

Page 4: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

3

1.3. Objectius

Dissenyar i crear una aplicació d’Android funcional, amb una comunicació directa i a temps real

amb una BBDD, que permeti un contacte entre el taxista i el client, i que serveixi per acordar i

gestionar el servei.

Per aconseguir aquest objectiu, hauré d’aprofundir amb els coneixements que tinc, tant de Java,

XML, Android Studio; treballar a nivell de APIs i amb una de les meves eines principals que serà

Firebase, que és la base de dades gratuïta (amb la seva versió de prova utilitzada per

desenvolupar programari) ofert per Google.

Tots aquets sistemes són de codi obert i programari lliure, per tant el cost de l’ aplicació no és

més que el temps invertit.

1.4. Organització memòria

L’Organització d’aquesta memòria pretén mostrar primer el producte, per donar una idea clara

d’on vull arribar, i quines etapes i quins mètodes he utilitzat per aconseguir-ho.

Un cop clara l’aplicació, indagaré de dalt cap a baix tant amb els passos que he seguit com amb

el contingut tècnic de la pròpia aplicació, codi desglossat, integració de APIs, etc.

Més endavant explicaré com integrar la base de dades de Firebase al meu projecte, com

l’estructuro a nivell de referències i com es realitza la comunicació a temps real.

Finalment exposaré les conclusions i línies futures.

Page 5: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

4

2. Disseny de l’APP

2.1. Esquema de l’aplicació A la figura 0 es mostra un primer contacte amb la navegació per a la nostra aplicació.

Com es pot veure, a grans trets, l’aplicació consta d’una pantalla inicial per seleccionar quin tipus

d’usuari ets (client o taxista). Un cop seleccionat el tipus d’entrada, hi haurà una pantalla de

login o registre i, un cop dins, es veurà, si s’hi ha entrat com a client, un mapa que indicarà la

nostra posició i la posició relativa dels taxis; a la part inferior de la pantalla hi haurà dos botóns,

un per iniciar la geo-localització i l’altre per sol·licitar el taxista seleccionat.

Per alta banda, si s’entra com a taxista, tindrem un botó per iniciar la geo-localització i l’altre per

acceptar o rebutjar el taxista.

Figura0: Sumari de l’aplicació.

Page 6: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

5

2.2. Desenvolupament aplicació

En aquest apartat s’explica l’organització seguida per desenvolupar l’aplicació.

Aquesta idea va sorgir, com s’ha dit en el primer apartat, d’una necessitat. La vam desenvolupar

com a projecte conceptual en una assignatura de quart (Projectes de Telecomunicacions) i en

aquest TFG és on s’ha implementat. Allò em va donar la idea de treballar en petits objectius, que

és com he acabat funcionant.

El primer pas ha estat assignar uns objectius, que tal com veurem al final, la majoria s’han

acomplert. Posteriorment s’han definit una sèrie de tasques per implementar-los. Cada cop que

una tasca donava un problema inesperat, s’afegien noves sub-tasques per acabar la principal.

Per exemple, quan es pensava que agafar la posició al mapa i pintar-la al Google maps seria

simplement crear una activity “maps” i cridar a myLocation, es van haver de fer diferents sub-

tasques de com integrar el maps i el gps per separat, i també com sol·licitar els permisos que

necessitava.

Des d’un principi es tenia clar que la primera versió de l’aplicació no seria la que es mostra a

l’usuari final; per tant es va comptar en fer la versió de proves que ajudaria a testejar l’aplicació

i, després, en desfer tot el sobrant perquè l’usuari tingués la seva pròpia versió.

Finalment es va plantejar una manera de fer les proves de la meva aplicació amb usuaris reals

però amb el codi una mica modificat, de manera que els usuaris només poguessin ser taxis i jo

pogués interactuar amb ells.

Page 7: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

6

2.3. Configuració

Abans de començar a crear classes i activitys, s’ha de posar a punt la configuració del manifest i

el gradle, on es donaran unes instruccions a l’aplicació, i servirà per sincronitzar les APIs.

2.3.1. Manifest

El manifest és la configuració principal de l’aplicació, aquí es configura quina activity serà la

principal a l’hora d’executar-se la app, es declaren les diferents activitys que es tindran, es dona

nom a la app a la barra de navegació, etc.

Al manifest hi ha un conjunt d’informació molt rellevant per a l’aplicació així com els permisos

indispensables que es necessiten del dispositiu per executar-la. En aquest cas particular,

necessita accés a internet i a la posició del dispositiu.

La posició es pot determinar de vàries maneres. Per tant no només necessito accedir al GPS,

sinó que també cal accedir al paquet principal d’opcions que ens ofereixen posicionament al

mapa, WIFIs, etc. També serveix per sincronitzar APIs com la de Google maps.

Google t’ofereix una sola API key gratuïta[4] per desenvolupar la teva aplicació, aquesta s’ha

d’introduir en el manifest com a meta-data.

El manifest també determina la ruta de workspace utilitzada i el Package que contindrà les

classes.

En el codi 1 podem veure la configuració del nostre manifest on cal ressaltar la importància dels

<uses-permission> que ens permetran declarar els permisos necessaris de l’aplicació i

<activity> que ens diran les activitys que figuren en aquesta.

<?xml version=”1.0” encoding=”utf-8”?>

<manifest xmlns:android=”http://schemas.android.com/apk/res/android”

6efiní6=”urv.apptfg”>

<!—This is required for Picasso to work. →

<uses-permission android:name=”android.permission.INTERNET” />

<!—Used to adjust the work load depending on the type of network

the 6efiní is using. →

<uses-permission

android:name=”android.permission.ACCESS_NETWORK_STATE” />

<!—Used to load images from the gallery content provider. →

<uses-permission

android:name=”android.permission.READ_EXTERNAL_STORAGE” />

<uses-permission

android:name=”android.permission.ACCESS_COARSE_LOCATION” />

<uses-permission

android:name=”android.permission.ACCESS_FINE_LOCATION” />

<uses-feature android:name=”android.hardware.location.gps” />

Page 8: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

7

<application

android:allowBackup=”true”

android:icon=”@mipmap/ic_launcher”

android:label=”@string/app_name”

android:supportsRtl=”true”

android:theme=”@style/AppTheme”>

<activity android:name=”.Inici”>

<intent-filter>

<action android:name=”android.intent.action.MAIN” />

<category

android:name=”android.intent.category.LAUNCHER” />

</intent-filter>

</activity>

<activity android:name=”.MapsActivity” />

<activity android:name=”.iniciTaxista” />

<activity android:name=”.iniciClient” />

<activity android:name=”.registreTaxista” />

<activity android:name=”.registreClient” />

<!--

The API key for Google Maps-based APIs is defined as a

string resource.

(See the file “res/7efiní/google_maps_api.xml”).

Note that the API key is linked to the encryption key

used to sign the APK.

You need a 7efiní7t API key for each encryption key,

including the release key that is used to

sign the APK for publishing.

You can 7efiní the keys for the debug and release targets

in src/debug/ and src/release/.

<meta-data

android:name=”com.google.android.gms.version”

android:value=”@integer/google_play_services_version” />

<meta-data

android:name=”com.google.android.geo.API_KEY”

android:value=”AizaSyA3ROFLejw2mvokz9VylK-zAyQ1kOT2vQI” />

<activity

android:name=”.Client”

android:label=”@string/title_activity_client” />

<activity android:name=”.ProvaObjectes”></activity>

</application>

</manifest>

Codi1: configuració del manifest

Cal recordar també que Android és un sistema operatiu en constant evolució i per tant hi ha una

cosa que cal remarcar. Abans els permisos es concedien a la pantalla d’inici de l’aplicació i tots

alhora. Actualment els permisos es demanen quan es fan servir.

Un exemple d’aquest sistema seria que, en entrar a l’aplicació, només et demanaria els permisos

del GPS quan iniciessis la geo-localització. Més endavant es mostrarà com funciona el sistema

de sol·licitud de permisos en execució.

Page 9: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

8

2.3.2. Gradle

El gradle és l’encarregat de configurar les versions de l’aplicació. Tothom sap que tant Android

com les APIs que utilitzem evolucionen amb el temps, i s’ha d’anar en compte en què totes les

versions tant de l’Android com de les APIs utilitzades siguin compatibles.

Al codi 2, podem veure la versió d’Android i de google-services. Aquest gradle es genera

automàticament després de fer el projecte i escollir la versió d’Android.

// Top-level build file where you can add configuration options common

to all sub-projects/modules.

buildscript {

repositories {

jcenter()

google()

}

dependencies {

classpath 'com.android.tools.build:gradle:3.1.3'

classpath 'com.google.gms:google-services:3.0.0' // google-

services plugin

// NOTE: Do not place your application dependencies here; they

belong

// in the individual module build.gradle files

}

}

allprojects {

repositories {

jcenter()

google()

}

}

task clean(type: Delete) {

delete rootProject.buildDir

}

Codi2: Configuració gradle

Després tenim el gradle on configuraré la versió de SDK i APIs, que es mostra a Codi 3.

apply plugin: 'com.android.application'

android {

compileSdkVersion 25

buildToolsVersion '27.0.3'

defaultConfig {

applicationId "urv.apptfg"

minSdkVersion 23

targetSdkVersion 25

versionCode 1

versionName "1.0"

testInstrumentationRunner

"android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {

release {

Page 10: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

9

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-

android.txt'), 'proguard-rules.pro'

}

}

}

dependencies {

implementation 'com.android.support.constraint:constraint-

layout:1.1.2'

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso:espresso-

core:2.2.2', {

exclude group: 'com.android.support', module: 'support-

annotations'

})

compile 'com.android.support:appcompat-v7:25.3.1'

testCompile 'junit:junit:4.12'

compile 'com.google.firebase:firebase-core:9.0.0'

compile 'com.google.firebase:firebase-database:9.0.0'

compile 'com.google.firebase:firebase-auth:9.0.0'

implementation 'com.google.android.gms:play-services-maps:9.0.0'

compile 'com.google.android.gms:play-services-maps:9.0.0'

implementation 'com.android.support:recyclerview-v7:25.4.0'

}

apply plugin: 'com.google.gms.google-services'

Codi3: Versions gradle

En aquest cas particular s’ha hagut de detallar la versió de Google maps que s’utilitza, de declarar

la funcionalitat del recycler view i també s’han hagut d’afegir els diferents serveis de Firebase:

database i l’authenticator. Aquest últim és el servei d’autentificació que veurem quan detalli les

activitys.

Com es veu al codi 3, totes les versions són les 9.0.0, i no perquè siguin les més actuals, sinó

perquè com que tot ha de ser compatible entre si, no es pot fer servir una versió més moderna

d’una cosa que de l’altra; i en aquesta versió hi ha compatibilitat.

El principal problema d’aquest sistema és que tant l’Android com les diferents APIs evolucionen

a diferent ritme, i s’ha d’anar ajustant contínuament la versió. Això també implica canvis

substancials a la manera d’accedir a les pròpies APIs.

Page 11: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

10

2.4. Classes

El projecte està distribuït en tres Java class i nou activitys.

Les activitys són el conjunt d’una Java class més una classe XML per donar-li forma a la interfície,

i se’n necessita una per a cada pantalla que tingui l’aplicació: inici, pantalla registre, etc.

Algunes d’aquestes activity seran invisibles a l’usuari final, però són molt útils a l’hora de

desenvolupar el codi. Per tant, en aquest apartat es comentarà totes les classes utilitzades i es

mostraran les activitys com es veuen a l’hora del desenvolupament.

En l’apartat de resultats finals ja es mostrarà com queden aquestes interfícies per l’usuari últim.

A la figura 1 podem veure l’estructura d’activitys del projecte.

Figura1: Estructura Activitys

Page 12: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

11

2.4.1. Conceptes bàsics de l’entorn Android

Abans de començar a comentar les classes una per una, es farà una explicació de dos conceptes

que es repetiran en totes les activitys i cal tenir clar què són i perquè serveixen:

Intent:

Intent és un mètode abstracte de l’entorn Android que permet fer crides a les altres activitys.

Context

El context és una interfície abstracta, que crea l’entorn per poder accedir a tot el “context” de

l’aplicació, que és l’estructura de nivell superior en una app.

Una app Android crea automàticament un context, i tots els mètodes Android cridats per

defecte amb l’Android Studio s’executen en el marc d’aquest context.

Aquest s’encarrega de llançar noves Activitys, escoltar els intents i emetre’ls en brodcast perquè

totes les Activitys sàpiguen que hi ha un missatge de crida.

Toast

Són els missatges emergents que duren uns segons en pantalla, tal i com veiem a la figura 2:

Figura2: Mostra toast

Aquets missatges són molt útils a l’hora de donar informació durant l’execució del programa,

com quan et registres correctament o et desconnectes de l’aplicació.

Page 13: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

12

A part de la utilitat de donar informació a l’usuari final, també és molt útil en l’entorn de

desenvolupament ja que Android Studio incorpora una consola per seguir tot el programa, però

no inclou un mètode per depurar el codi (debugger). Per tant, la millor manera per anar sabent

quines variables hi ha en cada moment, es anar deixant toast durant el funcionament del

programa. A la figura3 tenim un exemple de l’esmentat anteriorment.

Figura3: Mostra informació toast

2.4.2. Java class

Tot seguit comentaré les classes, una per una, seguint l’ordre definit anteriorment.

Hi ha tres Java class al projecte. Dos són objectes i l’altra relaciona les referències del projecte

amb els de la base de dades de Firebase.

Clients

Cada cop que es registra un client a l’activity Clients, s’hauran de passar els seus atributs per

poder-lo crear com a objecte. El seu constructor es pot observar al codi4:

public Clients() {

}

public Clients(String nom, String mobil, String email,String pos) {

this.nom = nom;

this.email = email;

this.mobil = mobil;

this.pos=pos;

}

Codi4: Constructor Clients

Sempre es deixa un constructor buit, perquè s’ha de tenir en compte que és un projecte que no

està finalitzat, i sempre es poden fer canvis a l’hora de crear un objecte. Així forcem que es creï

segons convingui.

Page 14: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

13

Un cop registrat un client, es té l’objecte a la base de dades completament funcional gràcies a

la funció de registrar. La classe Clients només dona forma a l’objecte i ens proporciona els getters

i els setters. Els getters i setters són mètodes pre-definits de java i auto-generats per l’IDE per

consultar i modificar les variables.

Taxistes

Al igual que Clients, Taxistes és una Java class que només dona forma a l’objecte, i ens

proporciona els getters i setters. Mostrem el seu constructor en el codi 4.

public Taxistes() {

}

public Taxistes(String nom, String codi, String mobil, String

usuari) {

this.nom = nom;

this.codi = codi;

this.mobil = mobil;

this.usuari = usuari;

this.ocupat=false;

}

Codi4: Constructor Taxistes

FirebaseReference

Aquesta classe proporciona les relacions entre les referències de l’app i les de la Firebase. Segons

com s’estructurin les referències, es tindrà un sistema basat en arbres en el qual s’hi pot accedir

navegant pels childs, que vindrien a ser les seves branques. Funciona similar a un sistema de

carpetes on el node final és l’objecte.

En el codi 5, es poden observar les diferents referències de l’aplicació. Les referències[5]

utilitzades són Taxistes i Clients, que estructuren la base de dades diferenciant aquestes dues

entitats. En un principi s’estructuraven aquests dos childs en un de més gran que era Usuaris,

utilitzant herència per fer una distinció entre els que eren taxistes i els que eren clients. Però

això sumava molta complexitat a l’hora de cridar les referències a l’aplicació, i tampoc no era

massa útil a l’hora d’estalviar feina de desenvolupament.

public class FirebaseReference {

//final public static String USUARIS_REFERENCE= "Usuaris";

final public static String TAXISTA_REFERENCE= "Taxistes";

final public static String CLIENT_REFERENCE= "Clients";

}

Codi5: Referencies firebase.

Page 15: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

14

2.4.3. Activitys

En aquest apartat es comentaran les activitys, ajuntant la seva part de “processat”, que seria la

Java class, més la seva part de interfície que es l’XML. S’ha de tenir en compte que aquestes

parts estan altament relacionades i es poden fer funcions a la Java class que canviïn l’XML.

Inici

A la figura 4 es mostra l’Activity Inici en la seva versió de prova. La funció onCreate serveix per

executar totes les instruccions necessàries a l’hora d’obrir l’activity.

Figura4: Activity Inici Desenvolupament

Per associar la classe Java amb la interfície XML cal utilitzar la instrucció setContentView tal i

com veiem en el codi 6. I el mètode bind() tan sols és una manera d’estructurar la classe que

ensenyarem a continuació.

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_inici);

bind();

}

Codi6: onCreate Inici

En aquesta activity tenim el logotip de l’aplicació i tres botóns (dos en la versió final). Aquests

botóns tenen l’única funció de redirigir l’usuari a les activitys principals de taxista o clients

mitjançant un intent a IniciTaxista o IniciCleints. L’estructura dels intents quasi sempre tindrà el

mateix format: es declara un botó, es posa “clickable”, i s’assigna la funció que es vol que realitzi

en el cas que es premi, dins el mètode onClick. Dins aquest mètode, es crea un intent per accedir

a la següent activity i es sol·licita el context de l’activity de destí, tal i com es veu al codi 7.

Page 16: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

15

private void bind(){

taxiButton = (Button) this.findViewById(R.id.taxistabutton);

taxiButton.setClickable(true);

taxiButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

iniciTaxista.class);

startActivity(intent);

}

});

clientButton = (Button) this.findViewById(R.id.clientbutton);

clientButton.setClickable(true);

clientButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

iniciClient.class);

startActivity(intent);

}

});

provaButton = (Button) this.findViewById(R.id.provabutton);

provaButton.setClickable(true);

provaButton.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

ProvaObjectes.class);

startActivity(intent);

}

});

}

Codi7: Metode bind()

Un cop polsat el botó, el context llença el missatge de brodcast i la classe referida executa el seu

mètode onCreate.

El botó de proves fa un intent a la classe ProvaObjectes. Aquesta classe és interesant perquè és

una mescla de tots els recursos utilitzats en l’aplicació.

Com he dit anteriorment, el mètode bind() serveix únicament per seguir una metodologia de

treball, ja que l’Android Studio t’ofereix un seguit d’eines per saber en qualsevol moment dins a

quins mètodes estàs i dins de quines classes, tal i com es veu en la figura 5.

Figura 5: Navegació Android Studio.

Page 17: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

16

Seguir un criteri per disposar tota l’estructura de paquets de classes i mètodes és molt

important a l’hora de re-escriure contingut i seguir el programa, ja que no es disposa d’un

mètode debugger com a tal. Només es disposa d’una consola, i al ser un entorn de creació amb

moltes funcions al background, interessa tenir l’estructura el màxim clara possible, ja que l’únic

sistema per seguir les dades és amb la utilització de toasts; en el codi 8 podem veure l’estructura

d’un toast. Els toasts són els missatges emergents que surten durant uns segons en fer una acció,

tal i com veiem a la figura 6.

Context context = getApplicationContext();

Toast.makeText(context, mail + "tu KEY" + taxiKey,

Toast.LENGTH_LONG).show();

Codi8: estructura toast.

Figura6: Toast emergent pantalla prova.

Aquí es mostra un exemple de toast, utilitzat per comprovar que s’agafava la clau correcta de la

base de dades de Firebase juntament amb el correu de la sessió que s’havia iniciat.

Referent a la classe XML que acompanya a la classe Java Inici, no té massa rellevància. Es tracta

d’un Linear Layout que permet posar la imatge i estructura els botóns d’una forma vertical, cada

element per sota de l’anterior.

Cada element té la seva pròpia configuració: altitud, amplada, color, gravetat. Però en aquest

cas, estan tots amb el mateix disseny. Així que tan sols es comentarà els XML amb coses més

remarcables, com els mapes o les activitys de prova.

Page 18: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

17

ProvaObjectes

El tercer botó de l’inici és el més important i interesant a nivell tècnic. Per tant es considera

oportú explicar aquesta activity en segon lloc, ja que totes les següents tenen alguna relació amb

el funcionament d’aquesta, tot i que l’usuari final no la podrà utilitzar, perquè té un

funcionament únic i exclusiu pel desenvolupament i per fer jocs de proves de manera ràpida.

Servirà tant per provar la comunicació amb la Firebase amb l’ajuda d’un recycle view[6], com

per ajuntar totes les utilitats de l’aplicació en una sola activity de proves. A la figura 7 en podem

veure el resultat.

Figura7: Activity prova

A continuació es desglossaran els diferents elements exposats.

recyclerView

Aquest element és relativament recent en Android i permet crear llistes en les quals només es

carreguen els elements que tenim en pantalla. La principal diferència respecte a una llista

normal, és que si una llista té dos-cents elements, aquesta carregaria tots els elements, fent que

aquest procés tingués molta càrrega per al dispositiu. En canvi amb un recycleView, només

carrega els elements que pot visualitzar. Així que si es té una llista de tres mil elements, però

només en calen visualitzar deu, el dispositiu només haurà de carregar aquests deu, i a l’hora de

navegar per la llista, es van carregant els elements un a un.

Page 19: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

18

Aquest tipus de llista s’acompanya d’una classe anomenada adapter, que és l’encarregada de

donar-li format i informació a cada cel·la; el procés de proporcionar informació s’anomena

inflate _aquest concepte s’utilitzarà més endavant. Aquestes classes estan estretament

relacionades, ja que una és la posició i l’altra el dipòsit.

Per tant, la classe Adapter s’estendrà d’una classe RecycleView tal i com es veu al codi 9:

public class Adapter extends

RecyclerView.Adapter<Adapter.TaxistesViewHolder>{

List<Taxistes> taxistes;

public Adapter(List<Taxistes> taxistes) {

this.taxistes = taxistes;

}

@Override

public TaxistesViewHolder onCreateViewHolder(@NonNull ViewGroup

parent, int viewType) {

View v =

LayoutInflater.from(parent.getContext()).inflate(R.layout.row_recyvler

,parent, false);

TaxistesViewHolder holder = new TaxistesViewHolder(v);

return holder;

}

@Override

public void onBindViewHolder(@NonNull TaxistesViewHolder holder,

int position) {

Taxistes taxista = taxistes.get(position);

holder.nom.setText(taxista.getNom());

holder.gps.setText(taxista.getLatitud()+"

"+taxista.getLongitud());

}

@Override

public int getItemCount() {

return taxistes.size();

}

public static class TaxistesViewHolder extends

RecyclerView.ViewHolder {

TextView gps,nom;

public TaxistesViewHolder(View itemView) {

super(itemView);

gps = (TextView) itemView.findViewById(R.id.textViewgps);

nom = (TextView) itemView.findViewById(R.id.textViewNom);

}

}

}

Codi9: Estructura Adaptador Recycler View

Page 20: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

19

A la figura 8 es veu el layout resultant de l’ activity de proves.

Figura8: Estructura interfície de l’activity proves.

La part més important d’aquest codi és la de l’inflate, que és un mètode abstracte que serveix

per assignar tots els valors sol·licitats des de la Firebase a l’adapter, de tal manera que es podrà

omplir la llista amb la informació real que rebi des de la base de dades. Aquest procés s’anomena

“inflar” el context.

Aquesta classe anirà lligada tant amb la interfície de la fila, que li direm row_recyvler, com amb

el recycleView que implementarem a la classe ProvaObjectes. La classe XML row_recyvler

assignarà una interfície determinada a la fila que ompli a la llista, tal i com es veu en el codi 10.

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout

xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:gravity="center"

android:orientation="vertical">

<TextView

android:id="@+id/textViewgps"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="gps"

android:textAlignment="center"

android:textAppearance="@android:style/TextAppearance.Material.Large"

/>

<TextView

Page 21: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

20

android:id="@+id/textViewNom"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="nom"

android:textAlignment="center"

android:textAppearance="@android:style/TextAppearance.Material.Large"

/>

<View

android:layout_width="wrap_content"

android:layout_height="1px"

android:background="@android:color/darker_gray" />

</LinearLayout>

Codi10: XML adapter

Aquest Codi 10 reflecteix l’estructura que té la interfície de la figura 9:

Figura9: Estructura adaptar.

En aquest punt ja es pot omplir el RecycleView amb els adapters creats anteriorment. Dins el

LinearLayout que contindrà tant la llista com el mapa, s’introdueix la part del recycle view, on se

li dona forma al codi 11.

<android.support.v7.widget.RecyclerView

android:id="@+id/recyclerView"

android:layout_width="wrap_content"

android:layout_height="wrap_content">

</android.support.v7.widget.RecyclerView>

Codi11: XML RecyclerView.

Page 22: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

21

Realment, aquest es tracta com si fos un layout normal en la part del XML. La part complexa ve

donada a la classe Java, on per omplir de contingut cada cel·la, s’haurà de recórrer a la base de

dades de Firebase.

Al codi 12 es creen els objectes necessaris per a l’activity. Per tant en aquest punt es tindran

creats un Adaptar, un RecicleView i una Llista de taxistes, que són el tipus d’objecte amb els

quals inflarem l’adapter.

public class ProvaObjectes extends FragmentActivity {

RecyclerView rv;

List<Taxistes> taxistes;

Adapter adapter;

Codi12: Declarar objectes a ProvaObjectes.

Dins el mètode onCreate que tenim al codi 13, hi ha la part de super.onCreate que serveix per

heretar tot el context que teníem anteriorment, i la part de setContentView que ens assignarà

la interfície a la activity.

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_prova_objectes);

Codi13: OnCreate provaObjectes.

rv = (RecyclerView) findViewById(R.id.recyclerView);

rv.setLayoutManager(new LinearLayoutManager(this));

taxistes = new ArrayList<>();

FirebaseDatabase database = FirebaseDatabase.getInstance();

adapter = new Adapter(taxistes);

rv.setAdapter(adapter);

Codi14: Inflate del Recycler View

En el codi 14 es relacionen tots els elements; primer es dona valor al array de taxistes, es posa

cada element en un adapter i es col·loquen dins el recyclerView. S’assigna el recyclerView que

s’ha creat al XML, es crea la llista de taxistes per poder omplir els adapters, es crea un adaptar

de taxistes i aquest s’introdueix dins el recyclerView. Cal recordar que la base de dades està

dividida entre taxistes i clients, tal i com es mostra a la figura 10.

Figura10: Jerarquia Firebase.

Page 23: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

22

Per tant, per capturar la informació de cada node de la base de dades, primer s’ha hagut d’entrar

a la carpeta taxistes, tal i com definim al codi 15, i així es podrà navegar per tots els nodes que

existeixen dins aquesta referència tal i com veiem a la figura 11.

database.getReference("Taxistes").addValueEventListener(new

ValueEventListener() {}

Codi15: Definició path referència taxista.

Figura11: Nodes Taxistes.

Per utilitzar l’eina que proporciona la lectura d’informació a temps real, es necessita utilitzar el

mètode onDataChange el qual es mostra al codi 16, que el proporciona l’API de Firebase. Aquest

mètode s’executarà cada cop que hi hagi un canvi a dins la carpeta referència[7].

database.getReference("Taxistes").addValueEventListener(new

ValueEventListener() {

@Override

public void onDataChange(DataSnapshot dataSnapshot) {

if( myMarker != null){

mMap.clear();

}

taxistes.removeAll(taxistes);

for (DataSnapshot snapshot :

dataSnapshot.getChildren()) {

Taxistes taxista = snapshot.getValue(Taxistes.class);

taxistes.add(taxista);

lon = taxista.getLongitud();

lati = taxista.getLatitud();

nom= taxista.getNom();

mobil = taxista.getMobil();

ocupat= taxista.isOcupat();

}

adapter.notifyDataSetChanged();

}

@Override

public void onCancelled(DatabaseError databaseError) {

}

});

Codi 16: Mètode onDataChange.

Page 24: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

23

Dins al mètode onDataChange, es fa un foreach, que permet recórrer tota la llista d’objectes

dins la carpeta referència, i capturar la informació que sigui necessària.

Tornant a l’adapter, per crear una fila cal utilitzar el mètode del codi 17.

@Override

public void onBindViewHolder(@NonNull TaxistesViewHolder holder, int

position) {

Taxistes taxista = taxistes.get(position);

holder.nom.setText(taxista.getNom());

holder.gps.setText(taxista.getLatitud()+"

"+taxista.getLongitud());

}

Codi17: Mètode onBindViewHolder.

On es creen les variables locals “nom” i “gps”, tal i com es veu al codi 18, es fan els gets dels

valors del taxista i s’assignen aquest valors al XML i, finalment, es mostren per pantalla.

public static class TaxistesViewHolder extends RecyclerView.ViewHolder

{

TextView gps,nom;

public TaxistesViewHolder(View itemView) {

super(itemView);

gps = (TextView) itemView.findViewById(R.id.textViewgps);

nom = (TextView) itemView.findViewById(R.id.textViewNom);

}

Codi18: Constructor TaxistesViewHolder.

Per tant hi han dues opcions: fer el get directament de l’objecte en qüestió (this), o assignar

valors a unes altres variables en el moment del foreach. En el codi anterior s’utilitza ambdós

versions perquè no només es crea l’adapter, sinó que més endavant es mostrarà la part del mapa

on ja es pinten totes les posicions dels taxistes.

Mapa

La part del mapa té un XML directament relacionat amb l’API de Google tal i com veiem al codi

19.

<fragment xmlns:android="http://schemas.android.com/apk/res/android"

android:id="@+id/map"

android:name="com.google.android.gms.maps.SupportMapFragment"

android:layout_width="match_parent"

android:layout_height="250dp" />

Codi19: Abstracte XML google maps

Aquesta part de codi està proporcionada directament per google, i l’únic que s’ha fet ha sigut

ajustar el layout a la pantalla segons ha sigut necessari.

El que s’ha de tenir en compte per distribuir els markers pel mapa, és agafar els atributs de cada

objecte a mesura que recorri la llista i utilitzar la funció onMapReady() tal i com es veu al codi20,

que assignarà cada taxista al mapa segons les coordenades que tingui.

Page 25: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

24

database.getReference("Taxistes").addValueEventListener(new

ValueEventListener() {

@Override

public void onDataChange(DataSnapshot dataSnapshot) {

if( myMarker != null){

mMap.clear();

}

taxistes.removeAll(taxistes);

for (DataSnapshot snapshot :

dataSnapshot.getChildren()) {

Taxistes taxista = snapshot.getValue(Taxistes.class);

taxistes.add(taxista);

lon = taxista.getLongitud();

lati = taxista.getLatitud();

nom = taxista.getNom();

mobil = taxista.getMobil();

ocupat= taxista.isOcupat();

onMapReady(mMap);

}

adapter.notifyDataSetChanged();

}

Codi20: Mètode onDataChange.

La funció onMapReady() es mostra al codi 21, i a part de situar el marker al mapa, també donarà

informació extra de l’objecte, com ara el nom o el mòbil del taxista i si està sol·licitat o ocupat...

segons el codi de colors que es tingui ideat.

@Override

public void onMapReady(GoogleMap googleMap) {

mMap = googleMap;

LatLng localitzacioTaxi = new LatLng(lati,lon);

if (lati == 0 && lon == 0 ) {

} else {

if (ocupat!=false) {

myMarker = mMap.addMarker(new

MarkerOptions().position(localitzacioTaxi).title("Nom :"+nom+" Mobil:

"+mobil).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFa

ctory.HUE_RED)));

} else {

myMarker = mMap.addMarker(new

MarkerOptions().position(localitzacioTaxi).title("Nom :"+nom+" Mobil:

"+mobil).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFa

ctory.HUE_GREEN)));

}

}

}

Codi21: Mètode onMapReady

Page 26: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

25

Inici Client

Aquesta part de la interfície XML s’explicarà amb l’ajuda que ens proporciona l’Android Studio

com a IDE, tal i com veiem a la figura 12, on es tenen tot un seguit d’opcions i es poden ajustar

a una pantalla que simula el mòbil, com es pot comprovar a la figura 13. Un cop fixats tots els

elements, els ajustos finals es faran en el codi XML, ja que et permet més precisió en alguns

detalls. Però l’estructura general de l’activity es pot fer en l’apartat de disseny amb molta

facilitat.

Figura 12: Estructura XML en forma d’arbre.

Figura 13: Estructura interfície activity iniciClient.

Page 27: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

26

En accedir a l’apartat de l’aplicació dirigida als clients, s’entra a la pantalla de la figura 14.

Figura14: Activity IniciClient.

En el codi 22 es veuen tots els botóns i camps de text que s’han de declarar i la funció onCreate

de l’activity

public class iniciClient extends AppCompatActivity implements

View.OnClickListener {

Button iniClientButton;

TextView registClient;

EditText email, contrassenya;

static String accesMail;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_inici_client);

iniClientButton = (Button)

this.findViewById(R.id.iniciarClient);

email = (EditText) this.findViewById(R.id.usuariClient);

contrassenya = (EditText)

Page 28: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

27

this.findViewById(R.id.passwordClient);

iniClientButton.setClickable(true);

iniClientButton.setOnClickListener(this);

registClient = (TextView)

this.findViewById(R.id.registrarClient);

registClient.setClickable(true);

registClient.setOnClickListener(this);

}

Codi22: Codi per declarar IniciClient

Un cop es tenen els botóns declarats i funcionals (clicables), es farà el mètode onClick tal i com

es mostra al codi 23.

@Override

public void onClick(View view) {

switch (view.getId()){

case R.id.registrarClient:

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

registreClient.class);

startActivity(intent);

break;

case R.id.iniciarClient:

if (email.getText().toString().isEmpty() ||

contrassenya.getText().toString().isEmpty()){

Context context = getApplicationContext();

Toast.makeText(context, "Algun camp obligatori no esta

ple!", Toast.LENGTH_LONG).show();

}else {

String mail = email.getText().toString();

String pass = contrassenya.getText().toString();

iniClient(mail, pass);

}break;

}

}

Codi23: Mètode onClick.

En aquest mètode es farà un switch dels dos botóns que hi ha: el d’iniciar sessió o el de registrar.

Si es prem el botó de registrar, el context farà un intent a l’activity de registrarClient. En el cas

que es polsi el botó d’iniciar sessió, aquest farà una comprovació que els dos camps estiguin

emplenats correctament amb la funció isEmpty(); després “castejarà” el contingut a text, per

poder-ho tractar tot com un string. “Castejar” o cast en anglès vol dir canviar el format de

l’objecte; per exemple, si tenim un número amb format de integer i li fem un cast a String, aquest

estarà tractat com si fos un seguit de caràcters. Després s’assignen els valors que he escrit a les

variables mail i pass que es tenen declarats en aquesta classe i es passen al mètode iniClient(mail, pass);

En aquest punt, s’utilitzarà l’API d’autentificació de Firebase que permet comprovar si les

credencials són correctes o no, tal i com es veu al codi 24. Si aquestes són correctes, es podrà

accedir a la següent activity i sortirà un missatge de benvinguda. També permetrà estar

connectats directament amb la base de dades i poder llegir i escriure les dades necessàries per

fer funcionar l’aplicació. Si les credencials no són correctes, apareixerà un missatge d’error del

tipus toast.

Page 29: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

28

private void iniClient(String mail, String pass){

FirebaseAuth.getInstance().signInWithEmailAndPassword(mail,pass).addOn

CompleteListener(new OnCompleteListener<AuthResult>() {

@Override

public void onComplete(@NonNull Task<AuthResult> task) {

if(task.isSuccessful()){

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

Client.class);

startActivity(intent);

Context context = getApplicationContext();

Toast.makeText(context,

"Benvingut!"+email.getText().toString(), Toast.LENGTH_LONG).show();

accesMail = email.getText().toString();

}else{

Context context = getApplicationContext();

Toast.makeText(context, "Uauari o contrassenya no

vàlida!", Toast.LENGTH_LONG).show();

}

}

});

}

Codi24: Autentificar Client.

Per finalitzar totes les activitys menys la principal, es configurarà el botó de tirar enrere com es

veu en el codi 25 que tenen tots els mòbils Android, de manera que al ser polsat tanqui l’activity

actual i torni a l’anterior:

@Override

public void onBackPressed(){

Intent intent = new Intent();

intent.setClass(getApplicationContext(), Inici.class);

startActivity(intent);

super.onBackPressed();

finish();

}

Codi25: Botó de retrocedir.

RegistreClient

Un cop s’accedeixi a registrar-se com a client, tindrem els atributs del codi 26.

public class registreClient extends AppCompatActivity {

private EditText nom,mobil, email,contrassenya;

private Button registrarClient;

FirebaseDatabase databaseClient = FirebaseDatabase.getInstance();

DatabaseReference clientRef = databaseClient.getReference();

Codi26: Declaració registreClient

Page 30: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

29

on s’utilitzarà el formulari de la figura 15 per donar valors a aquests atributs.

Figura15: Formulari registre.

Una vegada omplert, s’assignarà els atributs al node del client mitjançant el codi 27.

Private void registrarClient(String emailr,String contra){

FirebaseAuth.getInstance().createUserWithEmailAndPassword(emailr,contr

a).addOnCompleteListener(new OnCompleteListener<AuthResult>() {

@Override

private void registrarClient(String emailr,String contra){

FirebaseAuth.getInstance().createUserWithEmailAndPassword(emailr,contr

a).addOnCompleteListener(new OnCompleteListener<AuthResult>() {

@Override

public void onComplete(@NonNull Task<AuthResult> task) {

if(task.isSuccessful()){

Context context = getApplicationContext();

Toast.makeText(context, “S’ha registrat

29óvil29tamente!”, Toast.LENGTH_LONG).show();

Clients client = new

Clients(nom.getText().toString(),29óvil.getText().toString(),

email.getText().toString(),null);

clientRef.child(FirebaseReference.CLIENT_REFERENCE).push().setValue(cl

ient);

}else{

Context context = getApplicationContext();

Toast.makeText(context, “No s’ha pogut registrat!”,

Toast.LENGTH_LONG).show();

}

}

});

}

Codi27: Mètode registrarClient.

Cal mencionar que s’utilitzarà la referència CLIENT_REFERENCE per dirigir el node a la carpeta

de clients.

La primera part del codi validarà com a usuari, mitjançant el correu i la contrasenya, a la base de

dades. Aquesta part de codi ve proporcionada per l’API d’autentificació de la Firebase la qual

Page 31: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

30

podria anar acompanyada de diferents funcionalitats de la API d’autentificació, però això es

comentarà a l’apartat de línies futures.

La segona part del codi farà un get de tots els camps i el desarà a la base de dades, mitjançant

l’opció setVaule(). En aquesta part de codi cal remarcar dues coses: la primera és que al ser

nova informació, cal que els atributs estiguin acompanyats de la funció push() (aquesta funció

crearà nova informació a la base de dades). Si s’utilitzés, només es podria editar informació. La

segona part que cal remarcar, és que la nova informació estarà disposada a l’arrel de clients,

mitjançant la referència de clients. El formulari ve descrit per la figura 16.

Figura16: Estructura XML registreClient

Page 32: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

31

IniciTaxista

Aquesta activity és pràcticament idèntica a la de IniciClient, però per l’altra banda de l’arbre.

Es té la mateixa configuració de login més registre, amb una temàtica diferent com es pot veure

a la figura 17.

Figura 17: Estructura XML iniciTaxista

Com s’ha vist, el botó iniciar farà les comprovacions pertinents per poder autentificar-se a la

base de dades i en cas positiu farà un intent a Taxista. Per altra banda si es prem el botó de

registrar, farà un intent cap a RegistreTaxista

Page 33: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

32

RegistreTaxista

Registre taxista és molt similar a RegistreClient, tant l’estructura del codi Java com la del XML.

El disseny d’aquesta activity és el de la figura 18:

Figura18: Estructura formulari registreTaxista.

La principal diferència està en els camps a emplenar, ja que per fer la sol·licitud de taxista es

necessita un codi de taxi, que representa la llicència del taxista, i aquesta hauria de ser vàlida.

Com que el codi és pràcticament idèntic i l’únic que canvia és el tipus d’objecte, només es

comentarà la part dels atributs com es veu en el codi 28.

public class registreTaxista extends AppCompatActivity {

EditText mobil, codi, email, contrassenya, nom;

Button registrarTax;

FirebaseDatabase databaseTaxista = FirebaseDatabase.getInstance();

DatabaseReference taxRef = databaseTaxista.getReference();

Codi 28: Declaració registreTaxista.

Aquí es poden veure els diferents atributs que es tenen respecte als clients, i que la referència

utilitzada serà una referència cap a TAXISTA_REFERENCE. Per tant, l’objecte taxista es guardarà

dins la child de Taxistes

Page 34: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

33

Client

En aquesta activity comencen les funcionalitats pròpies de l’aplicació. Aquí hi ha algunes de les

funcionalitats de ProvaObjectes, que pertoquen als clients.

La funcionalitat de geo-localització ens mostrarà l’usuari centrat en el mapa amb un punt blau

mitjançant el mètode del codi 29[8].

public void onMapReady(GoogleMap googleMap) {

mMap = googleMap;

localitMeva = new LatLng(lati, lon);

if (lati == 0 && lon == 0) {

} else {

if (myMarker != null) {

myMarker.remove();

myMarker = mMap.addMarker(new

MarkerOptions().position(localitMeva).icon(BitmapDescriptorFactory.def

aultMarker(BitmapDescriptorFactory.HUE_BLUE)));

} else {

myMarker = mMap.addMarker(new

MarkerOptions().position(localitMeva).icon(BitmapDescriptorFactory.def

aultMarker(BitmapDescriptorFactory.HUE_BLUE)));

mMap.moveCamera(CameraUpdateFactory.newLatLng(localitMeva));

mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(localitMeva, 10));

}

}

}

Codi 29: Mètode onMapReady

En aquest mètode es destaquen dos punts importants. Quan “refresquem” la posició d’un

marker, l’anterior es queda al mapa i, per tant, cada cop que es tingui un marker no null es

borrarà i se’n crearà un de nou. Per altra banda, quan es crea el marker, el mapa se centrarà en

localitMeva, que és la posició de l’usuari i se li assignarà un 10 al zoom, per fer-lo d’una mida

relativa a una ciutat. L’escala del zoom és inversa: 1 és el mapa mundi, 15 seria per veure una

zona petita d’una ciutat.

Hi ha dues formes d’executar el mètode, una introduint-lo al mètode onCreate i l’altra que sigui

una acció clickable. S’ha decidit executar-lo amb un botó per qüestions de comoditat com es veu

al codi 30.

iniciGps = (Button) findViewById(R.id.buttonIniciar);

iniciGps.setOnClickListener(new View.OnClickListener() {

@Override

public void onClick(View view) {

Context context = getApplicationContext();

// Acquire a reference to the system Location Manager

LocationManager locationManager = (LocationManager)

Page 35: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

34

Client.this.getSystemService(Context.LOCATION_SERVICE);

// Define a listener that responds to location updates

LocationListener locationListener = new LocationListener() {

public void onLocationChanged(Location location) {

// Called when a new location is found by the network

location provider.

gps = "" + location.getLatitude() + " " +

location.getLongitude();

lati = location.getLatitude();

lon = location.getLongitude();

onMapReady(mMap);

clientm.child(clientKey).child("pos").setValue(gps); //

Per escriure la pos

}

public void onStatusChanged(String provider, int status,

Bundle extras) {

}

public void onProviderEnabled(String provider) {

}

public void onProviderDisabled(String provider) {

}

};

Codi 30: Mètode onLocationChanged

Dins de l’onCreate tenim la funció principal que utilitza la base de dades realtime de Firebase.

Aquesta és la funcionalitat que ens pintarà els taxistes en el mapa tal i com es pot observar al

codi 31.

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_client);

// Obtain the SupportMapFragment and get notified when the map is

ready to be used.

SupportMapFragment mapFragment = (SupportMapFragment)

getSupportFragmentManager()

.findFragmentById(R.id.map);

mapFragment.getMapAsync(this);

onChangedTaxistes();

mail = iniciClient.accesMail;

databaseClient = FirebaseDatabase.getInstance();

clientm = databaseClient.getReference("Clients");

clientm.orderByChild("email").equalTo(mail).addListenerForSingleValueE

vent(new ValueEventListener() {

@Override

public void onDataChange(DataSnapshot dataSnapshot) {

for (DataSnapshot childSnapshot :

dataSnapshot.getChildren()) {

clientKey = childSnapshot.getKey();

}

}

@Override

public void onCancelled(DatabaseError databaseError) {

}

});

Codi 31: Estructura de lectura de la base de dades.

Page 36: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

35

on onChangedTaxistes()és el codi 32.

public void onChangedTaxistes(){

taxistes = new ArrayList<>();

adapter = new Adapter(taxistes);

database = FirebaseDatabase.getInstance();

database.getReference("Taxistes").addValueEventListener(new

ValueEventListener() {

@Override

public void onDataChange(DataSnapshot dataSnapshot) {

if( markerTaxistes != null){

mMap.clear();

myMarker = mMap.addMarker(new

MarkerOptions().position(localitMeva).icon(BitmapDescriptorFactory.def

aultMarker(BitmapDescriptorFactory.HUE_BLUE)));

}

taxistes.removeAll(taxistes);

for (DataSnapshot snapshot :

dataSnapshot.getChildren()) {

Taxistes taxista = snapshot.getValue(Taxistes.class);

taxistes.add(taxista);

lonTaxi = taxista.getLongitud();

latTaxi = taxista.getLatitud();

ocupat=taxista.isOcupat();

nom = taxista.getNom();

mobil = taxista.getMobil();

pintarTaxistes(mMap);

}

adapter.notifyDataSetChanged();

}

@Override

public void onCancelled(DatabaseError databaseError) {

}

});

}

Codi32: Mètode onChanedTaxistes

Aquest mètode crearà una llista de taxis. Per cada taxista creat cridarà a la funció

pintarTaxistes(mMap) i aquesta pintarà un marker al mapa de manera similar a com es

crea el marker particular. Cal mencionar que aquest mètode entra dins a la child de taxistes, i

per tant, al validar-se com a client, ha de tenir permisos a la bbdd per poder fer lectura de les

dades.

La funció pintarTaxistes(mMap) es troba en el codi 33.

public void pintarTaxistes(GoogleMap googleMap) {

mMap = googleMap;

LatLng localitzacioTaxi = new LatLng(latTaxi, lonTaxi);

if (latTaxi == 0 && lonTaxi == 0) {

} else {

if (ocupat!=false) {

markerTaxistes = mMap.addMarker(new

MarkerOptions().position(localitzacioTaxi).title("Nom :"+nom+" Mobil:

"+mobil).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFa

Page 37: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

36

ctory.HUE_RED)));

} else {

markerTaxistes = mMap.addMarker(new

MarkerOptions().position(localitzacioTaxi).title("Nom :"+nom+" Mobil:

"+mobil).icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFa

ctory.HUE_GREEN)));

}}}

Codi33: Mètode pintarTaxistes.

Aquí cal destacar que dins el marker se li pot donar informació, com ara el nom, el mòbil o

qualsevol dels atributs que disposem. S’ha fet un boolean per assignar de color vermell els taxis

ocupats i verd els lliures.

També cal mencionar que quan es fa el logout com a taxista, es posa la longitud i la latitud a 0;

per tant, si aquestes no tenen valor, no els dibuixarà el marker perquè si fos així, es tindrien

punters al punt 0,0 de la terra.

Per finalitzar aquesta classe, com que ara sí que s’està connectat, s’ha de fer un logout de la

base de dades i per tant s’assigna aquesta funcionalitat al botó de tornar enrere que tenen tots

els mòbils Android com es veu al codi 34 i tanca l’activity.

@Override

public void onBackPressed(){

FirebaseAuth.getInstance().signOut();

Context context = getApplicationContext();

Toast.makeText(context, "Desconectat", Toast.LENGTH_LONG).show();

clientm.child(clientKey).child("pos").setValue(null);

super.onBackPressed();

finish();}

Codi34: Mètode botó enderrera.

A l’apartat visual es volia representar una estètica simple, sense la necessitat d’utilitzar botons.

L’únic detall a mantenir seria el menú de dalt a la dreta així com els markers que representen

als taxistes; per tant, un mapa que ocupi tota la pantalla. Per facilitar la interacció amb el client

es van introduir botons com veiem a la figura 19.

Page 38: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

37

Figura19: Estructura interfície Client

Taxista

L’apartat del taxista és el que dona informació, per tant, aquesta activity es basa en oferir una

posició al mapa i donar a conèixer la disponibilitat del taxi. Al ser una acitivty que només

proporciona informació, no té cap mètode a destacar; simplement canvia els booleans de certs

a falsos, o al inrevés, per seguir el seu codi de colors.

La posició la tractarem amb longitud i latitud per separat, perquè sigui més fàcil a l’hora de fer

els gets des de les altres fonts que necessiten aquesta informació.

El taxista tindrà un marker emergent segons el client que el sol·liciti; per a crear aquest marker

s’ha d’assignar dues variables noves al node del taxista de la Firebase, double latClient,

lonClient. Aquestes vindran donades mitjançant un push() des de l’activity del client.

Page 39: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

38

2.5. Permisos Abans Android demanava tots els permisos a l’hora d’instal·lar l’aplicació. Això no tenia massa

sentit perquè hi ha permisos molt puntuals que l’aplicació fa servir en situacions molt concretes.

Per tant, per evitar haver de donar molts permisos a l’inici, van canviar el sistema per l’actual,

que es coneix com a sol·licitud durant l’execució, com es mostra en el codi 35. Aquest mètode

és molt més pràctic i segur per l’usuari, i la sol·licitud en el codi ha de ser just abans de requerir

el permís[9].

// Assume thisActivity is the current activity

int permissionCheck = ContextCompat.checkSelfPermission(this,

android.Manifest.permission.ACCESS_FINE_LOCATION);

if (permissionCheck == PackageManager.PERMISSION_DENIED) {

// Should we show an explanation?

if (ActivityCompat.shouldShowRequestPermissionRationale(this,

android.Manifest.permission.ACCESS_FINE_LOCATION)) {

// Show an expanation to the user *asynchronously* -- don't

block

// this thread waiting for the user's response! After the user

// sees the explanation, try again to request the permission.

} else {

// No explanation needed, we can request the permission.

ActivityCompat.requestPermissions(this,

new

String[]{Manifest.permission.ACCESS_FINE_LOCATION},

1);

// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an

// app-defined int constant. The callback method gets the

// result of the request.

}

}

Codi35: Permisos en execució.

En aquest codi també es poden afegir explicacions de perquè necessitem el permís. Per exemple,

és estrany que una aplicació et demani permís per poder llegir-te els missatges particulars. Però

tenint en compte que potser només és per validar-te automàticament el compte, tot pren més

sentit.

Aquest apartat va associat als permisos que declares en el manifest, però és l’usuari final qui

decideix si dona o no els permisos necessaris a l’aplicació.

Page 40: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

39

2.6. Diagrames de relacions

Aquí es pot veure les diferents relacions entre les classes i les comunicacions que es fan amb els

diferents serveis. En la figura 20 es mostren les relacions entre classes.

Figura 20: Esquema de activitys

En figura 21 s’observa la comunicació que hi ha durant l’execució del programa.

Figura 21: Relació entre activitys i Firebase

Page 41: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

40

Finalment es veu en la figura 23 la comunicació que es fa a l’hora de registrar un usuari.

Figura23: Comunicació amb els serveis d’autentificació.

Page 42: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

41

2.7. Diagrama de seqüència En la figura 24 es pot observar pas per pas on anem després de cada activity.

Figura 24: Diagrama seqüencial.

Page 43: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

42

3. BBDD

3.1. Organització

Com s’ha mencionat anteriorment, la base de dades escollida per aquest projecte és la que ens

ofereix Google, Firebase.

3.1.1. Pla Firebas

Aquesta base de dades està proporcionada en tres formats, segons el mètode de pagament:

gratuïta, una quantitat fixa o pagament per l’ús, tal i com se’ns mostra a la figura 25[10].

Figura25: Diferents modalitats de pagament de Firebase.

Com es pot veure a la imatge, s’ha seleccionat el pagament per ús. Això realment ho gestiona

Firebase. Inicialment es tenia l’opció gratuïta, tot i que Firebase va redistribuir el projecte a la

opció Blaze. Això no va ser problema perquè el pagament per ús inclou l’opció Spark i, si se

superés l’ús gratuït, es cobraria en funció del que s’excedís. S’ha de dir que és un punt negatiu

que no es pugui fer cent per cent responsable de l’opció que es tria, però com que l’opció Spark

dona uns mínims prou elevats per fer una aplicació de proves, es va ignorar el tema. Els

paràmetres més destacables segons les funcions escollides es mostren a la figura 26.

Page 44: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

43

Figura26: Diferents característiques segons les modalitats de Firebase.

Com es pot apreciar, el pla Spark és ideal per fer projectes de desenvolupament, on totes les

comunicacions seran per fer proves. Si es llencés aquesta aplicació al mercat, caldria canviar el

model de la base de dades. En quant a volum de dades emmagatzemades, no s’utilitza gairebé

gens l’espai que ens ofereix, ja que es guarden uns quants Strings i doubles per cada usuari

registrat. Així que, en qualsevol dels casos, el factor limitant serien les connexions simultànies.

També cal mencionar que el pla Spark inclou el sistema d’autentificació que s’utilitzarà.

Page 45: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

44

3.1.2. Utilitats que ens proporciona Firebase

Firebase és molt més que una base de dades, és una API que ens proporciona:

Authentication

Un sistema d’autentificació el qual s’utilitzarà en el sistema de logins. Aquest ens permet

seleccionar el mètode d’iniciar sessió. Com es veu en la figura 27 es pot accedir de diferents

maneres.

Figura27: Mètodes d’autentificació.

Per una qüestió de comoditat a l’hora de desenvolupar l’aplicació, es va decidir que es faria

mitjançant correu electrònic. Per habilitar o deshabilitar el mètode d’autentificació, cal fer-li

click.

Page 46: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

45

També ens permet fer una llista blanca amb els dominis autoritzats tal i com es mostra a la figura

28:

Figura 28: Opcions d’admissió de l’aplicació

Per motius de seguretat i anti-spam es pot seleccionar, des del mateix menú, que només hi hagi

un compte per correu electrònic, i/o limitar els intents de creació de compte des d’una mateixa

IP, tal com es veu a la figura 29. Aquestes dues opcions estan deshabilitades perquè només

s’utilitzava una IP que creava nous comptes durant el període de desenvolupament i no té cap

sentit activar-les al temps que es crea l’aplicació. Però en un futur s’haurien d’incloure:

Figura 29: Sistema anti spam.

Page 47: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

46

Es disposa d’un sistema de plantilles molt fàcil d’implementar on trobarem opcions com les de

la figura 30.

Figura 30: Sistema de plantilles de Firebase authenticator.

Aquestes plantilles permetran implementar sistemes com el canvi de contrasenya o email,

enviar un correu de verificació a l’hora de crear el compte, utilitzar el propi SMTP en comptes

de serveis de correu electrònic integrats, o fer la verificació de crear un compte mitjançant un

SMS.

Finalment trobem una pestanya d’ús on s’hi pot veure la gent autentificada en tot moment, en

una gràfica auto generada.

Database

Dins la part més important de la base de dades, hi tenim la Realtime Database on trobarem les

pestanyes d’opcions mostrades a la figura 31.

Figura 31: Opcions Database.

Page 48: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

47

Datos

És on hi haurà l’arbre de les dades, el qual es pot expandir fins a qualsevol node.

Reglas

Són els permisos que tindran o no els usuaris, des del moment en què encara no estan registrats,

fins que estan autentificats.

Còpia de seguretat

Es crea una còpia de seguretat diària de les dades i les regles de la base de dades. Aquesta opció

es té desactivada perquè no hi ha cap informació de rellevància, però es pot activar de manera

gratuïta, mentre es tingui espai suficient al núvol.

Ús

Dibuixa els gràfics segons l’ús que està tenint a temps real, com en la figura 32.

Figura32: Mostra del flux de dades en temps real.

Storage

Serveix per emmagatzemar les dades i recuperar els arxius generats per l’usuari, com faríem

amb una copia de seguretat.

Hosting

Implementa llocs i aplicacions web mòbils en qüestió de segons, mitjançant una xarxa de

distribució de contingut segur i global.

ML Kit

Utilitza l’aprenentatge automàtic per solucionar problemes habituals en les aplicacions.

Crashlytics

És una solució potent i lleugera sobre informe d’errors.

Performance

Serveix per rebre informació útil sobre el rendiment de l’aplicació i sobre les latències que

experimenta l’usuari.

Test Lab

Prova l’aplicació en diferents dispositius.

Page 49: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

48

Audiences

Ens fa comparatives de la base de dades amb altres èpoques de l’any o altres anys a la mateixa

època.

Latest Release

Gràfica d’usuaris que tenen l’última versió de l’aplicació.

Retention

Gràfic dels usuaris que obren l’aplicació cada dia.

StreamView

Pots veure la relació d’ús de l’aplicació en el mapa mundi.

DebugView

Informa d’errors que envien els usuaris.

Cloud Messaging

Administra les campanyes de notificacions i envia missatges per implicar als usuaris adequats,

en el moment més oportú.

AdMob

Mostra els anuncis de milions d’anunciants de Google i treu un rendiment econòmic de

l’aplicació.

Altres

Hi ha una gran llista d’utilitats com les anomenades anteriorment, però aquí només es

remarcaran les que tindrien un benefici directe i a curt termini en el cas que es llancés

l’aplicació al mercat.

Conclusió Firebase

Com es veu, disposem de molts serveis diferenciats en tres blocs:

Desenvolupament, qualitat, i analítics i de creixement.

D’aquests serveis s’utilitzaran principalment el d’Authentication i Database. Però és molt

interesant conèixer bé tots els altres, perquè són fàcilment configurables i aporten unes

possibilitats molt interesants, ja sigui el de AdMob, si es vol rendibilitzar una aplicació gratuïta;

el de DebugView, si es vol veure els diferents errors que hi ha en el codi, o el TestLab si es vol

assegurar que no hi ha incompatibilitats de l’aplicació a cap smarphone Android, per posar

alguns exemples. En línies futures seguirem parlant de totes aquestes possibilitats.

Page 50: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

49

3.1.3. Sincronització firebase-aplicació

Com s’ha vist en l’apartat del gradle, la Firebase se sincronitza a l’aplicació mitjançant una

dependència en aquest, tal i com mostrem en el codi 36.

dependencies {

implementation 'com.android.support.constraint:constraint-

layout:1.1.2'

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso:espresso-

core:2.2.2', {

exclude group: 'com.android.support', module: 'support-

annotations' })

compile 'com.android.support:appcompat-v7:25.3.1'

testCompile 'junit:junit:4.12'

compile 'com.google.firebase:firebase-core:9.0.0'

compile 'com.google.firebase:firebase-database:9.0.0'

compile 'com.google.firebase:firebase-auth:9.0.0'

implementation 'com.google.android.gms:play-services-maps:9.0.0'

compile 'com.google.android.gms:play-services-maps:9.0.0'

implementation 'com.android.support:recyclerview-v7:25.4.0'

}

Codi36: Versions de Firebase implementades.

S’ha utilitzat la versió 9.0.0 de Firebase, tant del core, com de la bbdd, com de l’authentificator,

perquè és la primera versió que s’ha trobat que no presentava cap error a l’hora de “construir”

el projecte. Es diu “construir”, o en anglès build, quan es compila el projecte i se sincronitzen

totes les seves dependències i les seves classes entre si.

Actualment les versions més noves dels complements de la Firebase van per la 16.0.1, però

també cal destacar que la documentació que hi ha per cada versió és diferent, i necessita una

versió consolidada i amb tota la informació disponible.

L’autentificació es realitza mitjançant l’email i la contrasenya.

Les referències de la base de dades estan en un arbre on hi ha dues branques: taxistes i clients,

i dins de cada branca hi ha directament els nodes amb els atributs de cada taxista o client, tal i

com es representa a la figura 33.

Figura33: Distribució dels nodes a la BBDD.

Page 51: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

50

3.2. Comunicació

Per fer el sistema d’autentificació de Firebase hi ha dos sistemes: el sistema de tokens

personalitzats, i els sistema d’email i contrasenya.

S’ha utilitzat el sistema d’email i contrasenya per simplicitat, com es mostra al codi 37[11], ja

que hi ha els mètodes ja creats per fer el registre i el login. Per fer el registre es passa un email i

una contrasenya per paràmetre, i així es crea l’usuari a la Firebase. Aquesta funció es podria

completar fàcilment amb un email de validació com ja s’ha comprovat amb totes les

funcionalitats que ens dona Firebase, però, al ser un cas de desenvolupament, s’ometrà el pas

de validar tots els correus que es registren (ja que molts correus utilitzats són inventats). També

es veu que quan es completa la part del registre i es pot autentificar, salta al mètode

onComplete, que ens crearà un nou usuari amb els seus atributs associats al formulari i enviarà

un toast dient que s’ha completat el registre correctament. Si hi ha hagut qualsevol error,

tindrem un toast informant-nos que hem tingut un problema.

private void registrarClient(String emailr,String contra){

FirebaseAuth.getInstance().createUserWithEmailAndPassword(emailr,contr

a).addOnCompleteListener(new OnCompleteListener<AuthResult>() {

@Override

public void onComplete(@NonNull Task<AuthResult> task) {

if(task.isSuccessful()){

Context context = getApplicationContext();

Toast.makeText(context, "S'ha registrat

correctament!", Toast.LENGTH_LONG).show();

Clients client = new

Clients(nom.getText().toString(),mobil.getText().toString(),

email.getText().toString(),null);

clientRef.child(FirebaseReference.CLIENT_REFERENCE).push().setValue(cl

ient);

}else{

Context context = getApplicationContext();

Toast.makeText(context, "No s'ha pogut registrat!",

Toast.LENGTH_LONG).show();

}

}

});

Codi37: Mètode registrarClient

Amb el login, la funció pre-definida és la del codi 38. En aquest cas, agafa l’email i la contrasenya

que hi ha a la pantalla i els contrasta amb els que té registrats a la base de dades. Un cop validat

fa un intent a l’activity següent.

Page 52: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

51

private void iniClient(String mail, String pass){

FirebaseAuth.getInstance().signInWithEmailAndPassword(mail,pass).addOn

CompleteListener(new OnCompleteListener<AuthResult>() {

@Override

public void onComplete(@NonNull Task<AuthResult> task) {

if(task.isSuccessful()){

Intent intent = new Intent();

intent.setClass(getApplicationContext(),

Client.class);

startActivity(intent);

Context context = getApplicationContext();

Toast.makeText(context,

"Benvingut!"+email.getText().toString(), Toast.LENGTH_LONG).show();

accesMail = email.getText().toString();

}else{

Context context = getApplicationContext();

Toast.makeText(context, "Uauari o contrassenya no

vàlida!", Toast.LENGTH_LONG).show();

}

}

});

Codi38: Mètode de validació.

Es va descartar el sistema de tokens perquè en un principi semblava més complex a l’hora de

implementar-lo; de tota manera, es va trobar una funcionalitat que no ens permet el sistema

d’autentificació actual, així que en parlarem en l’apartat de línies futures.

A l’hora de desconnectar-se de la base de dades, hem de fer un logout, si no la comunicació

seguiria oberta en segon pla fins que es tanqués manualment l’aplicació; per tant es necessita

executar la comanda següent cada cop que sortim d’una activity en la qual hi estem autentificats

en una principal:

FirebaseAuth.getInstance().signOut();

Page 53: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

52

4. Resultats

Aquí es tindrà una visita per totes les activitys resultants de l’aplicació un cop acabades totes les

funcionalitats i amb una interfície més enfocada a l’usuari final.

En la figura 34 es veu la pantalla d’inici.

Figura34: Activity Inici.

Page 54: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

53

Si es prem Client, s’accedeix a la pantalla de login/registrar-se (figura 35) com a client.

Figura35: Activity IniciClient.

Si es prem Registrar, s’accedeix a la pantalla de registrar-se (figura 36).

Figura36: Activity RegistreClient.

Page 55: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

54

Si es prem Iniciar amb les credencials correctes des de Inici client, s’inicia el programa com a

usuari (client) i s’anirà a una pantalla similar a la figura 37.

Figura37: Activity Client.

Si es prem Taxista des de Inici s’accedeix a la pantalla de login/registrar-se com a Taxista

(figura 38).

Figura38: Activity IniciTaxista.

Page 56: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

55

Si es prem Registrar, s’accedeix a la pantalla de registrar-se com a taxista (Figura 39).

Figura39: Activity RegistreTaxista

Si es prem Iniciar amb les credencials correctes des de IniciTaxista, es comença l’activitat com a

usuari (taxista), i obtindrem una pantalla similar a la figura 40.

Figura40: Activity Taxista.

Page 57: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

56

5. Conclusions i línies futures

5.1. Conclusions

5.1.1 Conclusió personal

En primer lloc m’agradaria dir que quan vaig plantejar aquesta aplicació sobre el paper, donava

per suposat tenir tots els coneixements necessaris per a dur a terme el projecte. Tenim unes

bones bases de Java, havíem cursat una assignatura d’introducció a l’Android, i havíem fet

diferents projectes en vàries assignatures amb l’ajuda del AppInventor. Agrupant aquests

coneixements, vaig suposar que seria una qüestió de temps escriure tot el codi necessari i que

trobaria prou documentació i aquesta no em costaria de trobar.

Un cop iniciat el projecte i feta la part més senzilla, que és la de navegar per dins l’aplicació, van

sorgir alguns problemes i em vaig adonar que fer una aplicació mòbil requereix d’una divisió de

tasques i d’un equip per dur-les a terme.

Per assolir els objectius vaig definir i desglossar el projecte en tasques. Dins aquests objectius

he intentat avançar tant com he pogut, malgrat que hi hagi coses que no he aconseguit acabar-

les del tot, com veurem en les línies futures.

La documentació no és tan fàcil de trobar com sembla, el volum d’aquesta és molt gran, però al

ser un tema que avança tan ràpid, només la documentació dels llocs oficials és fiable, ja que en

altres webs, probablement estigui desactualitzada. Això té un gran inconvenient, pots trobar-te

amb gent que ha tingut els mateixos problemes que tu però com que està en una altra versió de

Android o Firebase els seus coneixements i les seves solucions no et serveixin per res. I al mateix

temps, els llocs de documentació oficial manquen d’exemples per poder tenir les teves pròpies

referències.

Una de les coses que em va passar en relació al tema de com avança la tecnologia, és que vaig

començar el programa en Android 7.0 i a mig projecte es va actualitzar a 8.0. Òbviament tots els

avenços que guanyen els Androids en cada versió estan majoritàriament en facilitar les opcions

de desenvolupament. Però a vegades et toca canviar parts del teu codi per posar-los al dia,

perquè també es modifiquen parts del funcionament de les aplicacions perquè l’usuari tingui

una millor experiència.

Exposada la part de programació, és fàcil veure que per tenir una aplicació funcional i sòlida i

que aquesta estigui al dia, requereix d’ una bona divisió de tasques, un bon gràfic UML i un

equip de persones treballant en paral·lel en les diferents parts de l’aplicació.

Page 58: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

57

5.1.2 Retrospectiva dels objectius plantejats i assolits.

Fent una repàs general de l’aplicació desenvolupada, es poden enumerar diferents objectius

bàsics per al funcionament d’aquesta, els quals s’han complert.

• S’ha dissenyat i creat l’estructura de classes de l’aplicació per un correcte ús tant en la

navegació com a l’hora d’utilitzar-la.

• S’ha dissenyat i creat l’estructura de la base de dades amb les seves respectives referències.

• S’ha completat amb èxit la integració de la base de dades al projecte.

• S’ha aconseguit una comunicació a temps real de l’aplicació al núvol on cada canvi que hi

hagi a la bbdd es notificarà a l’aplicació.

• S’ha implementat un sistema funcional de registres i logins on els usuaris podran crear el

seu perfil a la base de dades i posteriorment poder-se validar a l’aplicació.

• S’ha aconseguit una comunicació directa entre clients i taxistes.

5.2. Línies futures

M’agradaria canviar el sistema de login de “email més contrasenya” a “tokens personalitzats”

perquè és molt més fàcil referir-se a usuaris determinats amb els tokens, ja que amb el sistema

d’email has de buscar cada vegada la clau de l’usuari que està dins el node, fent comparacions

amb l’email. Amb el sistema de tokens, busques la ID de l’usuari directament.

En un inici, vaig plantejar d’una manera diferent la comunicació entre el client i el taxista de

forma que l’usuari, a l’hora de sol·licitar taxi, també li enviés la ruta d’inici a fi.

Complementàriament amb l’apartat anterior, també seria interessant, en una futura versió de

l’APP, integrar la funcionalitat de pagament mitjançant l’NFC del mòbil i completar aquesta

funcionalitat de forma que l’usuari pogués informar-se del preu segons el temps que retorna

l’API de Google maps i l’hora del dia, i així tingués un preu preestablert abans de sol·licitar la

ruta.

Per acabar m’agradaria acabar de polir les regles de la base de dades. Donar permisos a una

base de dades oberta als usuaris és complexa i s’ha de controlar qui pot accedir i/o modificar en

cada lloc; per tant, és un tema obert que s’hauria de regular com més acuradament millor.

Page 59: Oriol Mèlich Pons Aplicació Android Appxi TREBALL DE FI DE ...deeea.urv.cat/public/PROPOSTES/pub/pdf/2584pub.pdf2 1. Introducció 1.1. App Taxi Tot comença amb la necessitat persónal

58

6. Referències

[1] https://es.mytaxi.com/index.html

[2] https://firebase.google.com/?hl=es-419

[3] https://developer.android.com/studio/

[4] https://developers.google.com/places/web-service/get-api-key

[5] https://firebase.google.com/docs/database/android/start/?hl=es-419

[6] https://es.stackoverflow.com/

[7] https://firebase.google.com/docs/database/admin/retrieve-data?hl=es-419

[8]https://developers.google.com/android/reference/com/google/android/gms/maps/OnMap

ReadyCallback

[9] https://developer.android.com/training/permissions/requesting?hl=es-419

[10] https://firebase.google.com/pricing/?hl=es-419

[11] https://www.youtube.com/watch?v=C1GeJqu5Nz4