地址接口
public class Api {
public static final String url="http://result.eolinker.com/";
}
////////////////////
public interface SerApi {
// http://result.eolinker.com/iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio
@GET("iYXEPGn4e9c6dafce6e5cdd23287d2bb136ee7e9194d3e9?uri=vedio")
Observable<BeanInfo> getDate();
}
public class MainActivity extends AppCompatActivity implements ModleView {
@BindView(R.id.recyclerview)
RecyclerView recyclerview;
private DownloadUtil mDownloadUtil;
private Banner banner;
private int max;
private List<String> mListImage;
private RelativeLayout ly2;
private LinearLayout ly1;
private Button start;
private Button pause;
private ProgressBar mProgressBar;
private TextView total;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
recyclerview.setLayoutManager(new LinearLayoutManager(this));
Prenter prenter = new Prenter(this);
prenter.setModleView();
}
@Override
public void Modledate(BeanInfo beanInfo) {
final List<BeanInfo.DataBean> list = beanInfo.getData();
MyAdapter adapter = new MyAdapter(list, this);
banner = (Banner) findViewById(R.id.banner);
banner.setImageLoader(new GlideImageLoader());
mListImage = new ArrayList<String>();
mListImage.add(list.get(0).getImage_url());
mListImage.add(list.get(1).getImage_url());
mListImage.add(list.get(2).getImage_url());
banner.setImages(mListImage);
banner.start();
recyclerview.setAdapter(adapter);
adapter.setOnItemClickListener(new MyAdapter.OnItemClickListener() {
@Override
public void onItemClick(View view, int position) {
ly1 = view.findViewById(R.id.ly1);
ly2 = view.findViewById(R.id.ly2);
String title = list.get(position).getTitle();
String vedio_url = list.get(position).getVedio_url();
File f = new File(Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/local/" + title + ".mp4");
if (!f.exists()) {
total = (TextView) view.findViewById(R.id.textView);
start = (Button) view.findViewById(R.id.start);
pause = (Button) view.findViewById(R.id.delete);
mProgressBar = (ProgressBar) view.findViewById(R.id.progressBar);
ly1.setVisibility(View.GONE);
ly2.setVisibility(View.VISIBLE);
getdatapass(vedio_url, title);
} else {
Intent intent = new Intent(MainActivity.this, Main3Activity.class);
String s = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/local/" + title + ".mp4";
intent.putExtra("www", s);
startActivity(intent);
Toast.makeText(MainActivity.this, "播放", Toast.LENGTH_SHORT).show();
}
}
});
}
private void getdatapass(String s, String title) {
String urlString = "http://2449.vod.myqcloud.com/2449_bfbbfa3cea8f11e5aac3db03cda99974.f20.mp4";
String localPath = Environment.getExternalStorageDirectory()
.getAbsolutePath() + "/local";
mDownloadUtil = new DownloadUtil(2, localPath, title + ".mp4", s,
this);
mDownloadUtil.setOnDownloadListener(new DownloadUtil.OnDownloadListener() {
@Override
public void downloadStart(int fileSize) {
// TODO Auto-generated method stub
max = fileSize;
mProgressBar.setMax(fileSize);
}
@Override
public void downloadProgress(int downloadedSize) {
// TODO Auto-generated method stub
mProgressBar.setProgress(downloadedSize);
total.setText((int) downloadedSize * 100 / max + "%");
}
@Override
public void downloadEnd() {
// TODO Auto-generated method stub
ly1.setVisibility(View.VISIBLE);
ly2.setVisibility(View.GONE);
}
});
start.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
mDownloadUtil.start();
}
});
pause.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
mDownloadUtil.pause();
}
});
}
}
activity_main
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:orientation="vertical"
android:layout_height="match_parent"
tools:context="com.zhifei.test.kapian.MainActivity">
<com.youth.banner.Banner
android:layout_width="wrap_content"
android:layout_height="200dp"
android:id="@+id/banner"></com.youth.banner.Banner>
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</android.support.v7.widget.RecyclerView>
</LinearLayout>
这是跳转播放视频页面
public class Main3Activity extends AppCompatActivity {
private JCVideoPlayerStandard jcVideoPlayerStandard;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main3);
Intent intent = getIntent();
String s1 = intent.getStringExtra("www");
jcVideoPlayerStandard = (JCVideoPlayerStandard) findViewById(R.id.jiecao_Player);
jcVideoPlayerStandard.setUp(s1, jcVideoPlayerStandard.SCREEN_LAYOUT_NORMAL, "视频标题");
}
}
activity_main3
<?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="match_parent"
>
<fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard
android:id="@+id/jiecao_Player"
android:layout_width="match_parent"
android:layout_height="200dp">
</fm.jiecao.jcvideoplayer_lib.JCVideoPlayerStandard>
</android.support.constraint.ConstraintLayout>
这是轮播图加载的图片类
public class GlideImageLoader extends ImageLoader {
@Override
public void displayImage(Context context, Object path, ImageView imageView) {
//使用glide加载图片
Glide.with(context).load(path).into(imageView);
}
}
V层
public interface ViewBean {
void Viewbean(BeanInfo beanInfo);
}
工具类Utils
public class DownlaodSqlTool {
private DownLoadHelper dbHelper;
public DownlaodSqlTool(Context context){
dbHelper=new DownLoadHelper(context);
}
/**
* 创建下载的具体信息
*/
public void insertInfos(List<DownloadInfo> infos) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
for (DownloadInfo info : infos) {
String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";
Object[] bindArgs = { info.getThreadId(), info.getStartPos(),
info.getEndPos(), info.getCompeleteSize(), info.getUrl() };
database.execSQL(sql, bindArgs);
}
}
/**
* 得到下载具体信息
*/
public List<DownloadInfo> getInfos(String urlstr) {
List<DownloadInfo> list = new ArrayList<DownloadInfo>();
SQLiteDatabase database = dbHelper.getWritableDatabase();
String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";
Cursor cursor = database.rawQuery(sql, new String[] { urlstr });
while (cursor.moveToNext()) {
DownloadInfo info = new DownloadInfo(cursor.getInt(0),
cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),
cursor.getString(4));
list.add(info);
}
return list;
}
/**
* 更新数据库中的下载信息
*/
public void updataInfos(int threadId, int compeleteSize, String urlstr) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
String sql = "update download_info set compelete_size=? where thread_id=? and url=?";
Object[] bindArgs = { compeleteSize, threadId, urlstr };
database.execSQL(sql, bindArgs);
}
/**
* 关闭数据库
*/
public void closeDb() {
dbHelper.close();
}
/**
* 下载完成后删除数据库中的数据
*/
public void delete(String url) {
SQLiteDatabase database = dbHelper.getWritableDatabase();
database.delete("download_info", "url=?", new String[] { url });
}
}
public class DownLoadHelper extends SQLiteOpenHelper{
private static final String SQL_NAME = "download.db";
private static final int DOWNLOAD_VERSION=1;
public DownLoadHelper(Context context) {
super(context, SQL_NAME, null, DOWNLOAD_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "
+ "start_pos integer, end_pos integer, compelete_size integer,url char)");
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
}
}
/
public class DownloadHttpTool {
/**
*
* 利用Http协议进行多线程下载具体实践类
*/
private static final String TAG = DownloadHttpTool.class.getSimpleName();
private int threadCount;//线程数量
private String urlstr;//URL地址
private Context mContext;
private Handler mHandler;
private List<DownloadInfo> downloadInfos;//保存下载信息的类
private String localPath;//目录
private String fileName;//文件名
private int fileSize;
private DownlaodSqlTool sqlTool;//文件信息保存的数据库操作类
private enum Download_State {
Downloading, Pause, Ready;//利用枚举表示下载的三种状态
}
private Download_State state = Download_State.Ready;//当前下载状态
private int globalCompelete = 0;//所有线程下载的总数
public DownloadHttpTool(int threadCount, String urlString,
String localPath, String fileName, Context context, Handler handler) {
super();
this.threadCount = threadCount;
this.urlstr = urlString;
this.localPath = localPath;
this.mContext = context;
this.mHandler = handler;
this.fileName = fileName;
sqlTool = new DownlaodSqlTool(mContext);
}
//在开始下载之前需要调用ready方法进行配置
public void ready() {
Log.w(TAG, "ready");
globalCompelete = 0;
downloadInfos = sqlTool.getInfos(urlstr);
if (downloadInfos.size() == 0) {
initFirst();
} else {
File file = new File(localPath + "/" + fileName);
if (!file.exists()) {
sqlTool.delete(urlstr);
initFirst();
} else {
fileSize = downloadInfos.get(downloadInfos.size() - 1)
.getEndPos();
for (DownloadInfo info : downloadInfos) {
globalCompelete += info.getCompeleteSize();
}
Log.w(TAG, "globalCompelete:::" + globalCompelete);
}
}
}
public void start() {
Log.w(TAG, "start");
if (downloadInfos != null) {
if (state == Download_State.Downloading) {
return;
}
state = Download_State.Downloading;
for (DownloadInfo info : downloadInfos) {
Log.v(TAG, "startThread");
new DownloadThread(info.getThreadId(), info.getStartPos(),
info.getEndPos(), info.getCompeleteSize(),
info.getUrl()).start();
}
}
}
public void pause() {
state = Download_State.Pause;
sqlTool.closeDb();
}
public void delete(){
compelete();
File file = new File(localPath + "/" + fileName);
file.delete();
}
public void compelete() {
sqlTool.delete(urlstr);
sqlTool.closeDb();
}
public int getFileSize() {
return fileSize;
}
public int getCompeleteSize() {
return globalCompelete;
}
//第一次下载初始化
private void initFirst() {
Log.w(TAG, "initFirst");
try {
URL url = new URL(urlstr);
HttpURLConnection connection = (HttpURLConnection) url
.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
fileSize = connection.getContentLength();
Log.w(TAG, "fileSize::" + fileSize);
File fileParent = new File(localPath);
if (!fileParent.exists()) {
fileParent.mkdir();
}
File file = new File(fileParent, fileName);
if (!file.exists()) {
file.createNewFile();
}
// 本地访问文件
RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");
accessFile.setLength(fileSize);
accessFile.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
int range = fileSize / threadCount;
downloadInfos = new ArrayList<DownloadInfo>();
for (int i = 0; i < threadCount - 1; i++) {
DownloadInfo info = new DownloadInfo(i, i * range, (i + 1) * range
- 1, 0, urlstr);
downloadInfos.add(info);
}
DownloadInfo info = new DownloadInfo(threadCount - 1, (threadCount - 1)
* range, fileSize - 1, 0, urlstr);
downloadInfos.add(info);
sqlTool.insertInfos(downloadInfos);
}
//自定义下载线程
private class DownloadThread extends Thread {
private int threadId;
private int startPos;
private int endPos;
private int compeleteSize;
private String urlstr;
private int totalThreadSize;
public DownloadThread(int threadId, int startPos, int endPos,
int compeleteSize, String urlstr) {
this.threadId = threadId;
this.startPos = startPos;
this.endPos = endPos;
totalThreadSize = endPos - startPos + 1;
this.urlstr = urlstr;
this.compeleteSize = compeleteSize;
}
@Override
public void run() {
HttpURLConnection connection = null;
RandomAccessFile randomAccessFile = null;
InputStream is = null;
try {
randomAccessFile = new RandomAccessFile(localPath + "/"
+ fileName, "rwd");
randomAccessFile.seek(startPos + compeleteSize);
URL url = new URL(urlstr);
connection = (HttpURLConnection) url.openConnection();
connection.setConnectTimeout(5000);
connection.setRequestMethod("GET");
connection.setRequestProperty("Range", "bytes="
+ (startPos + compeleteSize) + "-" + endPos);
is = connection.getInputStream();
byte[] buffer = new byte[1024];
int length = -1;
while ((length = is.read(buffer)) != -1) {
randomAccessFile.write(buffer, 0, length);
compeleteSize += length;
Message message = Message.obtain();
message.what = threadId;
message.obj = urlstr;
message.arg1 = length;
mHandler.sendMessage(message);
sqlTool.updataInfos(threadId, compeleteSize, urlstr);
Log.w(TAG, "Threadid::" + threadId + " compelete::"
+ compeleteSize + " total::" + totalThreadSize);
if (compeleteSize >= totalThreadSize) {
break;
}
if (state != Download_State.Downloading) {
break;
}
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
randomAccessFile.close();
connection.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
public class DownloadInfo {
/**
* 保存每个下载线程下载信息类
*
*/
private int threadId;// 下载器id
private int startPos;// 开始点
private int endPos;// 结束点
private int compeleteSize;// 完成度
private String url;// 下载文件的URL地址
public DownloadInfo(int threadId, int startPos, int endPos,
int compeleteSize, String url) {
this.threadId = threadId;
this.startPos = startPos;
this.endPos = endPos;
this.compeleteSize = compeleteSize;
this.url = url;
}
public DownloadInfo() {
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getThreadId() {
return threadId;
}
public void setThreadId(int threadId) {
this.threadId = threadId;
}
public int getStartPos() {
return startPos;
}
public void setStartPos(int startPos) {
this.startPos = startPos;
}
public int getEndPos() {
return endPos;
}
public void setEndPos(int endPos) {
this.endPos = endPos;
}
public int getCompeleteSize() {
return compeleteSize;
}
public void setCompeleteSize(int compeleteSize) {
this.compeleteSize = compeleteSize;
}
@Override
public String toString() {
return "DownloadInfo [threadId=" + threadId + ", startPos=" + startPos
+ ", endPos=" + endPos + ", compeleteSize=" + compeleteSize
+ "]";
}
}
/
/**
* 将下载方法封装在此类
* 提供下载,暂停,删除,以及重置的方法
*/
public class DownloadUtil {
private DownloadHttpTool mDownloadHttpTool;
private OnDownloadListener onDownloadListener;
private int fileSize;
private int downloadedSize = 0;
@SuppressLint("HandlerLeak")
private Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
// TODO Auto-generated method stub
super.handleMessage(msg);
int length = msg.arg1;
synchronized (this) {//加锁保证已下载的正确性
downloadedSize += length;
}
if (onDownloadListener != null) {
onDownloadListener.downloadProgress(downloadedSize);
}
if (downloadedSize >= fileSize) {
mDownloadHttpTool.compelete();
if (onDownloadListener != null) {
onDownloadListener.downloadEnd();
}
}
}
};
public DownloadUtil(int threadCount, String filePath, String filename,
String urlString, Context context) {
mDownloadHttpTool = new DownloadHttpTool(threadCount, urlString,
filePath, filename, context, mHandler);
}
//下载之前首先异步线程调用ready方法获得文件大小信息,之后调用开始方法
public void start() {
new AsyncTask<Void,Void,Void>() {
@Override
protected Void doInBackground(Void... arg0) {
// TODO Auto-generated method stub
mDownloadHttpTool.ready();
return null;
}
@Override
protected void onPostExecute(Void result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
fileSize = mDownloadHttpTool.getFileSize();
downloadedSize = mDownloadHttpTool.getCompeleteSize();
Log.w("Tag", "downloadedSize::" + downloadedSize);
if (onDownloadListener != null) {
onDownloadListener.downloadStart(fileSize);
}
mDownloadHttpTool.start();
}
}.execute();
}
public void pause() {
mDownloadHttpTool.pause();
}
public void delete(){
mDownloadHttpTool.delete();
}
public void reset(){
mDownloadHttpTool.delete();
start();
}
public void setOnDownloadListener(OnDownloadListener onDownloadListener) {
this.onDownloadListener = onDownloadListener;
}
//下载回调接口
public interface OnDownloadListener {
public void downloadStart(int fileSize);
public void downloadProgress(int downloadedSize);//记录当前所有线程下总和
public void downloadEnd();
}
}
P层
public class Prenter implements ViewBean {
private ModleView modleView;
private ModleViewM modleViewM;
public Prenter(ModleView modleView) {
this.modleView = modleView;
modleViewM = new ModleViewM();
}
public void setModleView() {
modleViewM.Getdata(this);
}
@Override
public void Viewbean(BeanInfo beanInfo) {
modleView.Modledate(beanInfo);
}
}
M层
public class ModleViewM {
public void Getdata(final ViewBean viewBean) {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(5, TimeUnit.SECONDS)
.build();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.baseUrl(Api.url)
.client(okHttpClient)
.build();
SerApi api = retrofit.create(SerApi.class);
Observable<BeanInfo> date = api.getDate();
date.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<BeanInfo>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
}
@Override
public void onNext(BeanInfo beanInfo) {
viewBean.Viewbean(beanInfo);
}
});
}
}
M层接口
public interface ModleView {
void Modledate(BeanInfo beanInfo);
}
注册页面,初始化Fresco
public class MyAppliction extends Application {
@Override
public void onCreate() {
super.onCreate();
Fresco.initialize(this);
}
}
适配器
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHodler> implements View.OnClickListener {
private List<BeanInfo.DataBean> list;
private Context context;
private OnItemClickListener mOnItemClickListener = null;
//define interface
public interface OnItemClickListener {
void onItemClick(View view, int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
this.mOnItemClickListener = listener;
}
@Override
public void onClick(View view) {
if (mOnItemClickListener != null) {
mOnItemClickListener.onItemClick(view, (Integer) view.getTag());
}
}
public MyAdapter(List<BeanInfo.DataBean> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public ViewHodler onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.item, null);
view.setOnClickListener(this);
return new ViewHodler(view);
}
@Override
public void onBindViewHolder(ViewHodler holder, int position) {
holder.text.setText(list.get(position).getContent());
// String url = list.get(position).getImage_url();
//
// Glide.with(context).load(url).into(image);
holder.image.setImageURI(Uri.parse(list.get(position).getImage_url()));
//将position保存在itemView的Tag中,以便点击时进行获取
holder.itemView.setTag(position);
}
@Override
public int getItemCount() {
return list.size();
}
public class ViewHodler extends RecyclerView.ViewHolder {
private final SimpleDraweeView image;
private final TextView text;
public ViewHodler(View itemView) {
super(itemView);
image = itemView.findViewById(R.id.image);
text = itemView.findViewById(R.id.text);
}
}
}
清单文件中的权限,记得在下面添加跳转页面,这里就不写了
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.INTERNET" />
依赖,用到的,没用到的全上了
compile 'com.squareup.retrofit2:retrofit:2.1.0'//retrofit
compile 'com.google.code.gson:gson:2.6.2'//Gson 库
//下面两个是RxJava 和RxAndroid
compile 'io.reactivex:rxjava:1.1.0'
compile 'io.reactivex:rxandroid:1.1.0'
compile 'com.squareup.retrofit2:converter-gson:2.1.0'//转换器,请求结果转换成Model
compile 'com.squareup.retrofit2:adapter-rxjava:2.1.0'//配合Rxjava 使用
compile 'com.jakewharton:butterknife:8.6.0'
compile 'com.github.bumptech.glide:glide:3.7.0'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.6.0'
compile 'com.android.support:recyclerview-v7:21.0.0'
compile 'com.youth.banner:banner:1.4.9'
compile 'com.facebook.fresco:fresco:0.9.0+'
compile 'fm.jiecao:jiecaovideoplayer:4.8.3'
compile 'com.github.bumptech.glide:glide:3.7.0'
compile 'com.android.support:recyclerview-v7:21.0.+'