2015-01-23 17 views
12

Tôi đang xây dựng một ứng dụng ghi lại và phát lại video. Tôi muốn làm như vậy mà không ảnh hưởng đến phát lại nhạc nền, tức là nếu tôi bắt đầu phát video, tôi không muốn tạm dừng âm thanh của ứng dụng khác. Tuy nhiên, trên Lollipop, lớp VideoView của Android tự động yêu cầu lấy nét âm thanh khi phương thức riêng VideoView.openVideo() được gọi là:Tắt yêu cầu VideoView của AndroidAudioFocus khi phát video?

Bất kỳ đề xuất nào về cách giải quyết vấn đề này?

Trả lời

2

Tôi đã giải quyết vấn đề này bằng cách sao chép toàn bộ mã nguồn của android.widget.VideoView của Lollipop và xóa dòng bạn đã đề cập.

Tạo lớp học VideoView của riêng bạn. không sử dụng extends VideoView vì bạn không thể ghi đè phương thức openVideo().

Tôi không khuyến nghị điều này vì tôi nghĩ đó là giải pháp tạm thời. VideoView thay đổi rất nhiều giữa 4,1-5,0 vì vậy đây có thể làm cho RuntimeException trên phiên bản Android khác hơn Lollipop

Sửa

tôi đã thực hiện cách tiếp cận MediaPlayer + SurfaceView như pinxue nói với chúng tôi; Nó tôn trọng tỷ lệ co trong phạm vi viewWidthviewHeight.

  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"); 
       } 
      } 
+1

Mã nguồn cho 'VideoView' sử dụng rất nhiều tài liệu tham khảo để các lĩnh vực và phương pháp của' MediaPlayer' ẩn, làm thế nào bạn có được xung quanh rằng khi bạn sao chép nó để làm cho lớp học của riêng bạn? –

+0

Tôi đã ngu ngốc mà thời gian trước khi pinxue nói với chúng tôi MediaPlayer + SurfaceView. :/Tôi vừa xóa mọi thứ xảy ra lỗi trình biên dịch trên VideoView Source đã sao chép .. hầu hết trong số đó là các tham chiếu liên quan đến phụ đề mà tôi không cần. ..và làm việc tốt cho mục đích của tôi. Tôi cũng khuyên bạn nên sử dụng phương pháp MediaPlayer + SurfaceView. – LaruYan

+0

Cảm ơn bạn đã làm rõ, tôi cũng đã xóa mã lỗi biên dịch.Bạn có biết một hướng dẫn tốt để sử dụng phương pháp MediaPlayer + SurfaceView không? Tôi có thể xoay quanh để chuyển sang nó cuối cùng. –

1

Bạn có thể sử dụng MediaPlayer + SurfaceView để thay thế.

0

sử dụng audioManager.abandonAudioFocus (null)

Nếu bạn nhìn vào mã VideoView bạn sẽ thấy nó gọi là audioManager.requestAudioFocus phương pháp với null cho OnAudioFocusChangeListener. Khi bạn đăng ký người nghe với AudioManager, công cụ này sử dụng phương pháp này để tạo ID cho người nghe

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

tạo ID giống nhau mỗi khi bạn sử dụng null. Vì vậy, nếu bạn gọi từ bỏAudioFocus với null, nó sẽ loại bỏ bất kỳ người nghe nào đã được thêm vào bằng null khi tham số cho OnAudioFocusChangeListener

+0

Cố gắng cao quý, nhưng đã không làm việc cho tôi mặc dù đã thử mọi biến thể của điều này. –

1

Giải pháp được chấp nhận không đảm bảo khả năng tương thích trên tất cả các phiên bản Android và hack bẩn hơn giải pháp thực sự. Tôi đã thử tất cả các hình thức hack để có được điều này làm việc, nhưng không ai đã làm việc để sự hài lòng của tôi.

Tôi đã đưa ra giải pháp tốt hơn nhiều - chuyển từ số VideoView sang số TextureView và tải bằng MediaPlayer. Không có sự khác biệt so với quan điểm của người dùng, không chỉ dừng âm thanh.

Đây là trường hợp sử dụng của tôi để chơi một vòng lặp 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; 
    } 
} 
+1

Tôi nghĩ rằng đây sẽ là câu trả lời được chấp nhận, nó đã làm cho các trick cho tôi. – pillar15

Các vấn đề liên quan