android菜鸡提升之路---本地视频播放器实现全部流程

首先,要做一个本地视频播放器,需要克服的第一个困难就是遍历一下本地所有的视频文件:

 刚开始的时候我用的是下面的方法去遍历

Cursor cursor=getContentResolver().query(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,null,
        null
,null,null);
if(cursor!=null&&cursor.moveToFirst()){
    do{
       TextView textView=(TextView)findViewById(R.id.textView);
      //  textView.setText(cursor.getString(1));
        count++;//统计视频个数
    }while (cursor.moveToNext());
}

cursor.close();
Toast.makeText(this,String.valueOf(count),Toast.LENGTH_LONG).show();

非常简单,就是利用了contentprovided的MediaStore方法去找,但是后来发现蛋疼,明明有很多视频,遍历出来只有2个,后来查资料才知道,无法识别.rmvb格式的视频。然后就只能用下面的方法了:(扫描sd卡下全部的视频文件)

 
package com.example.admin.materialdesign;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
import android.media.MediaMetadataRetriever;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.VideoView;

import java.io.EOFException;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import list_been.VideoInfo;
import list_been.Video_recycler_been;

public class Main2Activity extends AppCompatActivity {
private List<Video_recycler_been> video_recycler_beens = new ArrayList<>();
private     ProgressDialog progressDialog ;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);
        search();


    }

/*
开始搜索
 */
        public void search(){

            ScannerAnsyTask ansyTask=new ScannerAnsyTask();
            //videoInfoss=ansyTask.doInBackground();
            ansyTask.execute();



    }
    /*
    异步任务具体
     */
    public class ScannerAnsyTask extends AsyncTask<Void,Integer,List<VideoInfo>> {
        private List<VideoInfo> videoInfos=new ArrayList<VideoInfo>();

        @Override
        protected void onPreExecute(){
           // progressDialog.setTitle("正在搜索。。。");
            progressDialog= new ProgressDialog(Main2Activity.this);
            progressDialog.setMessage("正在搜索。。。");
            progressDialog.setCancelable(false);
            progressDialog.show();



        }
        @Override
        protected List<VideoInfo> doInBackground(Void... params) {
            videoInfos=getVideoFile(videoInfos, Environment.getExternalStorageDirectory());
            //videoInfos=filterVideo(videoInfos);

            return videoInfos;
        }

        @Override
        protected void onProgressUpdate(Integer... values) {
            super.onProgressUpdate(values);
            //videoInfos=filterVideo(videoInfos);
           // Toast.makeText(Main2Activity.this,String.valueOf(values.()),Toast.LENGTH_LONG).show();



        }

        @Override
        protected void onPostExecute(List<VideoInfo> videoInfo) {

            RecyclerView recyclerView=(RecyclerView)findViewById(R.id.rec);
            LinearLayoutManager layoutManager = new LinearLayoutManager(Main2Activity.this);
            recyclerView.setLayoutManager(layoutManager);
            Video_Adapter video_adapter = new Video_Adapter(video_recycler_beens);
            video_adapter.setOnItemClickListener(new Video_Adapter.itemOnclick() {
                @Override
                public void onclick(int position) {
                    Video_recycler_been V = video_recycler_beens.get(position);
                    Intent intent = new Intent(Main2Activity.this,MainActivity.class);
                    intent.putExtra("path",V.getPath()) ;
                    startActivity(intent);
                }
            });
            recyclerView.setAdapter(video_adapter);

            init(videoInfo);


        }

        /**
         * 获取视频文件
         * @param list
         * @param file
         * @return
         */
        private List<VideoInfo> getVideoFile(final List<VideoInfo> list, File file) {

            file.listFiles(new FileFilter() {

                @Override
                public boolean accept(File file) {

                    String name = file.getName();

                    int i = name.indexOf('.');//文件出现“.”字符时算出它所在的位置(“12331.23”)那么i5
                    if (i != -1) {
                        name = name.substring(i);// i后面的字符求出(包括i                        if (name.equalsIgnoreCase(".mp4")
                                || name.equalsIgnoreCase(".3gp")//比较字符串是否一样,和equals类似,但是这个忽略大小写
                                || name.equalsIgnoreCase(".wmv")
                                || name.equalsIgnoreCase(".ts")
                                || name.equalsIgnoreCase(".rmvb")
                                || name.equalsIgnoreCase(".mov")
                                || name.equalsIgnoreCase(".m4v")
                                || name.equalsIgnoreCase(".avi")
                                || name.equalsIgnoreCase(".m3u8")
                                || name.equalsIgnoreCase(".3gpp")
                                || name.equalsIgnoreCase(".3gpp2")
                                || name.equalsIgnoreCase(".mkv")
                                || name.equalsIgnoreCase(".flv")
                                || name.equalsIgnoreCase(".divx")
                                || name.equalsIgnoreCase(".f4v")
                                || name.equalsIgnoreCase(".rm")
                                || name.equalsIgnoreCase(".asf")
                                || name.equalsIgnoreCase(".ram")
                                || name.equalsIgnoreCase(".mpg")
                                || name.equalsIgnoreCase(".v8")
                                || name.equalsIgnoreCase(".swf")
                                || name.equalsIgnoreCase(".m2v")
                                || name.equalsIgnoreCase(".asx")
                                || name.equalsIgnoreCase(".ra")
                               // || name.equalsIgnoreCase(".mp3")//搜索音乐文件
                                || name.equalsIgnoreCase(".ndivx")
                                || name.equalsIgnoreCase(".xvid")) {
                            VideoInfo video = new VideoInfo();
                          //  file.getUsableSpace();//h获取当前分区的大小(可以算D盘大小)
                            video.setDisplayName(file.getName());
                            video.setPath(file.getAbsolutePath());
                            video.setSize(getSizer(file.length()));
                            //获取视频的时长
                            video.setTime(getTimer(file.getAbsolutePath()));


                            Log.i("tga","name"+video.getDisplayName()+"   "+video.getSize());
                            list.add(video);
                            return true;
                        }
                        //判断是不是目录
                    } else if (file.isDirectory()) {
                        getVideoFile(list, file);
                    }
                    return false;
                }
            });

            return list;
        }

        /**
         * 把遍历到的路径和视频名以及时长显示到recyclerview         */
        private List<VideoInfo> filterVideo(List<VideoInfo> videoInfos){
            List<VideoInfo> newVideos=new ArrayList<VideoInfo>();
            for(VideoInfo videoInfo:videoInfos){
                File f=new File(videoInfo.getPath());
                if(f.exists()&&f.isFile()&&f.length()>10485760){
                    newVideos.add(videoInfo);
                    Log.i("TGA","文件大小"+f.length());
                }else {
                    Log.i("TGA","文件太小或者不存在");
                }
            }
            return newVideos;
        }
    }
/*
    将视频的时长转化为 xx:xx:xx的形式(获取的时间以毫秒为单位的一大串数字)
 */
private String getTimer(String address){
    String rTime="0";
    String rhour="0" , rminute="0" , rsecond="0";
    try {
        MediaPlayer mediaPlayer=new MediaPlayer();
        mediaPlayer.setDataSource(address);
        mediaPlayer.prepare();
        int time = mediaPlayer.getDuration();//算出来的时间是以毫秒为单位的,我们显示的时间到秒为止
        time=time/1000;
        int second=time%60;
        time=time/60;
        int minute = time % 60;
       int hour = time / 60;

        if(second>=10)
            rsecond = String.valueOf(second);
        else
            rsecond = "0"+ String.valueOf(second);

        if(minute>=10)
            rminute = String.valueOf(minute);
        else
            rminute = "0"+ String.valueOf(minute);

        if(hour>=10)
            rhour = String.valueOf(hour);
        else
            rhour = "0"+ String.valueOf(hour);

    }
    catch (IOException e){

    }
    rTime=rhour+":"+rminute+":"+rsecond;
    return rTime;
}
/*
 将视频的大小转化为 xMB XKB XB的形式(直接得到的大小是以B为单位的一大串数字)
 */

private String getSizer(long size){
    String rsize="0";
    if(size/1024==0){
        rsize=String.valueOf(size)+"B";

    }
    else {
        size=size/1024;
        if(size/1024==0){
            rsize=String.valueOf(size)+"KB";
        }
        else{
            size=size/1024;
            if(size/1024==0){
                rsize=String.valueOf(size)+"MB";
            }
            else{
                size=size/1024;
                if(size/1024==0){
                    rsize=String.valueOf(size)+"GB";
                }
            }
        }
    }
    return rsize;
}
    /***
     * 根据播放路径设置缩略图
     */
    public Bitmap getVideo_Bitmap(String filePath) {
        Bitmap bitmap = null;
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        try {
            retriever.setDataSource(filePath);
            bitmap = retriever.getFrameAtTime();
        }
        catch(IllegalArgumentException e) {
            e.printStackTrace();
        }
        catch (RuntimeException e) {
            e.printStackTrace();
        }
        finally {
            try {
                retriever.release();
            }
            catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
        return bitmap;
    }

    public void init(List<VideoInfo> videoInfo){

       for(VideoInfo a:videoInfo) {
           Video_recycler_been data = new Video_recycler_been(getVideo_Bitmap(a.getPath()), a.getDisplayName(), a.getTime(), a.getSize(),a.getPath());
           video_recycler_beens.add(data);
       }
        progressDialog.cancel();

    }

 

上面就是具体搜索全部的本地视频的代码,其中我写了一个VideoInfo的实体类,里面放了一些我需要的关于视频的信息,等等也一起贴出来。现在需要说明一下,直接获得视频的大小是以B为单位的一大串数据,那么我写了getSizer这个方法把格式转变了一下,代码有注释。同样的直接获取的视频的时间也是以毫秒为单位的一大串数字,我也同样写了方法去修改一下格式,代码里面有注释。下面给出我的实体类:

package list_been;

/**
 * Created by admin on 2018/3/21.
 */

public class VideoInfo {
    private String Path;
    private String DisplayName;
    private String Size;
    private String Time;

    public String getPath() {
        return Path;
    }

    public void setPath(String path) {
        Path = path;
    }

    public String getDisplayName() {
        return DisplayName;
    }

    public void setDisplayName(String displayName) {
        DisplayName = displayName;
    }

    public String getSize() {
        return Size;
    }

    public void setSize(String size) {
        Size = size;
    }

    public String  getTime() {
        return Time;
    }

    public void setTime(String time) {
        Time = time;
    }
}
 

具体的加什么内容,读者可以自行添加。

到了现在,已经可以把本地视频的名字 大小 时长 路径输出了。接下来,我们还需要把视频的缩略图得到,下面开始,还是先把代码贴出来先:

/***
 * 根据播放路径设置缩略图
 */
public Bitmap getVideo_Bitmap(String filePath) {
    Bitmap bitmap = null;
    MediaMetadataRetriever retriever = new MediaMetadataRetriever();
    try {
        retriever.setDataSource(filePath);
        bitmap = retriever.getFrameAtTime();
    }
    catch(IllegalArgumentException e) {
        e.printStackTrace();
    }
    catch (RuntimeException e) {
        e.printStackTrace();
    }
    finally {
        try {
            retriever.release();
        }
        catch (RuntimeException e) {
            e.printStackTrace();
        }
    }
    return bitmap;
}


这个是网上留传的根据视频路径得到缩略图的方法,我就直接用了,这里要注意一下,我没有把缩略图也写到实体类里面,因为最后你要把视频的全部信息放到recycler的item里面的,在着之前是靠arraylist来缓存数据的,如果你把bitmap也放进去,无疑会很大,最后OMM,所以每次要往item放信息的时候,调用一下getVideo_Bitmap()这个类就可以了;


接下来就是用recyclerview把视频的信息显示出来:

下面是item的布局:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="100dp">
<ImageView
    android:id="@+id/bitmap"
    android:layout_width="100dp"
    android:layout_height="0dp"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="0dp"
    android:layout_marginLeft="0dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_marginBottom="8dp" />

    <TextView
        android:id="@+id/name"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:text="TextView"
        android:textSize="20dp"
        android:textStyle="bold"
        app:layout_constraintLeft_toRightOf="@+id/bitmap"
        android:layout_marginLeft="8dp"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp" />

    <TextView
        android:id="@+id/time"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="16dp"
        app:layout_constraintLeft_toRightOf="@+id/bitmap"
        android:layout_marginLeft="8dp"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toBottomOf="@+id/name" />

    <TextView
        android:id="@+id/size"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="TextView"
        android:textSize="16dp"
        app:layout_constraintLeft_toRightOf="@+id/time"
        android:layout_marginLeft="16dp"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toBottomOf="@+id/name" />

    <TextView
        android:id="@+id/path"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:text="TextView"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="8dp"
        android:layout_marginRight="8dp"
        app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
 

下面是实体类:

package list_been;

import android.graphics.Bitmap;

/**
 * Created by admin on 2018/3/23.
 */

public class Video_recycler_been {
    private Bitmap bitmap;
    private String name;
    private String time;
    private String size;
    private String path;
    public Video_recycler_been(Bitmap bitmap,String name,String time,String size,String path){
        this.bitmap=bitmap;
        this.name=name;
        this.size=size;
        this.time=time;
        this.path=path;
    }

    public Bitmap getBitmap() {
        return bitmap;
    }

    public String getName() {
        return name;
    }

    public String getTime() {
        return time;
    }

    public String getSize() {
        return size;
    }

    public String getPath() {
        return path;
    }
}
 

下面是适配器Adapter:

package com.example.admin.materialdesign;

import android.provider.MediaStore;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.List;

import list_been.Video_recycler_been;

/**
 * Created by admin on 2018/3/23.
 */

public class Video_Adapter extends RecyclerView.Adapter<Video_Adapter.ViewHolder> {
    public interface itemOnclick{
        void onclick(int position);
    }
    private itemOnclick myitemonclick;
    private List<Video_recycler_been> mvideo;

    public void setOnItemClickListener(itemOnclick onItemClickListener ){
        this.myitemonclick=onItemClickListener;

    }

    static class ViewHolder extends RecyclerView.ViewHolder{
        ImageView bitmap;
        TextView name;
        TextView size;
        TextView time;
        View video_view;
        public ViewHolder(View view){
            super(view);
            bitmap=(ImageView)view.findViewById(R.id.bitmap);
            name=(TextView)view.findViewById(R.id.name);
            size=(TextView)view.findViewById(R.id.size);
            time=(TextView)view.findViewById(R.id.time);
            video_view=view;
        }
    }

    public Video_Adapter(List<Video_recycler_been> video){
        mvideo=video;

    }

    @Override
    public ViewHolder onCreateViewHolder(ViewGroup parent , int viewType){
        View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.video_item,parent,false);
        final ViewHolder holder = new ViewHolder(view);

        return holder;
    }

    @Override
    public void onBindViewHolder(ViewHolder holder , final int position){
        Video_recycler_been video_recycler_been=mvideo.get(position);
        holder.size.setText(video_recycler_been.getSize());
        holder.bitmap.setImageBitmap(video_recycler_been.getBitmap());
        holder.name.setText(video_recycler_been.getName());
        holder.time.setText(video_recycler_been.getTime());
        holder.video_view.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                myitemonclick.onclick(position);
            }
        });
    }
    @Override
    public int getItemCount(){
        return mvideo.size();
    }
}
 

这里说明一下,recyclerview没有直接可以在主java文件调用的点击事件监听,所以自己写了一个接口;接口很简单,先定义接口  

public interface itemOnclick{
    void onclick(int position);

}

private itemOnclick myitemonclick;

这里就放了一个点击的方法(抽像的);定义一个全局变量 最后然后写一个类(供主java调用)

public void setOnItemClickListener(itemOnclick onItemClickListener ){
        this.myitemonclick=onItemClickListener;

    }
 





这里放了你的接口,最后在

public void onBindViewHolder(ViewHolder holder , final int position){
    Video_recycler_been video_recycler_been=mvideo.get(position);
    holder.size.setText(video_recycler_been.getSize());
    holder.bitmap.setImageBitmap(video_recycler_been.getBitmap());
    holder.name.setText(video_recycler_been.getName());
    holder.time.setText(video_recycler_been.getTime());
    holder.video_view.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            myitemonclick.onclick(position);
        }
    });
}
 

这里把position传进去;(其实主要就是获得点击时的position)红色就是关键代码

点击了以后就跳到第二个界面去播放了,播放需要一个进度条,这里暂时偷个懒,先用了自带的进度条

MediaController mediaController = new MediaController(this);
 mediaController.setMediaPlayer(videoView);
 videoView.start();
videoView.setMediaController(mediaController);

至于视频播放和视频弹幕再我上一篇博客有介绍,需要的可以去看一下。


  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值