JustPlay, explorador de archivos

· 624 palabras · Lectura de 3 minutos

Uno de mis requisitos en JustPlay (de hecho, el fundamental), es poder reproducir a partir de archivos sueltos o directorios.

Por tanto, necesitaré un explorador de archivos, aunque sea muy básico, que permita ver los archivos en la memoria del dispositivo y añadirlos a una lista de reproducción. Gráficamente, la interacción entre las actividades sería así. En general la devolución del parámetro no tendrá mayor problema, ya que se puede hacer a través del intent de vuelta.

Para crear el explorador de archivos voy a seguir este tutorial, por supuesto añadiendo cosas de mi cosecha según me vaya pareciendo.

Creación de CrankExplorer

En primer lugar creo la activity tal cual heredando de CrankActivity y le añado la implementación por defecto de todos los métodos del ciclo de vida.

Ahora la declaro en el AndroidManifest:


<activity android:name=".FileExplorer" android:label="@string/explorer_name"/>

Para arrancarla, creo un botón en MediaPlayer:


<Button
android:id="@+id/buttonOpenExplorer"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/open_explorer"
android:onClick="openCrankExplorer" />

Y el listener:


public void openCrankExplorer(View v) {
  Intent openCrankExplorer = new Intent(this, CrankExplorer.class);
  startActivityForResult(openCrankExplorer, REQUEST_CODE);
}

Con esto ya puedo llamar a FileExplorer desde MediaPlayer.

Ahora toca implementar FileExplorer, en general la implementación seguirá estas líneas:

  1. Se mostrarán todos los archivos y directorios que se puedan leer.
  2. Si se hace click en un directorio se abrirá.
  3. Si se hace click en un archivo, se abrirá un diálogo de confirmación para añadirlo a la lista de reproducción.
  4. Si se deja presionado un directorio se abrirá un menú contextual para añadir todo su contenido a la lista de reproducción.

Al lío, siguiendo lo que comentan, hago un layout para los archivos, le voy a llamar file_row.xml y a continuación creo el layout de FileExplorer, crankexplorer.xml. No tiene mucha historia ya que es una lista y punto.

En cuanto a la actividad, lo primero que hago es filtrar los archivos mediante un FilenameFilter, para que solo muestre aquellos directorios y archivos que sean legibles y si es un archivo, que además termine en mp3 u ogg.

Añado un onListItemClick y si es un directorio se invocará a getDir sobre él, mientras que si es un archivo, se mostrará un diálogo que permitirá dos acciones:

  1. Añadir el archivo a la lista de reproducción.
  2. Cancelar

Por último, para devolver la canción a MediaPlayer, creo un método finish().

Para ir acabando, falta el menú contextual que me permita seleccionar un directorio para añadir (junto con todos los archivos contenidos en él y sus subdirectorios). Primero creo el layout del menu y lo llamo crankexplorer_context.xml a continuación en el onCreate, registro la lista para el menú contextual:


registerForContextMenu(getListView());

Después tengo que crear dos métodos del ciclo de vida, el primero, la creación del menú:


@Override
public void onCreateContextMenu(ContextMenu menu, View v,
  ContextMenuInfo menuInfo) {
  super.onCreateContextMenu(menu, v, menuInfo);
  menu.setHeaderTitle(R.string.directory_contextual_title);
  MenuInflater inflater = getMenuInflater();
  inflater.inflate(R.menu.crankexplorer_context, menu);
}

Y el segundo, la acción a ejecutar cuando se selecciona:


@Override
public boolean onContextItemSelected(MenuItem item) {
  switch (item.getItemId()) {
    case R.id.addDirectoryItem:
      AdapterContextMenuInfo info = (AdapterContextMenuInfo) item
      .getMenuInfo();
      this.selected = new File(this.path.get((int) info.id));
      if (this.selected.isDirectory()) {
        finish();
      }
      return true;
   default:
     return super.onContextItemSelected(item);
  }
}

Para acabar, implemento el método finish() para devolver bien la canción seleccionada, bien todas las canciones:


@Override
public void finish() {
  Intent data = new Intent();
  if (this.selected != null) {
    if (this.selected.isFile()) {
      data.putExtra("selectedFile", this.selected);
    } else if (this.selected.isDirectory()) {
      List<File> filesInDirectory = this.explodeDir(this.selected);
      data.putExtra("selectedFiles",
        (ArrayList<File>) filesInDirectory);
    }
  }
  setResult(RESULT_OK, data);
  super.finish();
}

Y en MediaPlayer creo un onActivityResult que procese la vuelta desde FileExplorer:


@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if (data.hasExtra("selectedFile")) {
    this.playlist.add((File) data.getExtras().get("selectedFile"));
    this.renderPlaylist();
  } else if (data.hasExtra("selectedFiles")) {
    List<File> fileList = (List<File>) data.getExtras().get(
      "selectedFiles");
    this.playlist.addAll(fileList);
    this.renderPlaylist();
  }
}
TODO

Pues ya solo queda:

  1. Hacer el bind del service en MediaPlayer
  2. Reproducir con un MediaPlayer en el thread.
Código

Sigue en GitHub

CrankPlay en GitHub

comments powered by Disqus