bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


android_imatges

Diferències

Ací es mostren les diferències entre la revisió seleccionada i la versió actual de la pàgina.

Enllaç a la visualització de la comparació

Ambdós costats versió prèvia Revisió prèvia
Següent revisió
Revisió prèvia
Següent revisió Ambdós costats nova versio
android_imatges [2021/10/20 10:30]
enrique_mieza_sanchez [Exercici: captura bàsica d'imatge amb miniatura]
android_imatges [2022/12/12 15:56]
enric_mieza_sanchez [Us de la càmera]
Línia 8: Línia 8:
   * Article [[Android]] a bytes.cat   * Article [[Android]] a bytes.cat
   * [[https://ioc.xtec.cat/materials/FP/Recursos/fp_dam_m08_/web/fp_dam_m08_htmlindex/WebContent/u3/a2/continguts.html|Apunts de MP08 UF2 de DAM a l'IOC]].   * [[https://ioc.xtec.cat/materials/FP/Recursos/fp_dam_m08_/web/fp_dam_m08_htmlindex/WebContent/u3/a2/continguts.html|Apunts de MP08 UF2 de DAM a l'IOC]].
 +  * [[https://developer.android.com/training/camera/photobasics#java|Article "photo basics"]] oficial d'Android. Cal llegir-lo en anglès perquè la versió en castellà conté errors.
 +  * [[https://developer.android.com/studio/debug/device-file-explorer|Device File Explorer]] de l'Android Studio.
  
  
Línia 13: Línia 15:
  
 ===== Us de la càmera ===== ===== Us de la càmera =====
-Aquest [[https://developer.android.com/training/camera/photobasics#java|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.+Aquest [[https://developer.android.com/training/camerax/take-photo#java|article CameraX de la pàgina oficial d'Android]] ens explica com capturar imatges amb la pròpia aplicació de la càmera del mòbil.
  
-<WRAP important+<WRAP info
-ULL! Mira el [[https://developer.android.com/training/camera/photobasics#java|tutorial "photobasics" d'Android]] **en anglès**La versió en castellà conté errors.+ULL! El [[https://developer.android.com/training/camera-deprecated/photobasics|codi anterior ha quedat obsolet (deprecated)]]. Si has de fer servir el mètode antic, tingues en compte que la pàgina en anglès funcionava bé, però la traducció a castellà tenia errors. Canvia l'idioma manualment a dalt a l'esquerra.
  
-Hauràs de canviar manualment l'idioma a dalt a la dreta.+El tutorial utilitza 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//).
 </WRAP> </WRAP>
  
-El tutorial utilitza la //app// Camera del sistema operatiuAixí, 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//).+<WRAP important> 
 +Segueix aquest [[https://medium.com/swlh/introduction-to-androids-camerax-with-java-ca384c522c5|tutorial a Medium.com de CameraX]] per fer una app mínima que accedeixi a la càmera i la mostri en un ''SurfaceView''
 +</WRAP> 
 + 
 + 
 +El [[https://developer.android.com/training/camerax/take-photo#java|tutorial oficial de CameraX d'Android]] està aquí però no acaba sent fàcil de seguir, particularment en Java (potser en Kotlin es deixa més).
  
 {{ android-camera-intent.jpg?direct&400 }} {{ android-camera-intent.jpg?direct&400 }}
Línia 53: Línia 60:
 Persistència del //thumbnail//: Persistència del //thumbnail//:
   * Amb el ''Bitmap'' que ens retorna l'aplicació, enregistra la foto al sistema d'arxius.   * Amb el ''Bitmap'' que ens retorna l'aplicació, enregistra la foto al sistema d'arxius.
-    * Crea un ''File'' sobre l'àrea interna d'emmagatzemament (llegeix mes avall).+    * Crea un ''File'' sobre l'àrea interna d'emmagatzemament amb [[https://developer.android.com/reference/android/content/Context#getFilesDir()|Context.getFilesDir()]] (llegeix mes avall).
     * Obre un ''FileOutputStream'' sobre el fitxer.     * Obre un ''FileOutputStream'' sobre el fitxer.
     * Utilitza ''Bitmap.compress'' per volcar el contingut del //thumbnail// sobre el fitxer.     * Utilitza ''Bitmap.compress'' per volcar el contingut del //thumbnail// sobre el fitxer.
-  * Utilitza el **Android File Explorer** per visualitzar si el teu arxiu s'ha creat correctament (recorda prémer "actualitzar" abans de comprovar-ho).+  * Utilitza el [[https://developer.android.com/studio/debug/device-file-explorer|Device File Explorer]] per visualitzar si el teu arxiu s'ha creat correctament (recorda prémer "actualitzar" abans de comprovar-ho).
   * Recupera la imatge sobre el ''ImageView'' quan iniciem l'aplicació de nou.   * Recupera la imatge sobre el ''ImageView'' quan iniciem l'aplicació de nou.
     * La forma més simple és amb la funció ''ImageView.setImageURI'' i assignar-li la Uri de l'arxiu.     * La forma més simple és amb la funció ''ImageView.setImageURI'' i assignar-li la Uri de l'arxiu.
Línia 63: Línia 70:
 \\ \\
  
-===== Persistència ===== +===== Emmagatzematge Android ====== 
-Segons [[https://developer.android.com/guide/topics/data/data-storage?hl=es-419|Android Data Storage]] tenim diversos tipus d'emmagatzematge+<WRAP tip> 
-  - **Preferències compartides**: tipus simples en forma clau-valor. +Hi ha diverses formes d'emmagatzematge a AndroidÉs un tema sensible per la seguretat de les dades.
-  - **Emmagatzematge Intern**: es guarda arxiu en la memòria interna del dispositiu, no es pot compartir entre aplicacions per seguretat+
-    * Els arxius es guarden a ''/data/data/com.myorg.myapp/files''+
-  - **Emmagatzematge "Extern" o Compartit**: SD card o memòria interna compartida entre aplicacions com la carpeta DCIM on hi ha el carret de fotos. +
-    * Els arxius es guarden a ''/data/media/0/Android/data/com.myorg.myapp/files''+
-  - **BBDD SQLite** +
-  - Connexió de xarxa (guardar en un servidor d'internet)+
  
 +Llegeix [[Android persistència]] per saber més.
 +</WRAP>
 \\ \\
  
-===== Emmagatzematge intern ===== +===== Exercici: fotos full-size a l'àrea externa =====
-És el més segur ja que no es pot compartir entre aplicacions. La seguretat es manté sempre i quan no es faci //root// el dispositiu. +
- +
-L'[[https://developer.android.com/reference/android/content/Context|objecte Context]] (del qual deriva ''Application'') ens proveeix algunes funcions per tractar els fitxers: +
-  * [[https://developer.android.com/reference/android/content/Context#openFileOutput(java.lang.String,%20int)|Context.fileOutputStream]] ens permet obrir un //stream// d'escriptura a l'espai privat de l'aplicació. +
-  * [[https://developer.android.com/reference/android/content/Context#getFilesDir()|Context.getFilesDir()]] ens dona el ''path'' de la carpeta privada de l'aplicació on emmagatzemarem els fitxer interns. Amb aquest ''File'' com a path podem utilitzar les funcions habituals de Java per tractament d'arxius.+
  
 <WRAP todo> <WRAP todo>
-App de testeig per visualitzar els arxius i les carpetes d'emmagatzematge intern. +Seguirem el [[https://developer.android.com/training/camera/photobasics#TaskPath|tutorial oficial de fotos d'Android a partir de la secció "Save full-size photo"]].
-  * Crea una nova aplicació amb un botó. +
-  * Utilitza la funció [[https://developer.android.com/reference/android/content/Context#openFileOutput(java.lang.String,%20int)|Context.fileOutputStream()]] per enregistrar un arxiu amb el nom "dades.txt"+
-  * Escriu-hi una línia de text. +
-  * Controla que tingui el seu ''try...catch'' i mostra un missatge d'error per si falla alguna cosa. +
-  * Utilitza el **Device File Manager** d'Android Studio per visualitzar l'arxiu que has generat. Pensa ACTUALTIZAR el File Manager per trobar el teu arxiu. +
-</WRAP>+
  
-\\+Modifica l'aplicació de l'exercici anterior per aconseguir guardar la foto a //full-size//:
  
-===== Emmagatzematge compartit ===== +  * Fes un //commit// amb //tag// (per després fer una //release//al [[Git]] abans de continuar
-Si utilitzem aquest espai, guardarem l'arxiu en una carpeta compartida on les diferents aplicacions poden intercanviar informació, com en el carret de fotos (DCIMo la carpeta de descàrregues (Downloads). +  * Per activar que la càmera faci l'enregistrament //full-size// caldrà que adjuntem la ''Uri'' del fitxer al ''Intent'' mitjançant un ''putExtra'' (fixa't en l'exemple)
- +  Caldrà utilitzar ''FileProvider'' per autoritzar a l'//app// Camera a utilitzar els arxius de la nostra //app// (sigui a l'àrea externa o interna). 
-Dins de l'emmagatzematge compartit hi ha 2 zones: +  * De moment no facis un nom d'arxiu dinàmic (amb data i hora, com es fa a l'exemple)Un nom fixe ens serveix per aquesta mini-app
-  * **Zona de l'aplicació** +  * Per tal que el codi anterior no peti caldrà que comentis o eliminis el què tens a ''onActivityResult'' ja que ja no ens arribarà cap //thumbnail// o miniatura. 
-    * Ubicat a ''/media/0/Android/data/com.myorg/myapp''+  * Visualitza el resultat de la fotoQuin problema tenim?
-    * Dins d'aquesta hi ha també un seguit de carpetes específiques per a Pictures, Music, etc. +
-    * Podem accedir a l'arrel i crear les carpetes que creiem necessàries. +
-    * No requereix permisos d'accés. +
-  * **Zona compartida de ''MediaStore''** +
-    * Ubicat a ''/media/0/''. +
-    * Hi ha carpetes específiques (fixes) com DCIM, Documents, Downloads, etc. +
-    * S'hi accedeix mitjançant l'objecte [[https://developer.android.com/training/data-storage/shared/media|MediaStore]] però la seva aproximació és molt diferent de la que estem treballant aquí ara+
-    Requereix permisos d'accés READ_EXTERNAL_STORAGE i/o WRITE_EXTERNAL_STORAGE. +
- +
-En cas d'utilitzar emmagatzematge compartit caldrà declarar al ''manifest.xml'' els permisos pertinents: +
-<sxh xml> +
-<manifest ...> +
-    <uses-permission android:maxSdkVersion="18" android:name="android.permission.READ_EXTERNAL_STORAGE" /+
-    <uses-permission android:maxSdkVersion="18" android:name="android.permission.WRITE_EXTERNAL_STORAGE" /+
-    ... +
-</manifest> +
-</sxh> +
- +
-<WRAP tip> +
-Des de la API 18 en endavant (Android 4.4 KitKat) ja no cal demanar els permisos per escriure en l'àrea externa de la pròpia //app//, per això apareix aquest ''maxSdkVersion=18'' en els permisosNomés cal tenir en compte que les altres aplicacions també podran accedir a aquestes dades si ho requereixen+
- +
-Si volem accedir les imatges i arxius d'altres //apps// mitjançant ''MediaStore'' caldrà que traiem el ''maxSdkVersion'' i demanem els permisos READ_EXTERNAL_STORAGE i WRITE_EXTERNAL_STORAGE.+
 </WRAP> </WRAP>
- 
-Als objectes [[https://developer.android.com/reference/android/content/Context|Context]] i [[https://developer.android.com/reference/android/os/Environment|Environment]] trobem funcions adequades per a accedir als arxius externs de l'app: 
-  * [[https://developer.android.com/reference/android/content/Context#getExternalFilesDir(java.lang.String)|Context.getExternalFilesDir(String type)]] ens dona el ''path'' de l'espai compartit dedicat a la nostra aplicació. 
-  * [[https://developer.android.com/reference/android/os/Environment#getExternalStoragePublicDirectory(java.lang.String)|Environment.getExternalStoragePublicDirectory(String type)]] ens dona el ''path'' de l'espai compartit comú de tots les aplicacions. 
- 
-A totes dues funcions cal especificar-les a quina de les diferents carpetes volem emmagatzemar-ho. Els valors s'indiquen a l'objecte [[https://developer.android.com/reference/android/os/Environment#fields|Environment]] i alguns exemples son: Environment.DIRECTORY_DCIM, Environment.DIRECTORY_MUSIC, Environment.DIRECTORY_SCREENSHOTS, etc. 
- 
- 
-==== Exercici: fotos full-size a l'àrea externa ===== 
- 
-Seguirem el [[https://developer.android.com/training/camera/photobasics#TaskPath|tutorial oficial de fotos d'Android a partir de la secció "Save full-size photo"]]. 
  
 <WRAP todo> <WRAP todo>
-Modifica l'aplicació de l'exercici anterior per aconseguir guardar la foto a //full size//: +Ajusta el tamany de la foto a la ''ImageView'' per fer que càpiga dins l'àrea marcada al //layout//.
-  * Fes un //commit// amb //tag// (per després fer una //release//) al [[Git]] abans de continuar. +
-  * Per activar que la càmera faci l'enregistrament //full-size// caldrà que adjuntem la Uri del fitxer al ''Intent'' mitjançant un ''putExtra'' (fixa't en l'exemple). +
-  * Caldrà utilitzar ''FileProvider'' per autoritzar a l'//app// Camera a utilitzar els arxius de la nostra //app//. +
-  *  +
-</WRAP>+
  
-\\ +  * Pots seguir les indicacions a la [[https://developer.android.com/training/camera/photobasics#TaskScalePhoto|secció "Decode a scaled image"]] del propi tutorial "photobasics"
- +  * Probablement el codi per ajustar i mostrar la foto et peti si està al ''onCreate''En primer lloc, perquè el primer cop no hi haurà imatge. El segon cop, petarà perquè durant el ''onCreate'' el valor de l'alçada i amplada del ''ImageView'' és zero. Per solventar-ho, [[https://stackoverflow.com/questions/19271609/imageview-getwidth-returns-0|aquest article proposa la solució]] d'actualitzar la imatge al mètode **''onWindowFocusChanged''** enlloc de fer-ho al ''onCreate'' (tampoc funciona al ''onStart'' ni al ''onResume'').
-===== Treballant amb XML i altres ===== +
- +
-És pràctic utilitzar arxius XML per separar els camps de forma llegible. Hi ha diverses llibreries per llegir XML amb Java: +
-  - [[https://stackoverflow.com/questions/11687074/create-xml-file-and-save-it-in-internal-storage-android|XmlSerializer]] és una opció. +
-  - Aquest article en castellà explica força bé com [[http://jmoral.es/blog/xml-dom|utilitzar DOM parser]]. +
-  - Potser et pot aclarir tb aquest [[https://stackoverflow.com/questions/773012/getting-xml-node-text-value-with-java-dom|post de DOM parser]] +
-  Algun [[https://stackoverflow.com/questions/5386991/java-most-efficient-method-to-iterate-over-all-elements-in-a-org-w3c-dom-docume|exemple mes de DOM parser]]. +
- +
-\\ +
- +
-===== Exercicis ===== +
- +
-Continuació de l'aplicacio "Andrevina" (endevinar el número del 1 al 100) iniciada a l'article [[Android]]+
- +
-<WRAP todo> +
-Continuant amb l'aplicació "Andrevina" i la taula de rècords: +
-  - Després d'entrar el nom per enregistrar un rècord, a més, engegarem la càmera. +
-  - Capturem la imatge i la enregistrem a disc amb un nom aleatori o seqüencial. +
-  - Assignem la imatge al nou item de rècord. +
-  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). +
-  - Modifiquem adequadament el //adapter// per aconseguir que ens agafi la imatge de disc i la assigni a la ''ListView''+
 </WRAP> </WRAP>
  
 \\ \\
- 
-En el cas que no estiguis desenvolupant l'app "Andrevina" pots fer aquest altre exercici: 
- 
-<WRAP todo> 
-  * Implementa una ''ListView'' tal i com s'explica a l'article [[Android ListView]]. 
-  * Modifica el ''layout'' per tal de que cada ''list_item'' tingui també un espai per a la imatge. 
-  * Afegeix un botó per capturar imatges i enregistrar-les amb diferents noms. Cada cop que enregistris una d'elles, assigna-la al primer element de la llista que no en tingui (al //Model// de la llista, o sigui, el ''ArrayList''). 
-  * Actualitza la //view// de manera que es visualitzin els canvis. 
-</WRAP> 
  
android_imatges.txt · Darrera modificació: 2022/12/19 20:15 per enric_mieza_sanchez