¿Deshabilitar la solicitud de VideoView de AndroidAudioFocus al reproducir un video?

Estoy creando una aplicación que graba y reproduce video. Me gustaría hacerlo sin afectar la reproducción de música de fondo, es decir, si empiezo a reproducir un vídeo, no quiero detener el audio de otras aplicaciones. Sin embargo, en Lollipop, la clase VideoView de Android solicita automáticamente el enfoque de audio cuando se llama al método privado VideoView.openVideo() :

 AudioManager am = (AudioManager) super.getSystemService(name); am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); 

¿Alguna sugerencia sobre cómo superar esto?

Conseguí alrededor de esto con una solución estúpida copiando el código fuente entero de android.widget.VideoView de Lollipop y quitando la línea que usted mencionó.

Haga su propia clase VideoView . No utilice extends VideoView ya que no puede anular el método openVideo() .

No recomiendo esto como pienso que es una solución temporal. VideoView Cambiado mucho entre 4.1-5.0 por lo que esto puede hacer RuntimeException en la versión de Android que no sea Lollipop

Editar

Hice la aproximación MediaPlayer + SurfaceView como pinxue nos dijo; Respeta la relación de aspecto en viewWidth y viewHeight .

  final String finalFilePath = filePath; final SurfaceHolder surfaceHolder = sv.getHolder(); final MediaPlayer mediaPlayer = new MediaPlayer(); final LinearLayout.LayoutParams svLayoutParams = new LinearLayout.LayoutParams(viewWidth,viewHeight); surfaceHolder.addCallback(new SurfaceHolder.Callback(){ @Override public void surfaceCreated(SurfaceHolder holder) { try { if(isDebug) { System.out.println("setting VideoPath to VideoView: "+finalFilePath); } mediaPlayer.setDataSource(finalFilePath); }catch (IOException ioe){ if(isDebug){ ioe.printStackTrace(); } //mediaPlayer = null; } mediaPlayer.setDisplay(surfaceHolder); mediaPlayer.prepareAsync(); mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mp) { if(isDebug){ System.out.println("Video is starting..."); } // for compatibility, we adjust size based on aspect ratio if ( mp.getVideoWidth() * svLayoutParams.height < svLayoutParams.width * mp.getVideoHeight() ) { //Log.i("@@@", "image too wide, correcting"); svLayoutParams.width = svLayoutParams.height * mp.getVideoWidth() / mp.getVideoHeight(); } else if ( mp.getVideoWidth() * svLayoutParams.height > svLayoutParams.width * mp.getVideoHeight() ) { //Log.i("@@@", "image too tall, correcting"); svLayoutParams.height = svLayoutParams.width * mp.getVideoHeight() / mp.getVideoWidth(); } sv.post(new Runnable(){ @Override public void run() { sv.setLayoutParams(svLayoutParams); } }); mp.start(); } }); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { if(isDebug){ System.out.println("surfaceChanged(holder, "+format+", "+width+", "+height+")"); } } @Override public void surfaceDestroyed(SurfaceHolder holder) { try { mediaPlayer.setDataSource(""); }catch (IOException ioe){ if(isDebug){ ioe.printStackTrace(); } } } }); if(sv.post(new Runnable() { @Override public void run() { sv.setLayoutParams(svLayoutParams);/// sv.setVisibility(View.VISIBLE); }})){ if(isDebug) { System.out.println("post Succeded"); } }else{ if(isDebug) { System.out.println("post Failed"); } } 

Puede utilizar MediaPlayer + SurfaceView en su lugar.

La solución aceptada no garantiza la compatibilidad entre todas las versiones de Android y es un hack sucio más que una verdadera solución. He intentado todas las formas de hacks para conseguir este trabajo, pero ninguno ha funcionado a mi satisfacción.

He llegado con una solución mucho mejor sin embargo – cambiar de un VideoView a un TextureView y cargar con un MediaPlayer . No hay diferencia desde la perspectiva del usuario, simplemente no hay detención de audio.

Aquí está mi caso de uso para jugar un bucle MP4:

 private TextureView _introVideoTextureView; private MediaPlayer _introMediaPlayer; ... @Override public void onCreate(...) { _introVideoTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() { @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { try { destoryIntroVideo(); _introMediaPlayer = MediaPlayer.create(SignInActivity.this, R.raw.intro_video); _introMediaPlayer.setSurface(new Surface(surfaceTexture)); _introMediaPlayer.setLooping(true); _introMediaPlayer.setVideoScalingMode(MediaPlayer.VIDEO_SCALING_MODE_SCALE_TO_FIT_WITH_CROPPING); _introMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() { @Override public void onPrepared(MediaPlayer mediaPlayer) { mediaPlayer.start(); } }); } catch (Exception e) { System.err.println("Error playing intro video: " + e.getMessage()); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int i, int i1) {} @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { return false; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) {} }); } @Override public void onDestroy() { super.onDestroy(); destoryIntroVideo(); } private void destoryIntroVideo() { if (_introMediaPlayer != null) { _introMediaPlayer.stop(); _introMediaPlayer.release(); _introMediaPlayer = null; } } 

Use audioManager.abandonAudioFocus (null)

Si miras el código de VideoView notarás que llama al método audioManager.requestAudioFocus con null para OnAudioFocusChangeListener. Cuando registra un oyente con el AudioManager utiliza este método para crear un ID para el oyente

 private String getIdForAudioFocusListener(OnAudioFocusChangeListener l) { if (l == null) { return new String(this.toString()); } else { return new String(this.toString() + l.toString()); } } 

Que genera el mismo ID cada vez que utiliza null. Así que si llama a abandonAudioFocus con null se eliminará cualquier oyente que se agregó con null como el parámetro para OnAudioFocusChangeListener

  • VideoView para que coincida con la altura de los padres y mantenga la relación de aspecto
  • Detectar si un VideoVIew está almacenando en búfer
  • Fragmento retenido no retenido
  • Transmisión de video en vivo entre dos teléfonos Android
  • Obtener el camino real para Uri Android
  • El video se reproduce en parte de la pantalla después de desbloquear la pantalla
  • Cómo reproducir video de la carpeta en bruto con el dispositivo Android?
  • Android multiple videoView problem, Galaxy Tab específico
  • VideoView dentro de DialogFragment
  • Android Video View no reproduce archivos MP4 en algunos dispositivos
  • Visibilidad del botón en VideoView después de usar videoView.setZOrderOnTop (true); Androide
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.