Android uses SurfaceView and TextureView to play video

There is a problem in debugging recently in the project: the adjustment of the camera screen displayed on the app side is a very pitiful problem. The project manager probably couldn't figure it out, so he threw this problem to me, which is a bit of a pit. Because the controls for playing camera video are inherited from surfaceview, so I started with surfaceview, because this control is inherited from surfaceview, and I did some encapsulation. As a result, I wrote the following code directly:

ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
params.width = 你期望的宽度;
params.height = 你期望的高度;
surfaceView.setLayoutParams(params);

After writing it, I secretly rejoiced, thinking that this problem is so simple that even the project manager can't handle it, but I actually managed it, haha, it seems that my technology is better than the manager! So call, quickly compile and run the project, ready to debug. I ran to the door machine in the lobby and called "5652". It was about time to witness the miracle. I found that the height of the video was correct, but there were shadows on both sides. The happy mood immediately disappeared without a trace, a little sad.

Later, he returned to his seat and started a new round of Baidu's journey. Then I carefully looked at the code and found a little pattern. The source code is written like this:

int screenWidth = SDUtil.getScreenWidth();
int height= screenWidth*240/320;
//int height = screenWidth*720/1280;
ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
params.height = height;
surfaceView.setLayoutParams(params);

I took a look, that line comment is the most eye-catching. why? Because this must be modified by the project manager, the reason is so simple, do not need to think too much. So, I opened this line of code again, commented out the line of code above it, recompiled and ran it, and ran to the door machine to test it again. The result was that there were shadows on both sides, which blinded my eyes again. Woohoo, how could there be such a result, I can't figure it out, I really can't figure it out.

I went back to my seat again and thought about it for a long time, as if I was thinking about life.
After that, the test was changed, the test was changed, and the number of times was estimated to be dozens of times. I can't remember the exact number of times, because I was too serious, haha. In the morning meeting the next day, the project manager asked everyone to talk about yesterday’s situation. It was my turn. I said that I was working on this video height problem yesterday. Did the project manager say it was resolved? I whimpered, a little slow to respond, and said not yet. The project manager said it doesn't matter, it doesn't matter, you should be familiar with the code. I secretly rejoiced in my heart, knowing that the project manager couldn't handle it, he had a bottom line. After the morning meeting, I was determined to solve this problem despite not admitting defeat.

In my wit, I started to think again, pondered carefully, and found that this is not the API of Huanxin? Suddenly a flash of light flashed in my mind——"Start with Huanxin's SDK". So I looked at its api. I found that there is a setScalMode method, which is used to set the filling mode of the video. I feel that I have finally found you, and it feels a bit late. So I added this setting method to the code. After running the test, I can really fill the entire layout. Haha, this problem is finally solved, it seems to be solved. So I reported to the project manager, I solved the problem, the project manager stood up excitedly, is this true? I feel like he is happier than me, and I can't believe myself anymore.

The next day, when the project manager had time, he took the mobile phone to test it, and then took a screenshot to let me compare the two photos on the mobile phone and the door phone. He said that it was still a little different. The video was not zoomed, but was covered. My brain seems to be hit by a stone, mushrooms are blue and thin, 10,000 words are omitted here...

The final result is that this problem has not been solved, and we will study the api of the next ring letter in the future.

I'm sorry, I've said so much before entering today's blog topic, I'm really sorry, sorry, sorry, I have to say important things three times.

Android's native video playback APIs include surfaceview, videoview, textureview, etc. I will not list the others, and I may not have used them. Let's talk about the usage of surfaceview and textureview.

1. Play video on surfaceview

1. First look at the layout file of the project (activity_main.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" >

    <SurfaceView
        android:id="@+id/surfaceView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>
</RelativeLayout>

This layout is too simple, so I wrote a surfaceview control, which is fine, because that's what I use.
2. Logic main code

import java.io.IOException;

import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.widget.Button;

public class MainActivity extends Activity {

    private static final String TAG = MainActivity.class.getSimpleName();
    private SurfaceView surfaceview;
    private SurfaceHolder surfaceHolder;
    private Button btnGo;
    private MediaPlayer mediaPlayer;

    private int postion = 0;

    private int screenWidth;
    private int screenHeight;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        getScreenParams();
        findViewById();
        initView();
    }

    /**
     * 获取屏幕宽高
     */
    private void getScreenParams() {
        DisplayMetrics dm = new DisplayMetrics();
        // 获取屏幕信息
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        screenWidth = dm.widthPixels;
        screenHeight = dm.heightPixels;
        Log.e(TAG, "screenWidth==" + screenWidth + ",screenHeight=="
                + screenHeight);
    }

    protected void findViewById() {
        surfaceview = (SurfaceView) findViewById(R.id.surfaceView);
    }

    protected void initView() {
        mediaPlayer = new MediaPlayer();
        surfaceHolder = surfaceview.getHolder();
        surfaceHolder.setKeepScreenOn(true);
        surfaceHolder.addCallback(new SurfaceViewLis());
        // 调整surfaceView的大小

        ViewGroup.LayoutParams params = surfaceview.getLayoutParams();
        params.width = screenWidth;
        params.height = screenHeight;
        surfaceview.setLayoutParams(params);

    }

    private class SurfaceViewLis implements SurfaceHolder.Callback {

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width,
                int height) {

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
            if (postion == 0) {
                try {
                    play();
                } catch (IllegalArgumentException e) {
                    e.printStackTrace();
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (IllegalStateException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {

        }

    }

    public void play() throws IllegalArgumentException, SecurityException,
            IllegalStateException, IOException {
        mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
        AssetFileDescriptor fd = this.getAssets().openFd("video.mp4");
        mediaPlayer.setDataSource(fd.getFileDescriptor(), fd.getStartOffset(),
                fd.getLength());
        mediaPlayer.setLooping(true);
        mediaPlayer.setDisplay(surfaceHolder);
        // 通过异步的方式装载媒体资源
        mediaPlayer.prepareAsync();
        mediaPlayer.setOnPreparedListener(new OnPreparedListener() {
            @Override
            public void onPrepared(MediaPlayer mp) {
                // 装载完毕回调
                mediaPlayer.start();
            }
        });
    }
}

This is mainly to play a video file under the local assets resource. The technology used is mainly SurfaceView+MediaPlayer. In fact, there is no technical content. It is mainly used to test and control the size of the video. It is found that the previous code can still be controlled.

ViewGroup.LayoutParams params = surfaceView.getLayoutParams();
params.width = 你期望的宽度;
params.height = 你期望的高度;
surfaceView.setLayoutParams(params);

That's right, the above code, what's the situation? Why can the native one be controlled, but the one encapsulated by the ring letter can't. Hey, tired! I don't want to do so much, and then watch the TextureView to play the video.

2. TextureView plays local video
1. Layout file

<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" >

    <TextureView
        android:id="@+id/textureview"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

2. The main body of the logic code

package com.example.textureviewdemo;

import java.io.IOException;

import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.media.MediaPlayer.OnVideoSizeChangedListener;
import android.os.Bundle;
import android.app.Activity;
import android.content.res.AssetFileDescriptor;
import android.view.Menu;
import android.view.Surface;
import android.view.TextureView;
import android.view.TextureView.SurfaceTextureListener;

public class MainActivity extends Activity implements SurfaceTextureListener,
        OnBufferingUpdateListener, OnCompletionListener, OnPreparedListener,
        OnVideoSizeChangedListener {
    private TextureView mTextureView;
    private MediaPlayer mMediaPlayer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById();
        init();
    }

    private void init() {
        mTextureView.setSurfaceTextureListener(this);
    }

    private void findViewById() {
        mTextureView = (TextureView) findViewById(R.id.textureview);

    }

    @Override
    public void onVideoSizeChanged(MediaPlayer arg0, int arg1, int arg2) {

    }

    @Override
    public void onPrepared(MediaPlayer arg0) {

    }

    @Override
    public void onCompletion(MediaPlayer arg0) {

    }

    @Override
    public void onBufferingUpdate(MediaPlayer arg0, int arg1) {

    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int arg1,
            int arg2) {
        Surface s = new Surface(surface);
        try {
            mMediaPlayer = new MediaPlayer();
            AssetFileDescriptor fd = this.getAssets().openFd("video.mp4");
            mMediaPlayer.setDataSource(fd.getFileDescriptor(),
                    fd.getStartOffset(), fd.getLength());
            mMediaPlayer.setSurface(s);
            mMediaPlayer.prepare();
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setOnVideoSizeChangedListener(this);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mMediaPlayer.setLooping(true);
            mMediaPlayer.start();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
        mMediaPlayer.stop();
        return true;
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,
            int arg2) {

    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture arg0) {

    }

}

Well, the function of playing video with these two controls is basically realized. The specific differences between them are: 1. TextureView must be available on Android 4.0 and above; 2. TextureView is more convenient and easier to use than SurfaceView; 3. Other

In addition, the source code download address is attached:

SurfaceViewDemo

TextureView Play Video Demo

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325850676&siteId=291194637