多线程下载播放视频,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; } }}
阅读全文
0 0
- 多线程下载播放视频,Retorfit+RXjava+Banner点击条目播放视频
- 多线程下载+视频播放
- 多线程下载+断点续传+播放视频
- 多条目展示+视频播放
- 最新GreenDao多线程下载,断点续传,播放视频
- Android视频播放项目总结之 点击listview条目调用手机上其他的视频播放器播放
- MVP+RxJava+Reftryfit+多线程断点续传+ijkplayer视频播放
- Rxjava +Retrofit+ok+GreenDao视频播放
- retrofit+Rxjava+Greendao+断点续传+Ijkplayer视频播放
- Retrofit请求数据 多线程下载 Ijkplayer视频播放
- 下载全功能视频播放器
- qqlive播放器下载视频
- 视频播放
- 视频播放
- 播放视频
- 视频播放
- 播放视频
- 播放视频
- hashcode
- 一起来学习Mybatis(四)-配置文件之typeAliases 元素
- PHP设计模式之观察者模式
- A+B for Input-Output Practice (II)
- android 8.0 应用启动崩溃?
- 多线程下载播放视频,Retorfit+RXjava+Banner点击条目播放视频
- 科学计数表示
- JTable常见用法细则
- 初试使用mitmproxy搭建网络代理
- java集合Collection中的All
- 哲学思考之否定之否定规律
- 静态代理VS动态代理
- 关于SVN更新慢的解决方法
- RxDoc mobi Rx开发文档