studio mediaplayer mecool example ejemplo developer create java android android-mediaplayer

java - mecool - MediaPlayer.setDataSource(String) no funciona con archivos locales



mediaplayer android studio ejemplo (6)

Puedo reproducir un mp3 local si uso el método estático MediaPlayer.create (context, id) pero no funciona si uso el método no estático MediaPlayer.setDataSource (String). Lo que sucede es que obtengo una excepción síncrona cuando llamo a MediaPlayer.prepare ():

prepare exceptionjava.io.IOException: Prepare failed.: status=0x1

Aquí está mi código (registro omitido):

String filename = "android.resource://" + this.getPackageName() + "/raw/test0"; mp = new MediaPlayer(); try { mp.setDataSource(filename); } catch (Exception e) {} try { mp.prepare(); } catch (Exception e) {} mp.start();

Tenga en cuenta que no recibo ningún error sobre el archivo que no se encuentra o nada. El nombre completo del archivo es test0.mp3 y lo coloco en el directorio / res / raw / en Eclipse.

Supongo que estoy configurando la ruta de forma incorrecta, pero todos los ejemplos que encuentro en línea utilizan la versión del FileDescriptor de setDataPath en lugar de la versión de String de setDataPath.

EDITAR: También puedo reproducir un mp3 local si uso el método MediaPlayer.setDataSource (FileDescriptor) y coloco los archivos en el directorio / asset / en Eclipse.

EDIT # 2: acepté la respuesta de que esto no es posible, pero luego me di cuenta de que la biblioteca que estoy usando (openFrameworks) realmente usa el método String para cargar un archivo. Mira aquí:

https://github.com/openframeworks/openFrameworks/blob/master/addons/ofxAndroid/ofAndroidLib/src/cc/openframeworks/OFAndroidSoundPlayer.java


Solución alternativa # 1: Usar Resources.getIdentifier ()

¿Por qué no usar getResources (). GetIdentifier () para obtener la identificación del recurso y usar el MediaPlayer.create () estático de la manera habitual?

public int getIdentifier (String name, String defType, String defPackage)

getIdentifier() toma el nombre de su recurso (prueba0), el tipo de recurso (en bruto), el nombre de su paquete y devuelve el ID del recurso real.

MediaPlayer mp; //String filename = "android.resource://" + this.getPackageName() + "/raw/test0"; mp=MediaPlayer.create(getApplicationContext(), getResources().getIdentifier("test0","raw",getPackageName())); mp.start();

He probado este código y funciona.

Actualización # 1:

Solución alternativa # 2: Usar Uri.parse ()

He probado este código también y funciona también. Pase su ruta de recursos como URI a setDataSource (). Acabo de hacer ese cambio en tu código para que funcione.

String filename = "android.resource://" + this.getPackageName() + "/raw/test0"; mp = new MediaPlayer(); try { mp.setDataSource(this,Uri.parse(filename)); } catch (Exception e) {} try { mp.prepare(); } catch (Exception e) {} mp.start(); Actualización # 2: la respuesta es NO

Acerca de la llamada a setDataSource (String)

Después de ver su comentario, parece que exactamente desea que se use setDataSource (cadena) para su propósito. No entiendo porque Pero, lo que asumo es que, por alguna razón, está tratando de evitar el uso de "contexto". Si ese no es el caso, entonces las dos soluciones anteriores deberían funcionar perfectamente para usted o si está tratando de evitar el contexto, me temo que no es posible con la función con la firma setDataSource (String) call. La razón es la siguiente,

La función setDataSource () de MediaPlayer tiene estas opciones a continuación, de las cuales solo está interesado en setDataSource (String),

setDataSource (String) llama internamente a setDataSource (String path, String [] keys, String [] values). Si puedes comprobar su source ,

public void setDataSource(String path) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { setDataSource(path, null, null); }

y si verifica el código setDataSource (String path, String [], String []), verá la siguiente condición filtrando la ruta según su esquema, especialmente si es el esquema "file" al que llama setDataSource (FileDescriptor) o si el esquema no es "archivo", llama a la función de medios JNI nativa.

{ final Uri uri = Uri.parse(path); final String scheme = uri.getScheme(); if ("file".equals(scheme)) { path = uri.getPath(); } else if (scheme != null) { // handle non-file sources nativeSetDataSource( MediaHTTPService.createHttpServiceBinderIfNecessary(path), path, keys, values); return; } final File file = new File(path); if (file.exists()) { FileInputStream is = new FileInputStream(file); FileDescriptor fd = is.getFD(); setDataSource(fd); is.close(); } else { throw new IOException("setDataSource failed."); } }

En el código anterior, el esquema de URI de su archivo de recursos no será nulo (android.resource: //) y setDataSource (String) intentará usar la función nativa de nativo (nativo) NativeSetDataSource () pensando que su ruta es http / https / rtsp y obviamente La llamada fallará también sin lanzar ninguna excepción. Es por eso que su llamada a setDataSource (String) se escapa sin una excepción y prepara la llamada a () con la siguiente excepción.

Prepare failed.: status=0x1

Por lo tanto, el reemplazo de setDataSource (String) no puede manejar su archivo de recursos. Necesitas elegir otra anulación para eso.

En el otro lado, marque setDataSource (contexto de contexto, uri uri, encabezados de mapas) que es usado por setDataSource (contexto de contexto, uri uri), utiliza AssetFileDescriptor, ContentResolver de su contexto y openAssetFileDescriptor para abrir el URI que se realiza correctamente como openAssetFileDescriptor ( ) puede abrir su archivo de recursos y, finalmente, el fd resultante se usa para llamar a la anulación de setDataSource (FileDescriptor).

AssetFileDescriptor fd = null; try { ContentResolver resolver = context.getContentResolver(); fd = resolver.openAssetFileDescriptor(uri, "r"); // : // : // : if (fd.getDeclaredLength() < 0) { setDataSource(fd.getFileDescriptor()); } else { setDataSource(fd.getFileDescriptor(), fd.getStartOffset(), fd.getDeclaredLength()); }

Para concluir, no puede usar el reemplazo de setDataSource (String) ya que es usar su archivo de recursos mp3. En cambio, si desea usar la cadena para reproducir su archivo de recursos, puede usar la función estática MediaPlayer.create () con getIdentifier () como se indicó anteriormente o setDataSource (context, uri) como se indica en la Actualización # 1.

Consulte el código fuente completo para obtener más información aquí: source

Actualización # 3:

openFrameworks setDataSource (String):

Como mencioné en los comentarios a continuación, openFrameworks usa el código ASIS de MediaPlayer de Android. Si puede referirse a la línea no: 4,

import android.media.MediaPlayer;

y línea n. °: 26, 27, 28 y 218.

player = new MediaPlayer(); //26 player.setDataSource(fileName); //27 player.prepare(); //28 private MediaPlayer player; //218

Por lo tanto, si intenta pasar ardroid.resource // + this.getPackageName () + "raw / test0" a setDataSource () usando openFrameworks, todavía obtendrá la misma excepción que expliqué en la Actualización # 2. Habiendo dicho eso, simplemente probé mi suerte en la búsqueda en Google para volver a estar seguro de lo que estoy diciendo y encontré este enlace del foro openFrameworks donde dice uno de los desarrolladores de openFrameworks core arturo :

no sé exactamente cómo funciona el mediaPlayer pero todo en res / raw o bin / data se copia en /sdcard/cc.openframeworks.packagename

Basado en ese comentario, puede intentar usar la ruta copiada en setDataSource (). El uso del archivo de recursos en setDataSource (String) de MediaPlayer no es posible ya que no puede aceptar la ruta del archivo de recursos. Tenga en cuenta que, dije que la "ruta del archivo de recursos" comienza con el esquema android.resource // que en realidad es una ubicación de contenedor (dentro de su apk), no una ubicación física. El archivo local funcionará con setDataSource (String) que comienza con el archivo de esquema : // .

Para que entienda claramente lo que está tratando de hacer con un archivo de recursos, intente ejecutar este código a continuación y vea el resultado en logcat,

try{ Log.d("RESURI", this.getClass().getClassLoader().getResource("res/raw/test0").toURI().toString()); } catch(Exception e) { }

Obtendrás el resultado como,

jar:file:/data/app/<packagename>/<apkname>.apk!/res/raw/test0

es para mostrarle que el archivo de recursos al que intenta acceder no es en realidad un archivo en la ruta física, sino una ubicación jar (dentro de apk) a la que no puede acceder utilizando el método setDataSource (String). (Intente usar 7zip para extraer su archivo apk y verá el res / raw / test0 en él).

Espero que ayude.

PD: Sé que es una respuesta un poco larga, pero espero que esto lo explique en detalle. Dejando las soluciones alternativas en la parte superior si eso puede ayudar a otros.


A continuación el código que funciona para mí, creo que este código te ayudará

player = MediaPlayer.create(this,R.raw.test0); player.setLooping(true); // Set looping player.setVolume(100,100); player.start(); @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); player.stop(); player.release(); }


Como dice la documentation Android

Archivos arbitrarios para guardar en su forma cruda. Para abrir estos recursos con un InputStream sin formato, llame a Resources.openRawResource () con el ID de recurso, que es R.raw.filename.

Sin embargo, si necesita acceder a los nombres de archivos originales y a la jerarquía de archivos, puede considerar guardar algunos recursos en el directorio de activos (en lugar de res / raw /). Los archivos en los activos / no tienen un ID de recurso, por lo que puede leerlos solo con AssetManager.

Por lo tanto, debe usar un InputStream para leer el archivo de audio antes de configurarlo en el reproductor multimedia.

Te sugiero que pongas el archivo de audio en la carpeta de activos como dijiste que jugaste

:)


Cuando se trata de un recurso en bruto, debe confiar en el siguiente constructor:

Creación de MediaPlayer estática pública (contexto de contexto, int resid)

Método de conveniencia para crear un MediaPlayer para un ID de recurso dado. En caso de éxito, prepare () ya habrá sido llamado y no deberá ser llamado nuevamente.

El código parece

mediaPlayer = MediaPlayer.create(this, R.raw.test0); mediaPlayer.start();

No olvides llamar a mediaPlayer.release() cuando hayas terminado.

( source )


Desde here

Cuando la ruta se refiere a un archivo local, el proceso puede realmente abrirse por un proceso distinto de la aplicación que realiza la llamada. Esto implica que la ruta debe ser una ruta absoluta (como cualquier otro proceso se ejecuta con un directorio de trabajo actual no especificado), y que la ruta debe hacer referencia a un archivo legible para todo el mundo. Como alternativa, la aplicación podría abrir el archivo para su lectura y luego usar el descriptor de archivos de la forma setDataSource (FileDescriptor).

Tratar,

String filePath = "path/file.mp3"; File file = new File(filePath); FileInputStream inputStream = new FileInputStream(file); mediaPlayer.setDataSource(inputStream.getFD()); inputStream.close();

¡Espero eso ayude!


setDataSource(@NonNull Context context, @NonNull Uri uri) utilizar setDataSource(@NonNull Context context, @NonNull Uri uri) lugar de setDataSource(String path)

Ya que quieres resolver los recursos de la aplicación interna de recursos, debes proporcionar un Context que se usaría para resolver esto.

Además, si observa estos dos métodos, observará que utilizan diferentes estrategias para encontrar el recurso resultante.