TextureView+MediaPlayer播放本地视频

本文介绍如何使用Android的TextureView来播放视频,通过示例代码展示了TextureView的优势及其在硬件加速窗口中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

TextureView介绍

应用程序的视频或者opengl内容往往是显示在一个特别的UI控件中:SurfaceView。SurfaceView的工作方式是创建一个置于应用窗口之后的新窗口。这种方式的效率非常高,因为SurfaceView窗口刷新的时候不需要重绘应用程序的窗口(android普通窗口的视图绘制机制是一层一层的,任何一个子元素或者是局部的刷新都会导致整个视图结构全部重绘一次,因此效率非常低下,不过满足普通应用界面的需求还是绰绰有余),但是SurfaceView也有一些非常不便的限制。因为SurfaceView的内容不在应用窗口上,所以不能使用变换(平移、缩放、旋转等)。也难以放在ListView或者ScrollView中,不能使用UI控件的一些特性比如View.setAlpha()

为了解决这个问题 Android 4.0中引入了TextureView

与SurfaceView相比,TextureView并没有创建一个单独的Surface用来绘制,这使得它可以像一般的View一样执行一些变换操作,设置透明度等。另外,Textureview必须在硬件加速开启的窗口中。


具体做法是先创建TextureView对象,然后实现SurfaceTextureListener接口


    @Override 
    public void onSurfaceTextureAvailable(SurfaceTexture arg0, int arg1, int arg2) { 
    } 
    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture arg0) {
    } 
    @Override 
    public void onSurfaceTextureSizeChanged(SurfaceTexture arg0, int arg1,int arg2) { 
    } 
    @Override 
    public void onSurfaceTextureUpdated(SurfaceTexture arg0) {
    }

下面写一个使用TextureView播放视频Demo


效果图:



代码:


主界面:

package com.lly.videodemo.activitys.fragment;

import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;

import com.lly.videodemo.R;
import com.lly.videodemo.activitys.BaseFragment;
import com.lly.videodemo.activitys.adapter.VideoInfoAdapter;
import com.lly.videodemo.activitys.entity.Video;
import com.lly.videodemo.activitys.utils.Utils;
import com.lly.videodemo.activitys.utils.VideoProvider;

import org.xutils.view.annotation.ContentView;
import org.xutils.view.annotation.Event;
import org.xutils.view.annotation.ViewInject;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;


/**
 * @author 雷子
 */
@ContentView(R.layout.fragment_videoplay_layout)
public class VideoFragment extends BaseFragment implements TextureView.SurfaceTextureListener {

    @ViewInject(R.id.id_textureview)
    private TextureView mTextureView;
    private Surface mSurface;
    private MediaPlayer mediaPlayer;

    //播放器是否准备好
    private boolean isPrepared;

    @ViewInject(R.id.listview)
    private ListView mListView;
    private List<Video> mVideos;

    @Override
    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        initView();
        //扫描本地视频
        scanVideo();

    }

    /**
     * 扫描本地视频
     */
    private void scanVideo() {
        new Thread() {
            @Override
            public void run() {
                super.run();
                mVideos = new ArrayList<>();
                VideoProvider videoProvider = new VideoProvider(getActivity());
                mVideos = videoProvider.getList();
                getActivity().runOnUiThread(new Runnable() {
                    @Override
                    public void run() {
                        if (mVideos.size() > 0) {
                            setAdapter();
                        } else {
//                            showToast("木有扫描到视频!");
                        }
                    }
                });
            }
        }.start();
    }

    /**
     * 填充数据
     */
    private void setAdapter() {
        VideoInfoAdapter infoAdapter = new VideoInfoAdapter(getActivity(), mVideos);
        mListView.setAdapter(infoAdapter);

        mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String path = mVideos.get(position).getPath();
                Log.v("test", "Path:=" + path);
                if (path != null) {
                    changePlay(path);
                }
            }
        });
    }

    /**
     * 初始化View
     */
    private void initView() {
        mTextureView.setSurfaceTextureListener(this);
        //设置16:9
        int screenWeight = Utils.getWindowWidth(getActivity());
        ViewGroup.LayoutParams layoutParams = mTextureView.getLayoutParams();
        layoutParams.height = screenWeight * 9 / 16;
        mTextureView.setLayoutParams(layoutParams);
    }

    @Override
    public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
        mSurface = new Surface(surface);
        initMediaPlayer();
    }

    @Override
    public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    }

    @Override
    public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
        mTextureView = null;
        mSurface = null;
        mediaPlayer.stop();
        mediaPlayer.release();
        return true;
    }

    @Override
    public void onSurfaceTextureUpdated(SurfaceTexture surface) {

    }

    /**
     * 初始化播放器
     */
    public void initMediaPlayer() {
        mediaPlayer = new MediaPlayer();
        try {
            mediaPlayer.setSurface(mSurface);
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
                @Override
                public void onPrepared(MediaPlayer mp) {
                    isPrepared = true;
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 切换播放
     *
     * @param path
     */
    public void changePlay(String path) {
        try {
            mediaPlayer.reset();
            mediaPlayer.setDataSource(path);
            mediaPlayer.prepare();
            mediaPlayer.start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 播放or暂停视频
     */
    public void play() {
        if (mediaPlayer != null) {
            if (mediaPlayer.isPlaying()) {
                mediaPlayer.stop();
            } else {
                try {
                    mediaPlayer.prepare();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                mediaPlayer.start();
            }
        }
    }


    @Event(value = R.id.id_textureview)
    private void onViewClick(View v) {
        switch (v.getId()) {
            case R.id.id_textureview:
                if (isPrepared) {
                    play();
                }
                break;
        }
    }
}

扫描本地视频代码(网上找的):


实体:

package com.lly.videodemo.activitys.entity;

import java.io.Serializable;

public class Video implements Serializable {
    /**
     *
     */
    private static final long serialVersionUID = -7920222595800367956L;
    private int id;
    private String title;
    private String album;
    private String artist;
    private String displayName;
    private String mimeType;
    private String path;
    private long size;
    private long duration;

    /**
     *
     */
    public Video() {
        super();
    }

    /**
     * @param id
     * @param title
     * @param album
     * @param artist
     * @param displayName
     * @param mimeType
     * @param size
     * @param duration
     */
    public Video(int id, String title, String album, String artist,
                 String displayName, String mimeType, String path, long size,
                 long duration) {
        super();
        this.id = id;
        this.title = title;
        this.album = album;
        this.artist = artist;
        this.displayName = displayName;
        this.mimeType = mimeType;
        this.path = path;
        this.size = size;
        this.duration = duration;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getTitle() {
        return title;
    }

    public void setTitle(String title) {
        this.title = title;
    }

    public String getAlbum() {
        return album;
    }

    public void setAlbum(String album) {
        this.album = album;
    }

    public String getArtist() {
        return artist;
    }

    public void setArtist(String artist) {
        this.artist = artist;
    }

    public String getDisplayName() {
        return displayName;
    }

    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }

    public String getMimeType() {
        return mimeType;
    }

    public void setMimeType(String mimeType) {
        this.mimeType = mimeType;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public long getDuration() {
        return duration;
    }

    public void setDuration(long duration) {
        this.duration = duration;
    }

}

package com.lly.videodemo.activitys.utils;

import android.content.Context;
import android.database.Cursor;
import android.provider.MediaStore;

import com.lly.videodemo.activitys.entity.Video;

import java.util.ArrayList;
import java.util.List;


public class VideoProvider {

    private Context mContext;

    public VideoProvider(Context context) {
        this.mContext = context;
    }

    public List<Video> getList() {
        List<Video> list = null;
        if (mContext != null) {
            Cursor cursor = mContext.getContentResolver().query(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI, null, null,
                    null, null);
            if (cursor != null) {
                list = new ArrayList<Video>();
                while (cursor.moveToNext()) {
                    int id = cursor.getInt(cursor
                            .getColumnIndexOrThrow(MediaStore.Video.Media._ID));
                    String title = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.TITLE));
                    String album = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.ALBUM));
                    String artist = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.ARTIST));
                    String displayName = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.DISPLAY_NAME));
                    String mimeType = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.MIME_TYPE));
                    String path = cursor
                            .getString(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.DATA));
                    long duration = cursor
                            .getInt(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));
                    long size = cursor
                            .getLong(cursor
                                    .getColumnIndexOrThrow(MediaStore.Video.Media.SIZE));
                    Video video = new Video(id, title, album, artist, displayName, mimeType, path, size, duration);
                    list.add(video);
                }
                cursor.close();
            }
        }
        return list;
    }
}

下面Listview适配器:


package com.lly.videodemo.activitys.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.media.ThumbnailUtils;
import android.provider.MediaStore;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

import com.lly.videodemo.R;
import com.lly.videodemo.activitys.entity.Video;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * VideoInfoAdapter[v 1.0.0]
 * classes:com.lly.miss.adapter.VideoInfoAdapter
 *
 * @author lileiyi
 * @date 2016/1/26
 * @time 11:48
 * @description
 */
public class VideoInfoAdapter extends BaseAdapter {

    private Context mContext;
    private List<Video> videos;
    private LayoutInflater mLayoutInflater;

    public VideoInfoAdapter(Context context, List<Video> videos) {
        this.mContext = context;
        this.videos = videos;
        mLayoutInflater = LayoutInflater.from(mContext);
    }

    @Override
    public int getCount() {
        return videos.size();
    }

    @Override
    public Object getItem(int position) {
        return videos.get(position);
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        ViewHolder viewHolder;
        if (convertView == null) {
            viewHolder = new ViewHolder();
            convertView = mLayoutInflater.inflate(R.layout.fragment_videolist_item, parent, false);
            viewHolder.imge_pic = (ImageView) convertView.findViewById(R.id.imge_pic);
            viewHolder.tv_duration = (TextView) convertView.findViewById(R.id.tv_duration);
            viewHolder.tv_title = (TextView) convertView.findViewById(R.id.tv_title);
            viewHolder.tv_type = (TextView) convertView.findViewById(R.id.tv_type);
            convertView.setTag(viewHolder);
        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        Video video = videos.get(position);
        viewHolder.tv_duration.setText(transferLongToDate("HH:mm:ss", video.getDuration()));
        viewHolder.tv_title.setText(video.getTitle());
        viewHolder.tv_type.setText(video.getMimeType());
        Bitmap bitmap = getVideoThumbnail(video.getPath(), 80, 80, MediaStore.Video.Thumbnails.MINI_KIND);
        if (bitmap != null) {
            viewHolder.imge_pic.setImageBitmap(bitmap);
        }
        return convertView;
    }

    private class ViewHolder {

        private ImageView imge_pic;
        private TextView tv_duration;
        private TextView tv_title;
        private TextView tv_type;
    }


    /**
     * 获取视频缩略图
     *
     * @param videoPath
     * @param width
     * @param height
     * @param kind
     * @return
     */
    private Bitmap getVideoThumbnail(String videoPath, int width, int height, int kind) {
        Bitmap bitmap = null;
        bitmap = ThumbnailUtils.createVideoThumbnail(videoPath, kind);
        bitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
        return bitmap;
    }

    private String transferLongToDate(String dateFormat, Long millSec) {
        SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
        Date date = new Date(millSec);
        return sdf.format(date);

    }
}


     Demo下载地址:http://download.youkuaiyun.com/detail/ght199266/9419620

 





评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值