PDM Avanzado Accedendo á SD en Android 5.1

De MediaWiki
Ir a la navegación Ir a la búsqueda

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 5.0 | http://mediawiki.cifprodolfoucha.es/index.php?title=PDM_Avanzado_Permisos_AndroidManifiest.xml]. 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.
  • 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 superiores á API 21.


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

  • 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:


  • Á 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.



Caso práctico

Neste código imos ver un exemplo de como conseguir información multimedia:

  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) {
 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 CHAMAR POR TELÉFONO", 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.INTERNAL_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 += "Genres: ";
 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).