Bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 FOL
Totes les UFs del modul
MP13 EIE
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 FOL
Totes les UFs del modul
MP12 EIE
Totes les UFs del modul
MP13 Projecte
Totes les UFs del modul
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
M09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 FOL
Totes les UFs del modul
MP10 EiE
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
android

Android

Android és un sistema operatiu per a dispositius mòbils impulsat per Google. Està basat en Linux, però conté també mòduls privatius.

android.jpeg

Una bona referència teòrica son els continguts de MP08 de DAM del IOC.

Desenvolupament Android

Hi ha diverses opcions per desenvolupar per a Android, fem un breu resum de les més habituals:

  • Java sol ser la opció més comuna per desenvolupar apps per a Android. Es compilen sobre un processador virtual corresponent a la JVM (Java Virtual Machine). És el que s'anomena Android Runtime.
  • Cordova (abans PhoneGap) ens permet treballar amb HTML, CSS i JavaScript per construir les aplicacions de forma més “amigable” que amb Java. Cordova funciona sobre el Android Runtime de Java, pel que és necessari comptar amb aquestes eines també.
  • Altres: Es pot treballar també amb C++ (codi nadiu amb el què es realitza el nucli i drivers), C# i el més recent, Kotlin, molt similar a Java però també més amigable.

Eines de desenvolupament per a Android:

  • Android Studio que no deixa de ser el mateix IntelliJ Idea amb les llibreries per a Android incorporades. Actualment és la eina oficial recomanada per Google.
  • IntelliJ Idea és una plataforma de desenvolupament de la companyia JetBrains.
  • Eclipse : el popular IDE de codi obert havia estat prèviament la plataforma oficial recomanada per Google, fins que van decidir canviar a Android Studio.
  • Visual Studio permet treballar amb Cplusplus i C#
  • Xamarin permet treballar en C# i compilar de forma multiplataforma per a Android i iOS

Alguns aspectes inicials

La programació per a Android utilitza alguns recursos molt habituals com l'aniuament de classes i la sobreescriptura de mètodes en el moment de la instanciació.

Fes-li un cop d'ull a aquest codi d'exemple per clarificar certs aspectes de la programació Java aplicada a Android, abans d'aprofundir en la programació Android.

Tornem a referenciar-nos als apunts de desenvolupament per a Android de la IOC.

En particular, para atenció als conceptes següents:

  • Activity, Fragment, Service
  • Callback
  • Layout
  • Arxiu resources a.k.a. “R”
  • Cicle de vida d'una activitat
  • Intent

Cicle de vida d'una Android Activity. Font: apunts IOC.

Primeres passes

  1. Mira els apartats de més amunt i l'article Java per disposar de la instal·lació del IDE i llibreries adequades.
  2. Es recomana utilitzar algun tipus de sistema de control de versions. El més popular és Git i la web www.github.com . Es pot fer les operacions més comunes al menú VCS de IntelliJ IDEA.
  3. Si ja has llegit els apunts per aclarir els conceptes previs, podem passar a l'acció. Crea una aplicació amb una empty activity des del menú File→New→Project→Android
  4. Afegeix un botó (Button). Busca els arxius de recursos R.layout (carpeta res→layout i arxiu activity_main.xml) per afegir-ho gràficament (millor no complicar-nos la vida abans d'hora ;).
  5. Afegeix un OnButtonClickListener al mètode onCreate de la MainActivity.java. En principi, el botó no fa res quan el premem. Aquest listener ens permetrà captar l'event OnClick i fer alguna cosa. A la documentació del mateix Button trobaràs un exemple de com fer-ho.
  6. Afegeix un Toast. El primer que podem fer per comprovar que l'event OnClick s'està processant és construir un Toast, que son els missatges que apareixen en un globus temporalment sobre la app, a la part inferior de la pantalla habitualment. La manera més fàcil de crear-lo és amb Toast.makeText, i després fer-li un show a l'objecte perquè es visualitzi.

Una aplicació complerta

Requeriments joc "endevina el número"

  1. La app ens oferirà un casella d'entrada de text i un botó.
  2. La app crearà un número aleatori entre 1 i 100 que el jugador haurà d'endevinar.
  3. Cada cop que l'usuari fa una temptativa es compta un nou intent.
  4. Quan l'usuari endevina del número que la app ha “pensat”, s'acaba la partida.
  5. La puntuació resultant és el nombre d'intents que ha fet l'usuari fins a endevinar el número. Quan més petita és, millor.
  6. La app demanarà el nom a l'usuari per posar-ho a la taula de rècords. L'usuari podrà posar el seu nom o desestimar-ho.
  7. La app torna a “pensar” un nou número aleatori i comença nova partida.

Aplicació principal (joc)

  1. Crea una nova aplicació amb una sola activity (empty activity).
  2. Ves al layout i crea la casella d'entrada per al número. Es tracta d'un objecte TextEdit, però volem restringir-ho perquè només ens deixi entrar nombres i no lletres. Entre els objectes disponibles al IDE hi ha un de predefinit que ja ens ho facilita.
  3. Crea un botó i un listener perquè l'usuari validi l'entrada del número. Prova que funciona amb un Toast, per exemple.
  4. Investiga com crear un nombre aleatori en Java. Crea un al mètode onCreate de l'Activity i emmagatzema-ho en una propietat de l'objecte per tenir-ho disponible quan calgui.
  5. Anem al codi principal del joc, que estarà principalment al onClick del listener. Quan l'usuari entri un número li mostrem un Toast dient-li si el nombre que busca és major o menor.
  6. A més, per facilitar el joc a l'usuari, esborrem el número del EditText que l'usuari fa un intent.
  7. Es pot millorar la jugabilitat si implementem que el joc detecti la tecla Enter del teclat de pantalla.
    • S'implementa millor amb un OnEditorActionListener ja que el OnClickListener amaga el teclar al prèmer ENTER.
    • Us deixo igualment la doc de OnKeyListener sobre el EditText (OJU! no al button o altres llocs!)
      • Encara que detecteu correctament el Enter, us passarà que trobareu un ACTION_UP i un ACTION_DOWN, pel que la callback es cridarà dos cops. Filtreu aquests dos esdeveniments i avalueu l'entrada de l'usuari només en un dels dos (preferentment ACTION_DOWN). També convé recuperar el focus dintre del EditText perquè l'usuari no hagi de clicar de nou el widget cada cop que fa un intent.

Rècords "Hall Of Fame"

Per a la taula de rècords crearem una nova Activity i la obrirem amb un objecte Intent. L'objecte més adient per mostrar una llista de rècords seria una RecyclerView (la versió actualitzada de ListView) però té força complexitat utilitzar-la. Farem 3 versions amb dificultat incremental per anar sofisticant la nostra app i anar veient els diferents recursos que podem emprar:

  1. Versió més simple amb una TextView
  2. Versió millorada amb un TableLayout
  3. Versió pro amb RecyclerView

Abans, però, caldrà crear una nova Activity per poder posar-hi el rànking:

  1. Crear nova Activity amb el seu layout associat (arxiu XML): File→New→Android Activity→Empty Activity
  2. Afegim Intent: aquest objecte ens serveix per posar en marxa una altra activity. Així podrem passar de la partida a la taula de rècords. Caldrà que l'activem quan acabem la partida, o bé podem afegir un botó nou per visualitzar la taula de rècords. Aquest exemple per obrir una nova activity t'ajudarà.
  3. Per tal que puguem afegir una nova entrada a la taula de rècrods caldrà que el MainActivity passi el paràmetre del nº d'intents que el jugador ha realitzat. Per passar paràmetres examina el mètode putExtra() de l'objecte Intent.
  4. Diàlegs (Dialogs): el primer que farà la nova activitat és preguntar l'usuari pel seu nom per posar el rècord (nº d'intents) a la taula.
    1. A la documentació oficial hi ha diversos Dialogs prefabricats disponibles. Però nosaltres necessitem fer-ne un de personalitzat que ens demani el nom i prou. Aneu a la secció de la documentació dels diàlegs personalitzats.
    2. Caldrà que creis un layout xml per definir el camp de text i els botons del vostre quadre de diàleg.
    3. Aquesta pregunta de stackoverflow pot ajudar-te a crear un diàleg personalitzat per preguntar el nom.
    4. Versió alternativa de Dialog per crear-lo programàticament, sense xml.

Model de dades

Abans de mostrar la taula de rècords, cal que tinguem clar quin serà el nostre model de dades segons el paradigma MVC (Model-Vista-Controlador). Haurem de guardar una llista amb, al menys, un parell de valors en cada posició (nom, número d'intents i potser més tard el temps emprat).

La idea és que les dades dels rècords han de ser completament desacoblades de la interfície gràfica (model MVC). És una bona pràctica, però a més, no ens queda mes remei, ja que les diferents activities s'esborren: la informació gràfica i els widgets són efímers i no podem fiar-nos de que estiguin sempre allà.

Tenim diverses alternatives per guardar les dades.

  • Array estàtic : completament desaconsellat ja que no sabem el nombre de rècords que emmagatzemarem, i els anirem incrementant a cada partida.
  • Map (diccionari) : són molt eficients, però en el nostre cas en ofereix diversos problemes. Un, que un diccionari no està ordenat, i nosaltres haurem de mostrar una llista ordenada (rànking). L'altre, que al guardar amb la clau del nom de l'usuari, quan jugui una 2a partida, esborrarà el valor anterior, i això no ens interessa.
  • ArrayList : la millor opció ja que es pot ordenar per diferents criteris (intents, temps, nom) i és dinàmic.

Depenent de si volem permetre entrar el mateix nom 2 cops podrem utilitzar un diccionari (map) o bé una llista. Aquest objecte ha d'estar completament desacoblat de la interfície gràfica, i hauria de ser utilitzable en qualsevol altre entorn.

Variable estàtica

Les dades del rànking les haurem de ubicar com a variable de classe dins d'una de les activities. Això no garateix que les dades es mantinguin, ja que a l'obrir una 2a activity, la primera es tanca i s'esborra. Per garantir que tenim les dades sempre disponibles haurem de fer l'atribut static:

class RecordActivity extends AppCompatActivity {
    static ArrayList<Record> records = new ArrayList<Record>();

Versió TextView

A la nova Activity només en caldrà una TextView on mostrar els rècords i un botó per tornar a la MainActivity.

La idea és ben simple: en el onCreate() de la nostra RecordActivity iterarem per la llista de rècords que hem elaborat, i farem un String que mostrarem dins de la TextView.

Pot semblar un tant ineficient, però és així com funcionen les activities, cada cop que canviem a una de nova, les altres s'eliminen (per estalviar memòria) i llavors cal recrear tota la llista i tots els widgets.

Versió amb TableLayout

Fins ara hem creat layouts estàtics, que mostren dades dinàmiques, però on el widgets són fixes.

En aquesta versió el repte està en utilitzar TextViews dinàmics segons el nombre de rècords. Aquests els col·locarem en un TableLayout.

Haurem de crear un nombre de files dinàmic i, a cada fila, posar 3 TextView (nom, intents i temps). Per tant, aquests TextView es crearan dinàmicament, de forma programàtica.

Per dur-ho a terme, teniu aquest exemple d'un post de stackoverflow per afegir TextView programàticament.

Versió ListView

  1. Creem View + Adapter: seguint amb el paradigma MVC, ara haurem de crear la vista i un nou element que es diu Adapter. Aquest objecte és útil per gestionar llistes molt llargues que potser no caben a la RAM (mes limitada en un disp. mòbil). Aquest tutorial de ''ListView'' amb ''ArrayAdapter'' et pot ser d'utilitat per entendre-ho i posar-ho en marxa.
    1. Per a cada element (item) de la ListView es necessita un layout personalitzat. El pots crear tu mateix, o simplement adoptar uns layouts prefabricats per als items. Al arxiu de recursos android.R.layout trobaràs alguns com per exemple android.R.layout.simple_list_item_1 que et pot estalviar feina per als casos més habituals.
    2. En aquest exemple de ArrayAdapter en canvi, hem creat un layout personalitzat per a la nostra taula.
  2. Finalment, cal que la llista de rècords estigui ordenada. A la part “top” han d'aparèixer les partides amb menys intents.

Versió RecyclerView

La clàssica ListView ha quedat obsoleta i ara s'utilitza de forma genèrica la RecyclerView, que pot agafar diferents layouts i disposicions.

Malauradament és més complicada d'utilitzar que la ListView, i el mínim exemple per crear el Adapter resulta més complex que el ArrayAdapter que feiem servir.

Igualment us deixo les referències per si els més agosarats voleu utilitzar-la:

  1. Per si de cas, us deixo aquest altre exemple on s'han esforçat a fer un RecyclerAdapter més simple (igualment no deixa de ser força més llarg que el de la ListView).

Persistència

Segons Android Data Storage tenim diversos tipus d'emmagatzematge:

  1. Preferències compartides: tipus simples en forma clau-valor.
  2. Emmagatzematge Intern: es guarda arxiu en la memòria interna del dispositiu, no es pot compartir entre aplicacions per seguretat.
  3. Emmagatzematge “Extern” o Compartit: SD card o memòria interna compartida entre aplicacions com la carpeta DCIM on hi ha el carret de fotos.
  4. BBDD SQLite
  5. Connexió de xarxa (guardar en un servidor d'internet)

El més adequat per a nosaltres és l'emmagatzematge intern. La llibreria bàsica que s'explica en l'anterior link treballa amb arxius binaris.

És pràctic utilitzar arxius XML per separar els camps de forma llegible. Hi ha diverses llibreries per llegir XML amb Java:

  1. XmlSerializer és una opció.
  2. Aquest article en castellà explica força bé com utilitzar DOM parser.
  3. Potser et pot aclarir tb aquest post de DOM parser

Modes Portrait i Landscape

Com sabeu, la pantalla del mòbil pot estar en mode Portrait (vertical) o Landscape (apaïsat). Quan una app canvia d'un estat a l'altre és com si reiniciéssim la app de nou, i cal recrear tota l'estructura dels objectes que tenim en memòria.

Així, al passar d'un mode a l'altre, la nostra Activity es destruirà (cridant abans al mètode onSaveInstanceState) i es tornarà a crear (cridant onRestoreInstanceState). Aquests dos mètodes ens permetran guardar i restaurar les dades en memòria, per tal que sembli que l'aplicació manté el seu funcionament amb continuïtat.

Crida a funcions de save/restore quan l'app canvia d'estat.

Android ens dona aquesta eina onSaveInstanceState que ens facilita guardar les dades que ens calgui de la nostra app en un Bundle (una senzilla BD local persistent tipus key-value).

Aquí podeu veure un exemple d'ús d'aquests mètodes, tot i que cal tenir en compte que les dades que tenim són ArrayList, i que no és un tipus primitiu (com int, String, etc.). Caldrà que els nostres objectes implementin Serializable i utilitzar Bundle.getSerializable i Bundle.putSerializable.

Alternativa: utilitzar ViewModel

Els ViewModel és una manera de facilitar aquesta gestió de dades quan es destrueix la View al passar entre diferents modes de visió portrait/landscape. Enlloc de manualment guardar les dades amb el mètode onSaveInstanceState tenim l'alternativa de les ViewModel. Aquests són objectes que estan pensats per sobreviure al canvi d'estat, i són independents de l'Activity que les ha generat.

La idea principal és separar les dades pures o model de la interfície d'usuari. Així, es podrà destruir la interfície, i les dades (descarregades de serveis d'internet, lectura d'arxius, captura de sensors, etc.) seguiran allà.

Pots llegir la documentació oficial de ModelView per més informació i exemples de com utilitzar-ho.

La idea és que el Fragment o Activity demana una instància del ViewModel al ViewModelProvider, que és l'objecte que gestiona la persistència. Després aplica un Observer que facilitarà que quan hi hagi un canvi en el model, es cridi una callback per actualitzar la view.

Fragments

Hi ha moltes aplicacions que requereixen diverses “pestanyes” amb diferents funcions, cadascuna amb el seu pertinent layout. La forma típica de treballar d'Android és utilitzar les classes Fragment i FragmentActivity. Un Fragment representa una porció de la interfície que gestiona una FragmentActivity.

Aquest exemple bàsic de la documentació oficial es pot veure el codi en aquest Exemple de Fragment. Conté:

  1. Una DetailsActivity, imprescindible una Activity contenidora i que disposa del handlers adequats, particularment el FragmentManager.
  2. Un ListFragment (esquerra) per tenir la llista de pestanyes o sub-views i seleccionar-los.
  3. Un DetailsFragment que canvia la view de la dreta quan es clica a la ListFragment.

Els Fragment es comporten similarment a les Activity, i tenen els mateixos mètodes onCreate, on Stop i alguns més propis del Fragment, com podem veure en aquesta imatge del seu lifecycle:

Cicle de vida d'un Fragment i la seva Activity contenidora.

Com es pot veure al fragment lifecycle hi ha algunes crides més que impliquen les views

Potser la manera més pràctica de començar és utilitzar una plantilla de les que ens proporciona Android Studio al principi del projecte, i modificar-la adientment. Tingueu en compte que si ho feu així, la plantilla també conté els objectes ViewModel descrits més amunt quan hem parlat dels modes landscape i portrait.

Captura d'imatges

Aquest article de la pàgina oficial d'Android ens explica com capturar imatges amb la pròpia aplicació de la càmera del mòbil. El tutorial oficial explica 2 aproximacions diferents. Ambdues utilitzen la app Camera del sistema operatiu. Així, no farem la foto dins la pròpia aplicació, sinó que la farà la Càmera (amb un Intent + setActivityForResult) i després haurem de gestionar el resultat (amb una callback). La diferència entre els dos diferents mètodes és la següent:

  1. Miniatura: Si cridem la càmera sense cap extra ens retornarà un Bitmap amb el thumbnail (miniatura) de la foto. Té poca resolució, però és força senzill d'implementar i per moltes aplicacions ens resulta suficient. Addicionalment al què hi ha al tutorial, podeu afegir l'enregistrament de la foto en un arxiu de l'espai de la nostra pròpia app mitjançant el mètode Bitmap.compress
  2. Full resolution: Si la volem a full caldrà donar-li un espai a la app Camera on guardar l'arxiu. Això ens complica el codi. Per poder fer això caldrà generar un FileProvider dins la nostra app (arxiu AndroidManifest.iml). Un cop cridem la app Camera ella mateixa guardarà l'arxiu on li haguem dit (sigui a l'espai de la nostra app, o al carret de fotos (DCIM) compartit del sistema operatiu). OJU! Quan iniciem la càmera i li demanem que ens guardi la foto en full resolution no rebrem el thumbnail en la callback de tornada (amb el què el codi previ probablement petarà).

Guia pràctica:

  1. Crea una nova aplicació per provar la captura d'imatges.
  2. Crea-hi un layout senzill amb una ImageView i un botó per capturar imatges.
  3. Afegeix un OnClickListener al botó que engegui un Intent per obrir la aplicació càmera.
  4. Captura la imatge, tal i com explica la documentació, i assigna el thumbnail a la ImageView.
  5. Pots guardar la foto:
    1. a la carpeta DCIM del mòbil, tal i com explica el tutorial oficial. Per poder accedir a aquesta carpeta cal demanar permisos i és una mica liós.
    2. guardar el tumbnail en l'espai intern de la app.
      1. Crea un File a la carpeta local de la app: la carpeta local la pots aconseguir amb Context.getDataDir.
      2. Crea un FileOutputStream associat al File
      3. Volca el contingut del thumbnail amb Bitmap.compress
      4. Fes també un botó per recuperar la imatge guardada i mostrar-la a la ImageView. La forma més simple és amb la funció ImageView.setImageURI i assignar-li la Uri de l'arxiu.

Continuant amb l'aplicació i la taula de rècords:

  1. Després d'entrar el nom per enregistrar un rècord, a més, engegarem la càmera.
  2. Capturem la imatge i la enregistrem a disc amb un nom aleatori o seqüencial.
  3. Assignem la imatge al nou item de rècord.
  4. Modifiquem el layout del ArrayAdapter per afegir-hi una ImageView al rècord (on havíem de tenir prèviament el nom i els intents).
  5. Modifiquem adequadament el adapter per aconseguir que ens agafi la imatge de disc i la assigni a la ListView

Més coses interessants

Android i RMI

Un recurs molt habitual d'utilitzar per comunicació entre dispositius és la llibreria RMI de Java o Remote Method Invocation. Malauradament, aquesta llibreria molt estàndard en altres aplicacions Java no està suportada en Android.

Una possible alternativa és utilitzar LipeRMI, una implementació lleugera de RMI que, malgrat fa anys que no té actualitzacions, funciona per a Android (a data d'Octubre de 2020). Podeu veure un exemple de com utilitzar-la en aquest thread de (com no) Stackoverflow.

Importar LipeRMI a Android Studio

Per importar LipeRMI a Android Studio, descarregueu el jar de LipeRMI i feu les següents passes:

Aneu a:

File -> Project Structure -> Modules -> + -> Import .JAR/.AAR Package

Trieu el jar del vostre filesystem i feu Finish i Apply.

Aneu a:

File -> Project Structure -> Dependencies -> app -> + -> Module Dependency -> Marcar LipeRMI

I finalitzeu amb OK i Apply.

Seguiu l'exemple de Stackoverflow per implementar el codi en client (Android) i servidor (podeu fer servir Eclipse o compilar-ho directament amb javac).

Si us dona problemes per importar la llibreria de lipeRMI, reviseu el primer pas on fem Import .JAR/.AAR Package i assegureu-vos que enlloc de lipermi-0.4 la llibreria l'anomeneu lipermi.

Text to Speech

Una funció interessant per a les nostres apps és fer-la parlar. Per fer-ho, podeu gravar vosaltres els sons, però és molt interessant utilitzar el sintetitzador de veu d'Android, amb la llibreria Text-to-Speech. Així podem fer-li parlar qualsevol cosa, sense haver d'enregistrar abans. Val a dir que en els idiomes més parlats (anglès, castellà, francès, xinès) funciona molt bé, però en català el sintetitzador és de poca qualitat.

  1. Exemple per canviar de llengua (Locale) per a llengües que no estan als objectes principals.

Flexbox Layout

A part dels tipus de layout treballats durant el curs (ConstrainLayout, LinealLayout, TableLayout) hi ha aquest molt particular que ens pot ser interessant en determinats projectes per imitar el comportament del conegut FLEXBOX de CSS.

android.txt · Darrera modificació: 2020/11/06 20:34 per enric_mieza_sanchez