Disable Android's VideoView requestAudioFocus when playing a video?

前端 未结 5 2137
野的像风
野的像风 2021-02-13 06:04

I\'m building an app that records and plays back video. I would like to do so without affecting background music playback, i.e. if I begin playing a video, I do not want to paus

相关标签:
5条回答
  • 2021-02-13 06:37

    use audioManager.abandonAudioFocus(null)

    If you look at the VideoView code you will notice it calls the method audioManager.requestAudioFocus with null for the OnAudioFocusChangeListener. When you register a listener with the AudioManager it uses this method to make an ID for the listener

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

    which generates the same ID every time you use null. So if you call abandonAudioFocus with null it will remove any listener that was added with null as the parameter for the OnAudioFocusChangeListener

    0 讨论(0)
  • 2021-02-13 06:38

    You may use MediaPlayer + SurfaceView instead.

    0 讨论(0)
  • 2021-02-13 06:43

    I got around this with a stupid solution by copying whole source code of android.widget.VideoView of Lollipop and removing line you mentioned.

    Make your own VideoView class. don't use extends VideoView since you can't override openVideo() method.

    I don't recommend this as I thinking it's a temporary solution. VideoView Changed a lot between 4.1-5.0 so this can make RuntimeException on Android version other than Lollipop

    Edit

    I made approach MediaPlayer + SurfaceView as pinxue told us; It respects aspect ratio within viewWidth and 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");
                    }
                }
    
    0 讨论(0)
  • 2021-02-13 06:46

    Starting with Android SDK 26 you may want to use VideoView and

    if(Build.VERSION.SDK_INT >= Build.Version_CODES.O){
         //set this BEFORE start playback
         videoView.setAudioFocusRequest(AudioManager.AUDIOFOCUS_NONE)
    }
    

    For older version, there's a workaround described here: https://stackoverflow.com/a/31569930/993439

    Basically, copy source code of VideoView and uncomment following lines

    AudioManager am = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
    am.requestAudioFocus(null, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
    
    0 讨论(0)
  • 2021-02-13 06:47

    The accepted solution does not guarantee compatibility across all Android versions and is a dirty hack more than a true solution. I've tried all forms of hacks to get this working, yet none have worked to my satisfaction.

    I have come up with a much better solution though - switch from a VideoView to a TextureView and load it with a MediaPlayer. There is no difference from the user's perspective, just no more audio stoppage.

    Here's my use case for playing an MP4 looping:

    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;
        }
    }
    
    0 讨论(0)
提交回复
热议问题