运用surfaceView与MediaPlayer实现播放视频的功能

时间:2024-01-14 19:49:20

该程序运用了surfaceView与MediaPlayer结合,实现播放视频,surfaceView详情请见

SurfaceView的使用

使用了第三方包Volly里面的方法StringQueue下载json数据,ImageLoader下载图片数据,Volley请见

MyApp:主要作用是创建请求队列,设置为全局变量

public class MyApp extends Application {
private static RequestQueue requestQueue; @Override
public void onCreate() {
super.onCreate();
requestQueue = Volley.newRequestQueue(this);
}
public static RequestQueue getRequestQueue(){
return requestQueue;
}
}

main函数:

public class MainActivity extends AppCompatActivity {

    private ListView listview;
  /*装载数据的集合*/
private List<QSBK.ItemsBean> dataList = new ArrayList<>();
  /*请求队列*/
private RequestQueue requestQueue;
  /*自定义适配器*/
private QSAdapter qsAdapter; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listview = (ListView) findViewById(R.id.listview);
//加载数据
loadData();
//设置适配器
qsAdapter = new QSAdapter(this, dataList);
listview.setAdapter(qsAdapter);
} /**
* 加载数据
*/
private void loadData() {
    //得到请求队列
requestQueue = MyApp.getRequestQueue();
StringRequest stringRequest = new StringRequest(Request.Method.GET, String.format(uri.URL_VIDEO, ), new Response.Listener<String>() {
@Override
public void onResponse(String response) {
//解析gson
Gson gson = new Gson();
QSBK qsbk = gson.fromJson(response, QSBK.class);
          //添加数据,并通知适配器更新
dataList.addAll(qsbk.getItems());
qsAdapter.notifyDataSetChanged();
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
stringRequest.setTag("DATA");
requestQueue.add(stringRequest);
} @Override
protected void onDestroy() {
    //设置标记,请求队列根据标记取消当前请求
requestQueue.cancelAll("DATA");
super.onDestroy();
}
}

QSAdapter:

public class QSAdapter extends QSBaseAdapter implements MediaPlayer.OnPreparedListener {
private ImageLoader imageLoader;
private int currentPosition = -1;
private MediaPlayer mediaPlayer; public QSAdapter(Context context, List<QSBK.ItemsBean> dataList) {
super(context, dataList);
imageLoader = new ImageLoader(MyApp.getRequestQueue(),new MyImageLruCache());
mediaPlayer = new MediaPlayer();
//媒体播放器设置准备监听
mediaPlayer.setOnPreparedListener(this);
}

监听事件作用:开始播放视频

    /**
* 播放器的准备监听
* @param mp
*/
@Override
public void onPrepared(MediaPlayer mp) {
mediaPlayer.start();
}

listView的优化,复用控件,将布局传入ViewHolder中

并利用ImageLoader下载图片

 @Override
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder viewHolder = null;
if(convertView == null){
convertView = layoutInflater.inflate(R.layout.listview_item_video,parent,false);
viewHolder = new ViewHolder(convertView);
convertView.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) convertView.getTag();
}
QSBK.ItemsBean itemsBean = dataList.get(position);
if(itemsBean.getUser()!= null &&itemsBean.getUser().getLogin()!= null&&itemsBean.getUser().getIcon()!= null) {
viewHolder.tvContent.setText(itemsBean.getContent());//设置内容
viewHolder.tvLogin.setText(itemsBean.getUser().getLogin());//设置用户名
      //获得监听
ImageLoader.ImageListener imageListener = imageLoader.getImageListener(viewHolder.icon, R.mipmap.ic_launcher, R.mipmap.ic_launcher);
//头像获取(+ id掉后4位 + "/" + id + "/thumb/" + icon图片名.jpg)
//userIcon======http://pic.qiushibaike.com/system/avtnew/1499/14997026/thumb/20140404194843.jpg
//加载图片
    imageLoader.get(String.format(uri.URL_USER_ICON, itemsBean.getUser().getId() / 10000, itemsBean.getUser().getId(), item sBean.getUser().getIcon()), imageListener);//设置图标
ImageLoader.ImageListener imageListener1 = imageLoader.getImageListener(viewHolder.picUrl, R.mipmap.ic_launcher, R.mipmap.ic_launcher);

动态设置图片的高度:

注意:surfaceView如果不设置固定高度,就没有显示,包裹内容也没有显示

  //动态的设置图片的宽高
ViewGroup.LayoutParams layoutParams = viewHolder.picUrl.getLayoutParams();
layoutParams.height = itemsBean.getPic_size().get(1);
//请求重新布局
viewHolder.picUrl.requestLayout();
//设置视频的高度
ViewGroup.LayoutParams layoutParams1 = viewHolder.sfvLowUrl.getLayoutParams();
layoutParams1.height = itemsBean.getPic_size().get(1);
viewHolder.sfvLowUrl.requestLayout();

为图片设置一个tag,目的是当点击图片时,需要在监听事件中得到该索引,以此来确定播放的视频

  viewHolder.picUrl.setTag(position);
//判断手指点击的视频对应的索引是否等于当前正在显示的页面的索引
 if(currentPosition == position) {
try {
//设置图片不显示,视频显示
viewHolder.picUrl.setVisibility(View.GONE);
viewHolder.sfvLowUrl.setVisibility(View.VISIBLE);
            
//设置数据源为当前手指点击的视频资源
mediaPlayer.setDataSource(context, Uri.parse(itemsBean.getLow_url()));
//异步准备,会调用准备监听
mediaPlayer.prepareAsync();
            //得到操作surfaceView 的接口
SurfaceHolder holder = viewHolder.sfvLowUrl.getHolder();
            //绑定生命周期
holder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) {
//媒体播放器与surfaceView进行绑定
mediaPlayer.setDisplay(holder);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
});
} catch (IOException e) {
e.printStackTrace();
}
}else{
//设置图片显示,视频不显示
viewHolder.sfvLowUrl.setVisibility(View.GONE);
viewHolder.picUrl.setVisibility(View.VISIBLE);
imageLoader.get(itemsBean.getPic_url(),imageListener1);//加载覆盖视频的图片
}
}
return convertView;
}

ViewHolder:

class ViewHolder{
ImageView icon,picUrl;
SurfaceView sfvLowUrl;
TextView tvContent,tvLogin;
public ViewHolder(View view){
icon = (ImageView) view.findViewById(R.id.img_icon);
picUrl = (ImageView) view.findViewById(R.id.img_pic_url);
sfvLowUrl = (SurfaceView) view.findViewById(R.id.sfv_low_url);
tvContent = (TextView) view.findViewById(R.id.tv_content);
tvLogin = (TextView) view.findViewById(R.id.tv_login);
//为图片设置监听,点击图片播放视频
picUrl.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//得到当前索引
currentPosition = (int) v.getTag();
if(mediaPlayer!= null){
          //重置媒体播放器,回到初始状态
mediaPlayer.reset();
} //点击更新适配器,不设置会只在滑动屏幕时才调用getView方法  notifyDataSetChanged(); } }); } }

MyImageLruCache

class MyImageLruCache implements ImageLoader.ImageCache {
private LruCache<String,Bitmap>lruCache;
public MyImageLruCache(){
lruCache = new LruCache<String,Bitmap>((int) (Runtime.getRuntime().maxMemory()/8)){
@Override
protected int sizeOf(String key, Bitmap value) {
return value.getByteCount();
}
};
}
@Override
public Bitmap getBitmap(String url) {
return lruCache.get(url);
}
@Override
public void putBitmap(String url, Bitmap bitmap) {
lruCache.put(url,bitmap);
}
}

QSBKAdapter:

public abstract class QSBaseAdapter extends BaseAdapter {
public Context context;
public List<QSBK.ItemsBean>dataList;
public LayoutInflater layoutInflater;
public QSBaseAdapter(Context context,List<QSBK.ItemsBean>dataList){
this.context = context;
this.dataList = dataList;
layoutInflater = LayoutInflater.from(context);
}
@Override
public int getCount() {
return dataList.size();
} @Override
public Object getItem(int position) {
return dataList.get(position);
} @Override
public long getItemId(int position) {
return position;
} }

qsbkBaseAdapter

xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="10dp"
android:gravity="center_vertical"> <ImageView
android:id="@+id/img_icon"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/ic_launcher"/>
<TextView
android:id="@+id/tv_login"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"
android:text="hahha"
android:textSize="25sp"
android:textColor="#00eedd"/>
</LinearLayout>
<TextView
android:id="@+id/tv_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5dp"
android:textSize="25dp"
android:text="神走位"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<SurfaceView
android:id="@+id/sfv_low_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
<ImageView
android:id="@+id/img_pic_url"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="visible"
android:src="@mipmap/ic_launcher"/>
</FrameLayout> </LinearLayout>

layout

uri:

public class uri {
// 视频
public final static String URL_VIDEO = "http://m2.qiushibaike.com/article/list/video?page=%d"; //头像获取(+ id掉后4位 + "/" + id + "/thumb/" + icon图片名.jpg)
//userIcon======http://pic.qiushibaike.com/system/avtnew/1499/14997026/thumb/20140404194843.jpg
public final static String URL_USER_ICON="http://pic.qiushibaike.com/system/avtnew/%s/%s/thumb/%s";
}

效果:
运用surfaceView与MediaPlayer实现播放视频的功能

播放音频

  android中播放音频可以使用MediaPlayer类来实现,一下是它的一些方法:

              方法名             功能描述
            setDataSource()        设置要播放的音频文件的位置。
            prepare()            在开始播放之前调用这个方法完成准备工作。
            start()               开始或继续播放音频。
            pause()               暂停播放音频。
            reset()              将 MediaPlayer 对象重置到刚刚创建的状态。
            seekTo()             从指定的位置开始播放音频。
            stop()                     停止播放音频。调用这个方法后的 MediaPlayer 对象无法再播放音频。
            release()             释放掉与 MediaPlayer 对象相关的资源。
            isPlaying()             判断当前 MediaPlayer 是否正在播放音频。
            getDuration()           获取载入的音频文件的时长。