多线程下载播放视频,Retorfit+RXjava+Banner点击条目播放视频

来源:互联网 发布:淘宝衣服代购是正品吗 编辑:程序博客网 时间:2024/05/21 16:59

 


     多线程下载播放视频,Retorfit+RXjava+Banner点击条目播放视频



                          效果图

                        

       MP4视频接口
       http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4
       http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4

   在build.gradle里先导入依赖

compile 'com.youth.banner:banner:1.4.9'    compile 'com.github.bumptech.glide:glide:3.7.0'    compile 'com.squareup.okhttp3:okhttp:3.9.0'    compile 'com.squareup.okio:okio:1.13.0'    compile 'com.facebook.fresco:fresco:0.11.0'    compile 'org.greenrobot:greendao:3.2.0'    compile 'io.reactivex:rxjava:1.0.14'    compile 'com.squareup.retrofit2:adapter-rxjava:2.0.0-beta4'    compile 'com.squareup.retrofit2:converter-gson:2.0.0-beta4'    compile 'io.reactivex:rxandroid:1.0.1'    compile 'com.android.support:recyclerview-v7:26.0.0-alpha1'
  再在清单文件里添加权限
 <uses-permission android:name="android.permission.INTERNET"></uses-permission>

  布局文件

 activity——main

<?xml version="1.0" encoding="utf-8"?><RelativeLayout    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="match_parent"    >  <com.youth.banner.Banner      android:id="@+id/ban"      android:layout_width="match_parent"      android:layout_height="200dp"></com.youth.banner.Banner>    <VideoView        android:id="@+id/video_view"        android:layout_below="@+id/ban"        android:layout_width="match_parent"        android:layout_height="200dp" />   <android.support.v7.widget.RecyclerView       android:id="@+id/recy"       android:layout_below="@+id/video_view"       android:layout_width="match_parent"       android:layout_height="wrap_content"></android.support.v7.widget.RecyclerView></RelativeLayout>

item条目布局 /  适配器布局

<?xml version="1.0" encoding="utf-8"?><LinearLayout    xmlns:android="http://schemas.android.com/apk/res/android"    android:layout_width="match_parent"    xmlns:fresco="http://schemas.android.com/apk/res-auto"    android:layout_height="match_parent"    android:orientation="horizontal"    >    <com.facebook.drawee.view.SimpleDraweeView        android:id="@+id/img"        android:layout_width="120dp"        android:layout_height="120dp"        android:src="@mipmap/ic_launcher"        android:layout_margin="10dp"        />        <TextView            android:id="@+id/tv"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_marginTop="40dp"            android:maxLines="2"            android:text="26565465465446"            android:textSize="13dp"            android:textColor="#A9A9A9"            ></TextView></LinearLayout>

Api   Banner接口

 public class Api {    //public static final String BanUrl="http://news-at.zhihu.com/api/4/news/latest";    public static final String BanUrl="http://result.eolinker.com/iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio";}

Img        Glide配合Banner使用

 import android.content.Context;import android.widget.ImageView;import com.bumptech.glide.Glide;import com.youth.banner.loader.ImageLoader;public class Img extends ImageLoader {    @Override    public void displayImage(Context context, Object path, ImageView imageView) {        Glide.with(context)                .load(path)                .into(imageView);    }}

MainActivity

 import android.net.Uri;import android.os.Bundle;import android.support.v7.app.ActionBar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.LinearLayoutManager;import android.support.v7.widget.RecyclerView;import android.view.View;import android.widget.MediaController;import android.widget.Toast;import android.widget.VideoView; import com.facebook.drawee.backends.pipeline.Fresco;import com.google.gson.Gson;import com.youth.banner.Banner;import java.io.IOException;import java.util.ArrayList;import java.util.List;import okhttp3.Call;public class MainActivity extends AppCompatActivity implements Iview {    private Banner mBan;    List<String> list = new ArrayList<>();    private RecyclerView mRecy;    private VideoView videoView;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        //初始化 Fresco        Fresco.initialize(this);        setContentView(R.layout.activity_main);        //隐藏标题        ActionBar actionBar = getSupportActionBar();        actionBar.hide();        initView();        okUrlBanner();        MyPresenter presenter = new MyPresenter(this);        presenter.loadData();    }    private void initView() {        mBan = (Banner) findViewById(R.id.ban);        mRecy = (RecyclerView) findViewById(R.id.recy);       videoView= (VideoView) findViewById(R.id.video_view);        //创建布局管理器        LinearLayoutManager ll = new LinearLayoutManager(this);        mRecy.setLayoutManager(ll);    }    //Banner轮播    private void okUrlBanner() {        OkHttpUtils.getInstance().doGet(Api.BanUrl, new OnUiCallback() {            @Override            public void onFailed(Call call, IOException e) {            }            @Override            public void onSuccess(String result) throws IOException {                Gson gson = new Gson();                Beans beans = gson.fromJson(result, Beans.class);                for (int i = 0; i < beans.getData().size(); i++) {                    list.add(beans.getData().get(i).getImage_url());                }                mBan.setImageLoader(new Img());                mBan.setImages(list);                mBan.start();            }        });    }    //请求数据    @Override    public void setData(List<Beans.DataBean> beanList) {        //创建适配器        ShowAdapter showAdapter = new ShowAdapter(MainActivity.this, beanList);        mRecy.setAdapter(showAdapter);          //条目点击        showAdapter.setmOnItemClickListener(new ShowAdapter.OnItemClickListener() {            @Override            public void onItemClick(View view, int position) {                Toast.makeText(ShowActivity.this,"点击下载播放",Toast.LENGTH_SHORT).show();                DialogUtils.showUpdataDialog(MainActivity.this);                DialogUtils.setPlay(new DialogUtils.autopPlay() {                    @Override                    public void autopplay(String path) {                        //播放视频                        Uri uri = Uri.parse(path);                        videoView.setMediaController(new MediaController(MainActivity.this));                        videoView.setVideoURI(uri);                        videoView.start();                        videoView.requestFocus();                    }                });            }        });    }}

OKHttp封装 1      OkHttpUtils类

 import android.os.Handler;import okhttp3.Call;import okhttp3.Callback;import okhttp3.OkHttpClient;import okhttp3.Request;public class OkHttpUtils {    private Handler handler=new Handler();    public Handler getHandler(){        return handler;    }    private static OkHttpUtils okHttpUtils=new OkHttpUtils();    private OkHttpUtils(){};    public static OkHttpUtils getInstance(){        return okHttpUtils;    }    private OkHttpClient client;    private void initOkHttpClient(){        if(client==null){            client=new OkHttpClient().newBuilder().build();        }    }    public void doGet(String url, Callback callback){        initOkHttpClient();        Request request=new Request.Builder().url(url).build();        Call call=client.newCall(request);        call.enqueue(callback);    }}

OKHttp封装 2     OnUiCallback类

 import android.os.Handler;import java.io.IOException;import okhttp3.Call;import okhttp3.Callback;import okhttp3.Response;public  abstract  class OnUiCallback implements Callback {    private Handler handler=OkHttpUtils.getInstance().getHandler();    public abstract void onFailed(Call call,IOException e);    public abstract void onSuccess(String result)throws IOException;    @Override    public void onFailure(final Call call, final IOException e) {        handler.post(new Runnable() {            @Override            public void run() {                onFailure(call,e);            }        });    }    @Override    public void onResponse(Call call, final Response response) throws IOException {        final String result=response.body().string();        handler.post(new Runnable() {            @Override            public void run() {                try {                    onSuccess(result);                } catch (IOException e) {                    e.printStackTrace();                }            }        });    }}

Retorfit的封装             

 import okhttp3.OkHttpClient;import retrofit2.Retrofit;import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;import retrofit2.converter.gson.GsonConverterFactory;public class RetrofitManager {    private Retrofit mRetrofit;    private String baseUrl;    OkHttpClient client;    private static RetrofitManager mRetrofitManager;    private RetrofitManager(String baseUrl,OkHttpClient client){        this.baseUrl=baseUrl;        this.client=client;        initRetrofit();    }    public static synchronized RetrofitManager getInstance(String baseUrl,OkHttpClient client){        if (mRetrofitManager == null){            mRetrofitManager = new RetrofitManager(baseUrl,client);        }        return mRetrofitManager;    }    private void initRetrofit() {        mRetrofit = new Retrofit.Builder()                .baseUrl(baseUrl)                .addConverterFactory(GsonConverterFactory.create())                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                .client(client)                .build();    }    public <T> T setCreate(Class<T> reqServer){        return mRetrofit.create(reqServer);    }}

RequestApi   接口

  import retrofit2.http.GET;import rx.Observable;public interface RequestApi {    public static final String BASE_URL = "http://result.eolinker.com/";    @GET("iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio")    Observable<Beans> getData(); }

MVP

Model层      IModel接口

 import rx.Observer;  public interface IModel {    void setObSerVer(Observer obSerVer);    //void fenlei(Observer FLobserver);}

MyModel类

 import okhttp3.OkHttpClient;import rx.Observer;import rx.android.schedulers.AndroidSchedulers;import rx.schedulers.Schedulers;public class MyModel implements IModel{    @Override    public void setObSerVer(Observer obSerVer) {        OkHttpClient okclient = new OkHttpClient.Builder().build();            //引用封装类           RetrofitManager.getInstance(RequestApi.BASE_URL,okclient)                .setCreate(RequestApi.class)                .getData()                .observeOn(AndroidSchedulers.mainThread())                .subscribeOn(Schedulers.io())                .subscribe(obSerVer);     //未引用封装类 //        Retrofit retrofit=new Retrofit.Builder()//                .client(okclient)//                .baseUrl(Constant.BASE_URL)//                .addConverterFactory(GsonConverterFactory.create())//                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())//                .build();//        URLUtils urlUtils = retrofit.create(URLUtils.class);//         urlUtils.getObservable()//                 .subscribeOn(Schedulers.io())//                 .observeOn(AndroidSchedulers.mainThread())//                .subscribe(obSerVer);    }}

View层
 import java.util.List; public interface Iview {    void setData(List<Beans.DataBean> beanList);    }

Presenter层    MyPresenter类

  import java.util.List;import rx.Observer; public class MyPresenter {    IModel model;    Iview view;    public MyPresenter(Iview view) {         this.view = view;         model=new MyModel();    }    public void loadData(){        model.setObSerVer(new Observer<Beans>() {            @Override            public void onCompleted() {            }            @Override            public void onError(Throwable e) {            //    Log.i("///", "onError: "+e);            }            @Override            public void onNext(Beans  beans ) {                List<Beans.DataBean> data = beans.getData();                //  Log.i("/////", "onNext: "+list.size());                view.setData(data);            }        });    }}

NetUtils类(多线程下载类)

 import android.util.Log; import java.io.BufferedInputStream;import java.io.File;import java.io.IOException;import java.io.RandomAccessFile;import java.net.HttpURLConnection;import java.net.URL;public class NetUtils {    public static void downloadFile(String downloadUrl, String path, int blockSize, int startPosition){        BufferedInputStream bis = null;        RandomAccessFile raf = null;        try {            File f = new File(path);            if(!f.exists()){                f.createNewFile();            }            URL url = new URL(downloadUrl);            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.setReadTimeout(8000);            conn.setConnectTimeout(8000);//            long start = 0;            if(blockSize > 0){//                //使用线程id来计算 当前线程的开始位置和结束位置//                start = blockSize * threadId;                long end = blockSize + startPosition - 1;                //多线程下载  需要告诉服务器我要请求的是哪部分内容  需要写在请求头里面                conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + end);                Log.i(Thread.currentThread() + "======", "bytes=" + startPosition + "-" + end);            }            int code = conn.getResponseCode();            if(code < 400){                bis = new BufferedInputStream(conn.getInputStream());                raf = new RandomAccessFile(f, "rwd");                raf.seek(startPosition);                int len = 0;                byte[] buff = new byte[1024 * 8];                while((len = bis.read(buff)) != -1){                    synchronized (NetUtils.class){                        raf.write(buff, 0, len);                        if ( DialogUtils.PROGRESS<0){                            DialogUtils.PROGRESS = 0;                        }                        DialogUtils.PROGRESS += len;                    }                }            }        } catch (Exception e) {            e.printStackTrace();        }finally {            if(bis != null){                try {                    bis.close();                } catch (IOException e) {                    e.printStackTrace();                }            }            if(raf != null){                try {                    raf.close();                } catch (IOException e) {                    e.printStackTrace();                }            }        }    }    public static int getFileLength(String downloadUrl){        int len = 0;        try {            URL url = new URL(downloadUrl);            HttpURLConnection conn = (HttpURLConnection) url.openConnection();            conn.setReadTimeout(8000);            conn.setConnectTimeout(8000);            len = conn.getContentLength();        } catch (Exception e) {            e.printStackTrace();        }        return len;    }}

DownloadTask类(多线程下载类)

 public class DownloadTask extends Thread {    String downloadUrl;    String path;    int blockSize;    int startPosition;    public DownloadTask(String downloadUrl, String path, int blockSize, int startPosition) {        this.downloadUrl = downloadUrl;        this.path = path;        this.blockSize = blockSize;        this.startPosition = startPosition;    }    @Override    public void run() {        NetUtils.downloadFile(downloadUrl,path,blockSize,startPosition);    }}

DownloadThread类(多线程下载类)

 public class DownloadThread extends Thread{    private String downloadUrl = "";    private String path; //线程数量 private int threadNum = 4;    public DownloadThread(String downloadUrl, String path) {        this.downloadUrl = downloadUrl;        this.path = path;    }    @Override    public void run() {        int len = NetUtils.getFileLength(downloadUrl);        DialogUtils.MAX_SIZE = len;        //例如  1000kb  3   333        int blockSize = len/threadNum;//        //四舍五入---  让一个数字+0。5在四舍五入 就变成 向上取整//        int blockSize = (int) Math.round(tempSize + 0.5);        //计算出下载块以后   创建线程执行下载操作        for (int i = 0; i < threadNum; i++) {            //计算开始位置            int startPosition = blockSize * i;            //让最后一个线程下载的大小是正好的,  总长度 - 除了最后一个块的大小和            if(i == threadNum - 1){                blockSize = len - blockSize * (threadNum - 1);            }            new DownloadTask(downloadUrl, path, blockSize, startPosition).start();        }    }    public void setThreadNum(int threadNum){        this.threadNum = threadNum;    }}

DialogUtils弹出框

 import android.app.ProgressDialog;import android.content.Context;import android.content.DialogInterface;import android.os.AsyncTask;import android.os.SystemClock;import android.support.v7.app.AlertDialog;import android.widget.Toast; public class DialogUtils {    public static long MAX_SIZE = 0;    public static long PROGRESS = -2;  //  private static File file;   private static String path;    public static void showUpdataDialog(final Context context){        AlertDialog.Builder builder = new AlertDialog.Builder(context);        builder.setTitle("是否下载")                .setMessage("下载吧")                .setNegativeButton("以后再说", null)                .setPositiveButton("立即下载", new DialogInterface.OnClickListener() {                    @Override                    public void onClick(DialogInterface dialogInterface, int i) {                          //支持mp4视频播放格式                    // path= context.getCacheDir() + "/uri=vedio";      // new DownloadThread("http://result.eolinker.com/iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio",    // context.getCacheDir() + "/uri=vedio").start();                 path= context.getCacheDir() + "/911Mothers_2010W-480p.mp4";          new DownloadThread("http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4",         context.getCacheDir() + "/911Mothers_2010W-480p.mp4").start();                        showProgress(context);                    }                }).show();    }     public static interface autopPlay {         void autopplay(String path);     }         public static autopPlay play;         public static void setPlay(autopPlay autopPlay){             play=autopPlay;         };    public static void showProgress(final Context context){        final ProgressDialog pd = new ProgressDialog(context);        pd.setTitle("正在下载");        pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);        pd.setMax(100);        pd.show();        new AsyncTask<String, Integer, String>(){            @Override            protected String doInBackground(String... strings) {                while (PROGRESS+1 < MAX_SIZE){                    SystemClock.sleep(100);                    if (MAX_SIZE>0){                        publishProgress((int)(PROGRESS * 100 / MAX_SIZE));                    }                }                return null;            }            @Override            protected void onPostExecute(String s) {                super.onPostExecute(s);                pd.dismiss();             play.autopplay(path);              //  file=new File(context.getCacheDir() + "/911Mothers_2010W-480p.mp4");               // openApi(context,file);                Toast.makeText(context,"下载完成",Toast.LENGTH_SHORT).show();            }            @Override            protected void onProgressUpdate(Integer... values) {                super.onProgressUpdate(values);                pd.setProgress(values[0]);            }        }.execute();    }         //安装 //http://blog.csdn.net/cfy137000/article/details/70257912//    public static void openApi(Context context, File file){//        String[] command = {"chmod", "777", file.getPath() };//        ProcessBuilder builder = new ProcessBuilder(command);//        try {//            builder.start();//        } catch (IOException e) {//            e.printStackTrace();//        }//        //隐式跳转//        Intent intent=new Intent(Intent.ACTION_VIEW);//        intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);//        intent.setDataAndType(Uri.fromFile(file),"application/vnd.android.package-archive");//        context.startActivity(intent);//    }}

ShowAdapter适配器

 import android.content.Context;import android.support.v7.widget.RecyclerView;import android.util.Log;import android.view.View;import android.view.ViewGroup;import android.widget.TextView; import com.facebook.drawee.backends.pipeline.Fresco;import com.facebook.drawee.interfaces.DraweeController;import com.facebook.drawee.view.SimpleDraweeView;import java.util.List;public class ShowAdapter extends RecyclerView.Adapter<ShowAdapter.MyViewHolder> implements View.OnClickListener{    private  Context context;    private List<Beans.DataBean> chalist;    //利用接口回调实现点击事件    //再实例,然后创建方法    private OnItemClickListener mOnItemClickListener = null;    //点击事件    @Override    public void onClick(View view) {        if (mOnItemClickListener!=null){            mOnItemClickListener.onItemClick(view, (Integer) view.getTag());        }    }    public static interface OnItemClickListener {        void onItemClick(View view , int position);    }    public ShowAdapter(Context context, List<Beans.DataBean> chalist) {        this.context = context;        this.chalist = chalist;        Log.i("33333", "onBindViewHolder: "+chalist.size());    }    @Override    public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {        View view=View.inflate(context, R.layout.rcy_item_line,null);        MyViewHolder holder=new MyViewHolder(view);        //调用点击        view.setOnClickListener(this);        return holder;    }    @Override    public void onBindViewHolder(MyViewHolder holder, final int position) {        holder.tv.setText(chalist.get(position).getContent());//        String[] split = sousuolist.get(position).getImages().split("\\|");//        DraweeController ff= Fresco.newDraweeControllerBuilder()//               .setUri(String.valueOf(split[0]))//                .setAutoPlayAnimations(true)//                .build();//        holder.iv.setController(ff);      //  String s =chalist.get(position).getList().get(0).getImages().split("\\|")[0];        DraweeController ff= Fresco.newDraweeControllerBuilder()                .setUri(chalist.get(position).getImage_url())                .setAutoPlayAnimations(true)                .build();        holder.iv.setController(ff);        //把条目的下标position设置给holder        holder.itemView.setTag(position);       //ImageLoader.getInstance().displayImage(list.get(position).getList().get(0).getImages(),holder.iv);        //点击条目删除//        holder.itemView.setOnClickListener(new View.OnClickListener() {//            @Override//            public void onClick(View view) {//                chalist.remove(position);//               notifyItemRemoved(position);//            }//        });    }    public void setmOnItemClickListener(OnItemClickListener listener){        this.mOnItemClickListener=listener;    }    @Override    public int getItemCount() {        return chalist.size();    }    class MyViewHolder extends RecyclerView.ViewHolder{        public TextView tv;        public SimpleDraweeView iv;        public MyViewHolder(View itemView) {            super(itemView);            tv = itemView.findViewById(R.id.tv);            iv = itemView.findViewById(R.id.img);        }    }}

Bean类

 import java.util.List;/** *  * http://result.eolinker.com/iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio* */public class Beans {    /**     * code : 200     * data : [{"content":"习近平举行仪式欢迎加蓬总统访华","id":10000,"image_url":" */    private int code;    private String msg;    private List<DataBean> data;    public int getCode() {        return code;    }    public void setCode(int code) {        this.code = code;    }    public String getMsg() {        return msg;    }    public void setMsg(String msg) {        this.msg = msg;    }    public List<DataBean> getData() {        return data;    }    public void setData(List<DataBean> data) {        this.data = data;    }    public static class DataBean {        /**         * content : 习近平举行仪式欢迎加蓬总统访华         * id : 10000         * image_url : http://pic32.nipic.com/20130817/9745430_101836881000_2.jpg         * title : 今日头条         * type : 1         * vedio_url : http://2449.vod.myqcloud.com/2449_bfbbfa3cea8f11e5aac3db03cda99974.f20.mp4         */        private String content;        private int id;        private String image_url;        private String title;        private int type;        private String vedio_url;        public String getContent() {            return content;        }        public void setContent(String content) {            this.content = content;        }        public int getId() {            return id;        }        public void setId(int id) {            this.id = id;        }        public String getImage_url() {            return image_url;        }        public void setImage_url(String image_url) {            this.image_url = image_url;        }        public String getTitle() {            return title;        }        public void setTitle(String title) {            this.title = title;        }        public int getType() {            return type;        }        public void setType(int type) {            this.type = type;        }        public String getVedio_url() {            return vedio_url;        }        public void setVedio_url(String vedio_url) {            this.vedio_url = vedio_url;        }    }}