码迷,mamicode.com
首页 > 移动开发 > 详细

Android自定义视频播放器(网络/本地)

时间:2016-07-13 23:24:51      阅读:291      评论:0      收藏:0      [点我收藏+]

标签:

最近因公司项目要求需要写一个播放器,自带的又不太好用,也不太好看。自能自定义啦。查看了很多资料,都没有完善的,还好得以为前辈的指点得以完成感谢Yang。本篇里面我有可能有些地方写得不好(都附上了注释)。希望各路大神指点,虚心受教。

先来个图(源码在后面附上)

技术分享

视频列表里面的数据是本地的,如果你需要使用网络的只需要在此获取服务器的数据展示就行了。播放页面在后面。

package com.eteng.moblieplayer.video;

import android.content.ContentResolver;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.provider.MediaStore;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;

import com.eteng.moblieplayer.BaseActivity;
import com.eteng.moblieplayer.R;
import com.eteng.moblieplayer.adapter.VideoAdapter;
import com.eteng.moblieplayer.beans.VideoBenas;
import com.eteng.moblieplayer.utils.StringTimeUtil;

import org.xutils.view.annotation.ViewInject;

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

/**
 * Created by zqf on 2016/7/6.
 */
public class VideoActivity extends BaseActivity implements AdapterView.OnItemClickListener {

    private ListView video_listview;

    private TextView noresources_tv;

    private VideoBenas beans;
    private List<VideoBenas> data = new ArrayList<VideoBenas>();
    private VideoAdapter adapter;

    private StringTimeUtil util;

    public Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 0:
                    if (data != null && data.size() != 0) {
                        noresources_tv.setVisibility(View.GONE);
                        adapter = new VideoAdapter(data, VideoActivity.this, util);
                        video_listview.setAdapter(adapter);
                    } else {
                        noresources_tv.setVisibility(View.VISIBLE);
                    }

                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        settabtitle("视频列表");
        setrightvisible(View.GONE);
        video_listview = (ListView) findViewById(R.id.video_listviw);
        noresources_tv = (TextView) findViewById(R.id.noresources_tv);
        util = new StringTimeUtil();
        getAllVideo();

        video_listview.setOnItemClickListener(this);
    }

    private void getAllVideo() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                ContentResolver resolver = getContentResolver();
                Uri uri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                //查找的条件
                String[] projection = {MediaStore.Video.Media.TITLE,   //标题
                        MediaStore.Video.Media.DESCRIPTION,     //描述
                        MediaStore.Video.Media.SIZE,        //大小
                        MediaStore.Video.Media.DURATION,    //时长
                        MediaStore.Video.Media.DATA};   //绝对路径
                Cursor cursor = resolver.query(uri, projection, null, null, null);
                while (cursor.moveToNext()) {
                    //判断视频大小>3MB的才添加进来。
                    if (cursor.getLong(2) > 3 * 1024 * 1024) {
                        beans = new VideoBenas();
                        beans.setTitle(cursor.getString(0));
                        beans.setDescribe(cursor.getString(1));
                        beans.setSize(cursor.getLong(2));
                        beans.setLongtime(cursor.getString(3));
                        beans.setPath(cursor.getString(4));
                        data.add(beans);
                    }
                }
                handler.sendEmptyMessage(0);
            }
        }).start();


    }

    @Override
    public void leftonclick() {
        finish();
    }

    @Override
    public void rightonclick() {

    }

    //加载子布局内容
    @Override
    public View setcontent() {
        return View.inflate(VideoActivity.this, R.layout.activity_video, null);
    }

    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        VideoBenas item = data.get(position);
        Intent intent = new Intent(VideoActivity.this, VideoPlayerActivity.class);
        intent.setData(Uri.parse(item.getPath()));
        intent.putExtra("videotitle",item.getTitle());
        startActivity(intent);
    }
}

好了,接下来就是播放器页面了。

package com.eteng.moblieplayer.video;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import com.eteng.moblieplayer.BaseActivity;
import com.eteng.moblieplayer.R;
import com.eteng.moblieplayer.utils.StringTimeUtil;
import com.eteng.moblieplayer.view.VideoView;

/**
 * Created by zqf on 2016/7/6.
 * 播放页面
 */
public class VideoPlayerActivity extends BaseActivity implements MediaPlayer.OnPreparedListener, MediaPlayer.OnInfoListener {
    private VideoView videoView;
    //--播放的地址uri
    private Uri uri;
    private ImageView play_imag, fullview_imag, back_imag, battery_imag;
    private SeekBar mseekBar;
    private TextView videoTitle, SystemTime;
    private TextView videocurrent_time, videototal_time;
    private StringTimeUtil utils;
    private MyBrodCastReceiver receiver;
    //设置电量
    private int leave;
    //手势识别器
    private GestureDetector detector;
    //顶部布局
    private RelativeLayout top_layout;
    //底部布局
    private LinearLayout bottom_layout;
    /**
     * 判断是否播放
     */
    private boolean isPlayer = false;
    /***
     * 判断Activity是否被销毁
     * --true-->销毁
     * --false -->没有销毁
     */
    private boolean isDestory = false;
    //
    private static final int PROGRESS = 1;
    //隐藏顶部和底部的变量
    private static final int HIDE_TOPBOTTOMLAYOUT = 2;

    /**
     * 网络加载等待布局
     */
    private LinearLayout ll_loading;

    /***
     * 出现卡的缓冲加载
     */
    private ProgressBar pg_buff;

    private Handler mhandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case PROGRESS:
                    //设置进度
                    int currenttime = videoView.getCurrentPosition();
                    videocurrent_time.setText(utils.stringfortime(currenttime));
                    //更新seekbar
                    mseekBar.setProgress(currenttime);
                    //更新电量          //电量显示和系统时间可自行设置多久时间更新一次
                    setBattery();
                    //设置系统时间
                    setsystemTime();

                    /***
                     * 得到视频缓存度
                     * --缓存比例值-0~100
                     */
                    int Percentage = videoView.getBufferPercentage();
                    int total = Percentage * mseekBar.getMax();
                    int secondaryprogress = total / 100;
                    mseekBar.setSecondaryProgress(secondaryprogress);

                    if (!isDestory) {
                        mhandler.removeMessages(PROGRESS);
                        //消息的死循环--用于更新播放进度
                        mhandler.sendEmptyMessageDelayed(PROGRESS, 1000);
                    }
                    break;
                case HIDE_TOPBOTTOMLAYOUT:
                    hidelayout();
                    break;
            }
        }
    };


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        settabvisible(View.GONE);
        initView();
        initData();
        setonclick();
        //得到播放地址
        uri = getIntent().getData();
        videoView.setVideoURI(uri); //设置路径
        videoView.setOnPreparedListener(this);  //准备好的监听事件
    }

    private void setsystemTime() {
        SystemTime.setText(utils.getSystemTime());
    }


    private void setBattery() {
        if (leave <= 5) {
            battery_imag.setImageResource(R.mipmap.icv_power_00);
        } else if (leave <= 20) {
            battery_imag.setImageResource(R.mipmap.icv_power_01);
        } else if (leave <= 40) {
            battery_imag.setImageResource(R.mipmap.icv_power_02);
        } else if (leave <= 60) {
            battery_imag.setImageResource(R.mipmap.icv_power_03);
        } else if (leave <= 80) {
            battery_imag.setImageResource(R.mipmap.icv_power_04);
        } else if (leave <= 100) {
            battery_imag.setImageResource(R.mipmap.icv_power_05);
        }
    }

    /***
     * true--显示--false--隐藏
     */
    private boolean isShowLayout = false;


    private void initData() {
        videoTitle.setText(getIntent().getStringExtra("videotitle"));
        isDestory = false;
        utils = new StringTimeUtil();
        //注册电量监听的广播
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction(Intent.ACTION_BATTERY_CHANGED);
        receiver = new MyBrodCastReceiver();
        registerReceiver(receiver, intentFilter);
        //实例化
        detector = new GestureDetector(VideoPlayerActivity.this, new GestureDetector.OnGestureListener() {
            //单击
            @Override
            public boolean onDown(MotionEvent e) {
                Log.e("TAG", "onDown");
                if (isShowLayout) {
                    removeHideTopBottomLayoutMessage();
                    hidelayout();
                } else {
                    sendDelayedHideTopBottomLayout();
                    showLayout();
                }
                return true;
            }

            //长按执行的顺序---1.onDown-->2.onShowPress-->onLongPress
            @Override
            public void onShowPress(MotionEvent e) {
                Log.e("TAG", "onShowPress");
            }

            //单击后执行onDown接着执行的方法
            @Override
            public boolean onSingleTapUp(MotionEvent e) {
                Log.e("TAG", "onSingleTapUp");
                return false;
            }

            //滑动
            @Override
            public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
                Log.e("TAG", "onScroll");
                return false;
            }

            //长按
            @Override
            public void onLongPress(MotionEvent e) {
                Log.e("TAG", "onLongPress");
            }

            @Override
            public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
                return false;
            }
        });
    }


    /***
     * 发送延迟隐藏
     */
    private void sendDelayedHideTopBottomLayout() {
        mhandler.sendEmptyMessageDelayed(HIDE_TOPBOTTOMLAYOUT, 5000);
    }

    /***
     * 移除延迟隐藏的Handler消息
     */
    private void removeHideTopBottomLayoutMessage() {
        mhandler.removeMessages(HIDE_TOPBOTTOMLAYOUT);
    }

    /***
     * 显示的方法
     */
    private void showLayout() {
        isShowLayout = true;
        top_layout.setVisibility(View.VISIBLE);
        bottom_layout.setVisibility(View.VISIBLE);

    }

    /***
     * 隐藏的方法
     */
    private void hidelayout() {
        isShowLayout = false;
        top_layout.setVisibility(View.GONE);
        bottom_layout.setVisibility(View.GONE);
    }

    /***
     * 使用手势适配器
     *
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        super.onTouchEvent(event);
        detector.onTouchEvent(event);
        return true;    //返回true视交由人为处理
    }

    /***
     * 卡或者拖动卡时候出现的回调
     *
     * @param mp
     * @param what
     * @param extra
     * @return
     */
    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        switch (what) {
            case MediaPlayer.MEDIA_INFO_BUFFERING_START:    //开始出现卡或者拖动卡
                pg_buff.setVisibility(View.VISIBLE);
                break;
            case MediaPlayer.MEDIA_INFO_BUFFERING_END:      //结束卡或者拖动卡情况
                pg_buff.setVisibility(View.GONE);
                break;
        }
        return true;
    }

    private class MyBrodCastReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            //返回一个电量的范围值
            leave = intent.getIntExtra("level", 0);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        isDestory = true;
        unregisterReceiver(receiver);
        receiver = null;
        videoView.stopPlayback();
    }

    public void initView() {
        pg_buff = (ProgressBar) findViewById(R.id.pg_buff);
        videoView = (VideoView) findViewById(R.id.videoview);
        ll_loading = (LinearLayout) findViewById(R.id.ll_loading);
        top_layout = (RelativeLayout) findViewById(R.id.topLayout);
        bottom_layout = (LinearLayout) findViewById(R.id.bottomLayout);
        SystemTime = (TextView) findViewById(R.id.videosystemTime);
        battery_imag = (ImageView) findViewById(R.id.videoPower);
        back_imag = (ImageView) findViewById(R.id.videoBack);
        play_imag = (ImageView) findViewById(R.id.videoPlay);
        fullview_imag = (ImageView) findViewById(R.id.videoFullScreen);
        mseekBar = (SeekBar) findViewById(R.id.videoPlayProgress);
        videoTitle = (TextView) findViewById(R.id.videoTitle);
        videocurrent_time = (TextView) findViewById(R.id.videoCurrentProgress);
        videototal_time = (TextView) findViewById(R.id.videototalTime);

    }

    public void setonclick() {
        back_imag.setOnClickListener(onclicklistener);
        play_imag.setOnClickListener(onclicklistener);
        fullview_imag.setOnClickListener(onclicklistener);
        videoView.setOnInfoListener(this);
        mseekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            /***
             *
             * @param seekBar-->自身的seekba
             * @param progress-->seekbar的位置,视频的长度和seekbar的位置一一对应
             * @param fromUser-->如果是人为的拖动值为--true,如seekbar自身在改变的值--false
             */
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser) {
                    videoView.seekTo(progress);
                }
            }

            /**
             * 手指开始拖动时进行回调
             * @param seekBar
             */
            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                removeHideTopBottomLayoutMessage();
            }

            /**
             * 手指离开回调
             * @param seekBar
             */
            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                sendDelayedHideTopBottomLayout();
            }
        });


        /***
         * 视频加载出错时进行回掉
         * --true-->人为处理出错的结果
         */
        videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
            @Override
            public boolean onError(MediaPlayer mp, int what, int extra) {
                Toast.makeText(VideoPlayerActivity.this, "视频出错了", Toast.LENGTH_LONG).show();
                finish();
                return true;
            }
        });
    }


    View.OnClickListener onclicklistener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            switch (v.getId()) {
                case R.id.videoPlay:
                    if (isPlayer) {
                        videoView.pause();
                        play_imag.setImageResource(R.mipmap.icv_play);
                    } else {
                        videoView.start();
                        play_imag.setImageResource(R.mipmap.icv_pause);
                    }
                    isPlayer = !isPlayer;
                    break;
                case R.id.videoBack:
                    finish();
                    videoView.stopPlayback();
                    break;
            }
        }
    };


    @Override
    public void leftonclick() {

    }

    @Override
    public void rightonclick() {

    }

    //设置子布局
    @Override
    public View setcontent() {
        return View.inflate(VideoPlayerActivity.this, R.layout.activity_videoplayer, null);
    }

    /***
     * 监听是否准备好了
     *
     * @param mp
     */
    @Override
    public void onPrepared(MediaPlayer mp) {
        videoView.start();
        play_imag.setImageResource(R.mipmap.icv_pause);
        isPlayer = true;
        //获取总时长
        int duration = videoView.getDuration();
        videototal_time.setText("/" + utils.stringfortime(duration));
        //设置seekbar的最大值
        mseekBar.setMax(duration);
        setsystemTime();
        mhandler.sendEmptyMessageDelayed(PROGRESS, 1000);
        sendDelayedHideTopBottomLayout();
        ll_loading.setVisibility(View.GONE);
    }
}
最后结尾来个图吧!

技术分享

上次忘记发源码地址啦,给补上,抱歉。

源码地址

Android自定义视频播放器(网络/本地)

标签:

原文地址:http://blog.csdn.net/ae_fring/article/details/51898428

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!