PDM Avanzado Obtendo información Multimedia

De MediaWiki
Saltar a: navegación, buscar

Introdución

  • A partires da API 23 o acceso a SD considérase un permiso perigoso polo que temos que solicitar dentro da aplicación o permiso ao usuario.
Isto está explicado no enlace seguinte: Permisos especiais Android 6.0 API 23.
Teremos que solicitar o permiso Manifest.permission.READ_EXTERNAL_STORAGE se queremos acceder a tarxeta SD Externa e temos no AndroidManifiest un target=23 e estamos a probar cun dispositivo cunha API 23.


  • Pode suceder que queiramos facer unha aplicación que teña acceso a os arquivos multimedia da nosa tarxeta SD e obter a información multimedia (autor, título, xénero,...) asociada a ela.
  • Imos ver dúas formas de facer isto, tendo en conta que o acceso á SD Externa para buscar arquivos pode non funcionar en versións iguais ou superiores á API 23.

Obtendo a información dos arquivos multimedia: Método 1

Nas versións anteriores de Android podíamos percorrer toda a tarxeta buscando os arquivos de tipo 'multimedia' e extraendo as súas propiedades (título, xénero,...).
Un exemplo de código:


Clase onde gardaríamos as propiedades:

  1. public class Cancion {
  2.  
  3.         public int id;
  4.         public String titulo;
  5.         public String artista;
  6.         public String album;
  7.         public String genero;
  8.         public String year;// Tiene que ser un String porque en algunas canciones no esta en formato de numero
  9.         public String duracion;
  10.         public String numeroPista;
  11.         public byte[] imagen;
  12.         public String fechaAdd;
  13.         public String ruta;
  14.        
  15.         public Cancion(){
  16.                
  17.         }
  18.         public Cancion(int id,String titulo,String artista,String album,String genero,
  19.                         String duracion,String year,byte[] imagen,String fechaAdd,String numeroPista,String ruta){
  20.                
  21.                 this.id=id;
  22.                 this.titulo=titulo;
  23.                 this.artista=artista;
  24.                 this.album=album;
  25.                 this.genero=genero;
  26.                 this.year=year;
  27.                 this.duracion=duracion;
  28.                 this.numeroPista=numeroPista;
  29.                 this.fechaAdd=fechaAdd;
  30.                 this.ruta=ruta;
  31.         }
  32.        
  33. }



Método que devolve un obxecto da clase Cancion cos datos obtidos a partires dun File:

  1.         public static Cancion crearCanciones(File cancion){
  2.                
  3.                 MediaMetadataRetriever mmr = new MediaMetadataRetriever();
  4.  
  5.                         Cancion c= new Cancion();
  6.                         c.titulo=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_TITLE);
  7.                         c.artista=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ARTIST);
  8.                         c.album=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_ALBUM);
  9.                         c.genero=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_GENRE);
  10.                         c.numeroPista=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_CD_TRACK_NUMBER);                
  11.                         c.duracion=String.format("%1$TM:%1$TS",Long.parseLong(mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)));
  12.                         c.year=mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_YEAR);
  13.                         c.ruta=cancion.getAbsolutePath();      
  14.                 return c;
  15.         }


Obtendo a información dos arquivos multimedia: Método 2

  • Outra forma de acceder aos contidos multimedia tanto da tarxeta SD Interna como a SD Externa é a través da clase MediaStore.
  • A forma de acceder é a seguinte:
  • Determinamos o tipo de arquivo que queremos explorar:
  1. Uri allsongsuri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
Neste caso estamos a buscar os arquivos de audio da tarxeta SD Interna.
Podemos utilizar:
  • MediaStore.Audio: Arquivos de audio.
  • MediaStore.Files: Arquivos multimedia e non multimedia.
  • MediaStore.Images: Arquivos de imaxe
  • MediaStore.Video: Arquivos de vídeo.
E podemos indicar a tarxeta externa coa constante: EXTERNAL_CONTENT_URI.


  • Debemos de facer unha query buscando os arquivos que pertenzan a ese tipo. O resultado da query será un curso coas referencias aos arquivos:
  1.  Cursor cursor;
  2.  Uri allsongsuri = MediaStore.Audio.Media.INTERNAL_CONTENT_URI;
  3.  
  4.   cursor = getContentResolver().query(allsongsuri, null, null, null, "_id");


  • Percorremos o listado de arquivos e obtemos a información multimedia:
  1.                     do {
  2.                         String nomeCancion = cursor
  3.                                 .getString(cursor
  4.                                         .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
  5.                         int idCancion = cursor.getInt(cursor
  6.                                 .getColumnIndex(MediaStore.Audio.Media._ID));
  7.  
  8.                         String fullPath = cursor.getString(cursor
  9.                                 .getColumnIndex(MediaStore.Audio.Media.DATA));
  10.  
  11.                         String nomeAlbum = cursor.getString(cursor
  12.                                 .getColumnIndex(MediaStore.Audio.Media.ALBUM));
  13.  
  14.  
  15.                     } while (cursor.moveToNext());


Podemos obter moita máis información multimedia nestes enlaces:


Obtendo a xénero

  • Á hora de buscar o xénero xa se complica a cousa. A idea é de buscar por cada canción o/os xéneros aos que pertence.
Polo tanto necesitamos facer unha nova consulta levando como parámetro o ID da canción obtida do paso anterior:


  1.                         String[] genresProjection = {          // Indicamos os campos que imos recuperar da consulta
  2.                                 MediaStore.Audio.Genres.NAME,
  3.                                 MediaStore.Audio.Genres._ID
  4.                         };
  5.  
  6.                         Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", idCancion);
  7.  
  8.                         Cursor genresCursor;
  9.                         String info="";
  10.                         genresCursor = getContentResolver().query(uri, genresProjection, null, null, null);   // Facemos a consulta
  11.                         int genre_column_index = genresCursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME);
  12.  
  13.                         if (genresCursor.moveToFirst()) {
  14.                             info += "Xéneros: ";
  15.                             do {
  16.                                 info += genresCursor.getString(genre_column_index) + " ";
  17.                             } while (genresCursor.moveToNext());
  18.                         }
Info tería os xéneros da canción.


  • Outra forma sería a de buscar todas as cancións que teñan un determinado xénero:
  1.     public void listarXeneros(){
  2.         int index;
  3.         long genreId;
  4.         Uri uri;
  5.         Cursor genrecursor;
  6.         Cursor tempcursor;
  7.         String[] proj1 = {MediaStore.Audio.Genres.NAME, MediaStore.Audio.Genres._ID};
  8.         String[] proj2 = {MediaStore.Audio.Media.DISPLAY_NAME};
  9.  
  10.         genrecursor = getContentResolver().query(MediaStore.Audio.Genres.EXTERNAL_CONTENT_URI, proj1, null, null, null);
  11.         if (genrecursor.moveToFirst()) {
  12.             do {
  13.                 index = genrecursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME);
  14.                 Log.i("Nome do xénero:", genrecursor.getString(index));
  15.  
  16.                 index = genrecursor.getColumnIndexOrThrow(MediaStore.Audio.Genres._ID);
  17.                 genreId = Long.parseLong(genrecursor.getString(index));
  18.                 uri = MediaStore.Audio.Genres.Members.getContentUri("external", genreId);
  19.  
  20.                 tempcursor = getContentResolver().query(uri, proj2, null,null,null);
  21.                 Log.i("Número de cancións dese xénero:", tempcursor.getCount() + "");
  22.                 if (tempcursor.moveToFirst()) {
  23.                     do {
  24.                         index = tempcursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DISPLAY_NAME);
  25.                         Log.i("Nome da canción:", tempcursor.getString(index));
  26.                     } while(tempcursor.moveToNext());
  27.                 }
  28.             } while(genrecursor.moveToNext());
  29.         }
  30.  
  31.     }

Caso práctico

Neste código imos ver un exemplo de como conseguir información multimedia dos arquivos de audio que se atopan na SD-EXTERNA.


  1. import android.Manifest;
  2.  
  3. import android.app.Activity;
  4. import android.content.pm.PackageManager;
  5. import android.database.Cursor;
  6. import android.net.Uri;
  7. import android.os.Build;
  8. import android.provider.MediaStore;
  9. import android.os.Bundle;
  10. import android.util.Log;
  11. import android.view.Menu;
  12. import android.view.MenuItem;
  13. import android.widget.Toast;
  14.  
  15. import java.util.List;
  16.  
  17. public class MainActivity extends Activity {
  18.  
  19.     private String[] STAR = { "*" };
  20.  
  21.     // Usado por si necesitamos diferentes permisos, para identificar cual de ellos es
  22.     private final int CODIGO_IDENTIFICADOR=1;
  23.  
  24.  
  25.     public void pedirPermiso(){
  26.  
  27.         if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1) {
  28.             requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, CODIGO_IDENTIFICADOR);
  29.         }
  30.         else
  31.             listarCancions();
  32.  
  33.  
  34.     }
  35.  
  36.     @Override
  37.     public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
  38.  
  39.         switch (requestCode) {
  40.             case CODIGO_IDENTIFICADOR: {
  41.                 // Se o usuario premeou o boton de cancelar o array volve cun null
  42.                 if (grantResults.length > 0
  43.                         && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  44.                     // PERMISO CONCEDIDO
  45.                     listarCancions();
  46.                 } else {
  47.                     // PERMISO DENEGADO
  48.                     Toast.makeText(this, "É NECESARIO O PERMISO PARA ACCEDER Á TARXETA EXTERNA", Toast.LENGTH_LONG).show();
  49.                 }
  50.                 return;
  51.             }
  52.  
  53.             // Comprobamos os outros permisos
  54.  
  55.         }
  56.     }
  57.  
  58.     }
  59.     public void listarCancions()
  60.     {
  61.  
  62.         Cursor cursor;
  63.         Uri allsongsuri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
  64.  
  65.         if (isSdPresent()) {
  66.  
  67.             cursor = getContentResolver().query(allsongsuri, null, null, null, "_id");
  68.             if (cursor != null) {
  69.                 if (cursor.moveToFirst()) {
  70.                     do {
  71.                         String songname = cursor
  72.                                 .getString(cursor
  73.                                         .getColumnIndex(MediaStore.Audio.Media.DISPLAY_NAME));
  74.                         int song_id = cursor.getInt(cursor
  75.                                 .getColumnIndex(MediaStore.Audio.Media._ID));
  76.  
  77.                         String fullpath = cursor.getString(cursor
  78.                                 .getColumnIndex(MediaStore.Audio.Media.DATA));
  79.  
  80.                         String albumname = cursor.getString(cursor
  81.                                 .getColumnIndex(MediaStore.Audio.Media.ALBUM));
  82.  
  83.  
  84.                         Uri uri = MediaStore.Audio.Genres.getContentUriForAudioId("external", song_id);
  85.  
  86.                         String[] genresProjection = {
  87.                                 MediaStore.Audio.Genres.NAME,
  88.                                 MediaStore.Audio.Genres._ID
  89.                         };
  90.                         Cursor genresCursor;
  91.                         String info="";
  92.                         genresCursor = getContentResolver().query(uri,
  93.                                 genresProjection, null, null, null);
  94.                         int genre_column_index = genresCursor.getColumnIndexOrThrow(MediaStore.Audio.Genres.NAME);
  95.  
  96.                         if (genresCursor.moveToFirst()) {
  97.                             info += "Xéneros: ";
  98.                             do {
  99.                                 info += genresCursor.getString(genre_column_index) + " ";
  100.                             } while (genresCursor.moveToNext());
  101.                         }
  102.                         Log.i("INFO", songname);
  103.                         Log.i("INFO", albumname);
  104.                         Log.i("INFO", info);
  105.  
  106.                     } while (cursor.moveToNext());
  107.                 }
  108.                 cursor.close();
  109.             }
  110.         }
  111.     }
  112.  
  113.  
  114.     public static boolean isSdPresent()
  115.     {
  116.         return android.os.Environment.getExternalStorageState().equals(
  117.                 android.os.Environment.MEDIA_MOUNTED);
  118.     }
  119.  
  120.     @Override
  121.     protected void onCreate(Bundle savedInstanceState) {
  122.         super.onCreate(savedInstanceState);
  123.         setContentView(R.layout.activity_main);
  124.  
  125.  
  126.         pedirPermiso();
  127.  
  128.     }
  129.  
  130.     @Override
  131.     public boolean onCreateOptionsMenu(Menu menu) {
  132.         // Inflate the menu; this adds items to the action bar if it is present.
  133.         getMenuInflater().inflate(R.menu.menu_main, menu);
  134.         return true;
  135.     }
  136.  
  137.     @Override
  138.     public boolean onOptionsItemSelected(MenuItem item) {
  139.         // Handle action bar item clicks here. The action bar will
  140.         // automatically handle clicks on the Home/Up button, so long
  141.         // as you specify a parent activity in AndroidManifest.xml.
  142.         int id = item.getItemId();
  143.  
  144.         //noinspection SimplifiableIfStatement
  145.         if (id == R.id.action_settings) {
  146.             return true;
  147.         }
  148.  
  149.         return super.onOptionsItemSelected(item);
  150.     }
  151. }





-- Ángel D. Fernández González -- (2015).