2

我正在尝试从库中播放 .mp4 格式的视频,并在相机应用程序中录制视频。当我尝试执行 setDisplay 时,出现表面已释放错误。我已经阅读了大多数论坛,我确信这是我处理我的 surfaceView 或我的持有者的方式。在我调用我的开始之前,我的表面总是被破坏,我不知道如何保持它的创建。需要社区建议,因为这是我第一次这样做

我知道它正确地获取了文件的路径,并且当我删除任何播放视频的尝试时,音频部分起作用了。也许这与我在启动应用程序时看到主屏幕上的表面有关,所以我的 XML 可能不正确,但我认为应该没问题:

    public class MainActivity extends Activity implements OnClickListener,
            OnPreparedListener, OnCompletionListener, SurfaceHolder.Callback,
            OnBufferingUpdateListener, OnVideoSizeChangedListener {

        private static final int SELECT_VIDEO = 1;
        private static final String TAG = "MainActivity";
        private byte[] videoFile;
        private int mVideoWidth;
        private int mVideoHeight;
        private MediaPlayer mMediaPlayer;
        private SurfaceView mPreview;
        private SurfaceHolder holder;
        private Bundle extras;
        private boolean mIsVideoSizeKnown = false;
        private boolean mIsVideoReadyToBePlayed = false;
        private boolean hasActiveHolder = false;

        @SuppressWarnings("deprecation")
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);

            mPreview = (SurfaceView) findViewById(R.id.surface);
            holder = mPreview.getHolder();
            holder.addCallback(this);
            holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            extras = getIntent().getExtras();

            setupButtonClickListeners();
        }

        private void setupButtonClickListeners() {
            Button exitButton = (Button) findViewById(R.id.exitButton);
            exitButton.setOnClickListener(this);
            Button selectVideoButton = (Button) findViewById(R.id.selectVideo);
            selectVideoButton.setOnClickListener(this);
        }

        @Override
        public void onClick(View v) {
            switch (v.getId()) {
            case R.id.exitButton:
                this.finish();
                break;
            case R.id.selectVideo:
                Intent intent = new Intent();
                intent.setType("video/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(
                        Intent.createChooser(intent, "Select Video"), SELECT_VIDEO);
                break;
            }
        }

        public void onActivityResult(int requestCode, int resultCode, Intent data) {
            if (resultCode == RESULT_OK) {
                switch (requestCode) {
                case SELECT_VIDEO:
                    doCleanUp();
                    Uri videoUri = data.getData();
                    String path = getPath(videoUri);
                    boolean success = readFromFile(path);
                    if (success) {
                        // Create a new media player and set the listeners
                        playVideo(path);
                    } else {
                        //do nothing for now
                    }
                    Log.i(TAG, path);
                    break;
                }
            }
        }

        private void playVideo(String path) {
            try {
                mMediaPlayer = new MediaPlayer();
                mMediaPlayer.setDataSource(path);
                // Here is the problem

                synchronized (this) {
                    while (!hasActiveHolder) {
                        try {
                            this.wait();
                        } catch (InterruptedException e) {
                          //Print something
                        }
                    }
                }

                mMediaPlayer.setDisplay(holder);
                mMediaPlayer.prepare();
                mMediaPlayer.setOnBufferingUpdateListener(this);
                mMediaPlayer.setOnCompletionListener(this);
                mMediaPlayer.setOnPreparedListener(this);
                mMediaPlayer.setOnVideoSizeChangedListener(this);
                mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

            } catch (Exception ex) {
                Log.e(TAG, "error: " + ex.getMessage(), ex);
            }
        }

        private void doCleanUp() {
            mVideoWidth = 0;
            mVideoHeight = 0;
            mIsVideoReadyToBePlayed = false;
            mIsVideoSizeKnown = false;
        }

        private boolean readFromFile(String path) {
            File file = new File(path);
            try {
                FileInputStream fis = new FileInputStream(file);
                Log.i(TAG, "File Size: " + file.length());
                videoFile = new byte[(int) file.length()];
                fis.read(videoFile);
                fis.close();
            } catch (Exception ex) {
                ex.printStackTrace();
                return false;
            }
            return true;
        }

        @SuppressWarnings("deprecation")
        private String getPath(Uri uri) {
            String[] projection = { MediaStore.Video.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            int column_index = cursor.getColumnIndex(MediaStore.Video.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }

        @Override
        public void onPrepared(MediaPlayer mediaPlayer) {
            Log.d(TAG, "onPrepared called");
            mIsVideoReadyToBePlayed = true;
            if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
                startVideoPlayback();
            }
        }

        @Override
        public void onCompletion(MediaPlayer mp) {
            Log.d(TAG, "onCompletion called");
        }

        @Override
        public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
            Log.d(TAG, "surfaceChanged called");

        }

        @Override
        public void surfaceCreated(SurfaceHolder arg0) {
            Log.d(TAG, "surfaceCreated called");
            synchronized (this) {
                hasActiveHolder = true;
                this.notifyAll();
             }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder arg0) {
            Log.d(TAG, "surfaceDestroyed called");
            synchronized (this) {
                hasActiveHolder = false;
                this.notifyAll();
            }
        }

        @Override
        public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
            Log.v(TAG, "onVideoSizeChanged called");
            mIsVideoSizeKnown = true;
            mVideoWidth = width;
            mVideoHeight = height;
            if (mIsVideoReadyToBePlayed && mIsVideoSizeKnown) {
                startVideoPlayback();
            }
        }

        private void startVideoPlayback() {
            Log.v(TAG, "startVideoPlayback");
            holder.setFixedSize(mVideoWidth, mVideoHeight);
            mMediaPlayer.start();
        }

        @Override
        public void onBufferingUpdate(MediaPlayer arg0, int percent) {
            Log.d(TAG, "onBufferingUpdate percent:" + percent);

        }

        @Override
        protected void onPause() {
            super.onPause();
            releaseMediaPlayer();
            doCleanUp();
        }

        @Override
        protected void onDestroy() {
            super.onDestroy();
            releaseMediaPlayer();
            doCleanUp();
        }

        private void releaseMediaPlayer() {
            if (mMediaPlayer != null) {
                mMediaPlayer.release();
                mMediaPlayer = null;
            }
        }

    }

我的表面 XML 如下。再一次,不知道为什么在应用程序加载时会显示表面,但我只想在从图库中选择视频后在那里播放。:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

     <android.view.SurfaceView   
        android:id="@+id/surface"  
        android:layout_width="fill_parent"  
        android:layout_height="fill_parent" />

    <Button
        android:id="@+id/changeFilePath"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="78dp"
        android:text="@string/changeFilePath" />

    <Button
        android:id="@+id/recordVideo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/changeFilePath"
        android:layout_centerHorizontal="true"
        android:text="@string/recordVideo" />

    <Button
        android:id="@+id/exitButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/recordVideo"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="49dp"
        android:text="@string/exitButton" />

    <Button
        android:id="@+id/selectVideo"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/recordVideo"
        android:layout_centerHorizontal="true"
        android:text="@string/selectVideo" />  

</RelativeLayout>
4

0 回答 0