tutorial studio sound play permission mediaplayer developer android surfaceview android-mediaplayer

android - studio - La superficie se ha liberado cuando intento configurarDisplay to MediaPlayer



mediaplayer permission android (6)

Mi archivo xml:

<SurfaceView android:id="@+id/surfaceView" android:layout_marginTop="50dp" android:layout_width="fill_parent" android:layout_height="300dp" />

Mi función para configurar Mostrar:

public void playVideo() { MediaPlayer mp = new MediaPlayer(); SurfaceView sv = (SurfaceView) this.findViewById(R.id.surfaceView); try { mp.setDataSource("sdcard/test/a.3gp"); SurfaceHolder sh = sv.getHolder(); mp.setDisplay(sh);***----the exception occured here*** mp.prepare(); mp.start(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }

el registro de la siguiente manera:

04-24 22:19:33.645: W/System.err(16106): java.lang.IllegalArgumentException: The surface has been released 04-24 22:19:33.645: W/System.err(16106): at android.media.MediaPlayer._setVideoSurface(Native Method) 04-24 22:19:33.645: W/System.err(16106): at android.media.MediaPlayer.setDisplay(MediaPlayer.java:698)

He encontrado algunas preguntas similares aquí, pero todas esas no son adecuadas para mí. Esperando tus respuestas. Muchas gracias.


Es algo relacionado con la secuencia de ejecución, ya que la superficie debe crearse primero antes de configurar la visualización para el MediaPlayer , por lo que debe anular la surfaceCreated método de devolución de llamada.

@Override public void surfaceCreated(SurfaceHolder holder) { mp.setDisplay(sh); // now "mp" is defined as a class variable }

y ahora no hay necesidad de configurarDisplay dentro de su método de juego:

private MediaPlayer mp; // to use it inside surfaceCreated callback method public void playVideo() { mp = new MediaPlayer(); SurfaceView sv = (SurfaceView) this.findViewById(R.id.surfaceView); try { mp.setDataSource("sdcard/test/a.3gp"); SurfaceHolder sh = sv.getHolder(); mp.prepare(); mp.start(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } }


Hacer uso de SurfaceHolder.Callback como a continuación

SurfaceView mSurfaceView = (SurfaceView) findViewById(R.id.surfaceView); SurfaceHolder holder = mSurfaceView.getHolder(); final MediaPlayer player = new MediaPlayer(); holder.addCallback(new SurfaceHolder.Callback() { @Override public void surfaceCreated(SurfaceHolder holder) { player.setDisplay(holder); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override public void surfaceDestroyed(SurfaceHolder holder) { } }); String UrlPath="android.resource://"+getActivity().getPackageName()+"/"+R.raw.your_file_name_without_extension; try { player.setDataSource(getActivity(),Uri.parse(UrlPath)); player.prepareAsync(); } catch (IOException e) { e.printStackTrace(); } player.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { mp.start(); } });


La forma más sencilla es llamar a setDisplay en surfaceCreated :

@Override public void surfaceCreated(SurfaceHolder holder) { mp.setDisplay(holder) }

y no te olvides de desenlazar la superficie:

@Override public void surfaceDestroyed(SurfaceHolder holder) { mp.setDisplay(null); }

Nota: el reproductor multimedia debe onCreate en algún lugar antes, por ejemplo, en onCreate .


La superficie puede ser destruida. Es por eso que necesita agregar a un public void surfaceDestroyed(SurfaceHolder holder) a su implementación de SurfaceView de esta manera:

@Override public void surfaceDestroyed(SurfaceHolder holder) { synchronized (this) { hasActiveHolder = false; synchronized(this) { this.notifyAll(); } } }

También debe agregar una función que maneje la creación de Surface:

@Override public void surfaceCreated(SurfaceHolder holder) { synchronized (this) { hasActiveHolder = true; this.notifyAll() } }

Y modifica tu propia función de esta manera:

mp.setDataSource("sdcard/test/a.3gp"); SurfaceHolder sh = sv.getHolder(); synchronized (this) { while (!hasActiveHolder) { try { this.wait(); } catch (InterruptedException e) { //Print something } } mp.setDisplay(sh); mp.prepare(); }

Tienes otra opción que es la forma en que Google sugiere que uses SurfaceView: en un hilo separado.


Para aquellos que aún tienen problemas, intente implementar SurfaceHolder.Callback en su actividad / fragment / etc y en el método onCreate / onCreateView , llame al método addCallback (SurfaceHolder.Callback callback) , usando su actividad / fragment / etc como el parámetro callback.


Podemos ver el código fuente de VideoView:

SurfaceHolder.Callback mSHCallback = new SurfaceHolder.Callback(){ ... public void surfaceCreated(SurfaceHolder holder) { mSurfaceHolder = holder; openVideo(); } private void openVideo() { ... mMediaPlayer = new MediaPlayer(); mMediaPlayer.setDisplay(mSurfaceHolder); } }

Así que podemos aprender que debemos usar mediaplayer.setDisplay() en el método surfaceCreate .