====== Android Multimèdia ====== Per multimèdia s'entenen els diferents mitjans que permeten a la persona humana percebre l'entorn. Els més destacats son la visió i la oïda, però també podrien incloure's el tacte, el gust i l'olfacte. I també la orientació, sabem si estem cap per avall mercès als canals semicirculars de la oïda (no és ni una brúixola ni un GPS però algo és algo). {{ android:sunset-camera-musica.png?450 }} Tot el relacionat amb sensors és susceptible d'entrar en aquesta categoria, però per raons d'extensió ens centrarem en: * Imatge i video: captura d'imatges i vídeo, tractament i visualització * Àudio: gravació, reproducció, TTS (Text to Speech) * Sensors: acceleròmetre, giròscop (brúixola 3D) Apunts de referència: * [[Android]] {{tag> #Dam #DamMp08 #DamMp08Uf2 #DamMp08Uf02 Android mobile java }} \\ ===== Seguretat i permisos ===== {{ android:android-permisos.png?120}} Els sistemes operatius cada cop es tornen més exigents amb la seguretat, i per tant més restrictius. Això fa que totes les operacions tinguin força passes prèvies abans de poder-se realitzar, per impedir que aplicacions malicioses vulnerin els nostres drets de privacitat de les dades. Podeu llegir més sobre el [[https://ioc.xtec.cat/materials/FP/Recursos/ActivityUtil/documents_fp_docencia_activitats_cib_m03_cib_m03_u4/documents_fp_docencia_activitats_cib_m03_cib_m03_u4_cib_m03_u4l1_oa2/index.html|model de seguretat dels dispostius mòbils]]. Els accessos als arxius compartits requereixen diversos nivells de permisos: * **Permisos estàtics** (sistema antic) a l'''AndroidManifest.xml'' que declaren abans d'instal·lar els recursos del dispositiu als que es voldrà accedir. * **Permisos dinàmics** (veure foto) son més granulars i permeten que provis l'aplicació fins que arriba el moment d'accedir a les dades compartides. Es va implementar des d'Android 6 Marshmallow (API 23), i s'ha reforçat a partir d'Android 13 (API 33). \\ ===== Activity for result ===== Moltes gestions en la nostra app es poden **delegar en una aplicació externa**, com accedir a la galeria multimèdia, o permetre que l'aplicació de fotos del sistema operatiu faci la foto per nosaltres. Aquesta delegació es fa amb un ''Intent'', similarment a quan canviem d'''Activity''. {{ android-camera-intent.jpg?400 }} Inicialment aquesta operació era més senzilla i implicava una simple crida ''startActivityForResult()'' i una //callback// ''onActivityResult()'', però amb el reforçament de les directives de seguretat s'ha passat a emprar la anomenada [[https://developer.android.com/training/basics/intents/result|Activity Result API]] que afegeix algunes sofisticacions (i complicacions) més. \\ ===== Exercicis ===== Necessitarem algunes fotos dins el dispositiu de l'emulador quan treballem amb Android Studio. Ves a l'aplicació de fotos i fes algunes perquè el carret de la càmera tingui alguns exemples. Per simular la captura de fotos podem **ajustar les càmeres frontal i interna de l'emulador** amb diverses opcions: * **Virtual Scene**: escena 3D (l'habitació amb el gat, el gos, la TV i la cuina). Ets pots moure dins l'estança i apuntar en diferents llocs. * **Emulated**: un dibuix ultrapixelat molt bàsic. * **Webcam**: enllaç a la càmera real del dispositiu (si estàs en un PC, la webcam). \\ **Accés a galeria multimèdia** Mireu el [[https://developer.android.com/training/basics/intents/result#launch|codi "Launch an Activity for result" de la documentació oficial d'Android]]. En realitat és un codi molt curt, tot i que conté implícit el ''Intent'' i d'altres recursos. Caldrà afegir l'acció de la //callback// on diu "Handle the returned Uri", i aplicar la imatge que ens arriba en forma de Uri al ''ImageView'' que tinguem. {{android:android-gallery0.png?100}} {{android:android-gallery1.png?100}} **Captura de imatge en miniatura amb la càmera (versió //thumbnail//)** El mateix mecanisme que heu emprat per demanar la càrrega d'imatge des de la galeria multimèdia es pot aplicar per a capturar imatges en versió //thumbnail//. Enlloc del contracte ''ActivityResultContracts.GetContent()'' que hem emprat, investiga com aplicar ''ActivityResultContracts.TakePicturePreview()''. Afegeix un botó a l'aplicació anterior amb el què capturis el //thumbnail// directament de l'aplicació càmera del sistema operatiu. \\ ===== Foto full-size i FileProvider : donant accés a l'espai privat ===== Demanar una miniatura (//thumbnail//) a una altra ''Activity'' és senzill perquè no son gaires dades que s'han de passar d'una a l'altra a través del ''Intent''. En canvi, demanar que facin una foto d'alta resolució o un vídeo ja és més complicat, ja que el ''Intent'' no permet transferir tanta informació. Un mètode força segur per a fer la foto en alta resolució és obrir els permisos temporalment d'un arxiu privat de l'aplicació que demana la foto perquè l'App Càmera externa la pugui escriure. Això es fa a través del [[https://developer.android.com/reference/androidx/core/content/FileProvider|FileProvider]]. {{ android:external-camera-app.png }} Per a realitzar la foto //full-size// i guardar-la a l'espai privat caldrà: - Afegir un arxiu ''res/xml/file_paths.xml'' on s'indiquen carpetes i arxius compartibles. - Declarar el ''FileProvider'' al ''AndroidManifest.xml''. - Al codi de l'''Activity'' transformar el ''File'' estàndard a ''Uri'' (recurs compartible) amb el ''FileProvider''. - Engegar l'App Camera amb la ''Activity Result API'' (similar al fet fins ara per la galeria i el //thumbnail//). ==== Arxius XML ==== ==== Codi MainActivity.kt ==== Preparació del recurs compartit i inici de l'App Camera: val photoButton = findViewById