Android Studio 下载视频到本地

Android Studio 下载视频到本地,第1张

概述最近在研究视频下载到本地的问题,像爱奇艺,腾讯视频,迅雷看看等等一些视频播放器,如果在一个播放器里面视频下载到一半用户退出App之后,再次登录从头开始,那么就太可悲了,所以在做视频音频类的项目时,要实现的一个功能

最近在研究视频下载到本地的问题,像爱奇艺,腾讯视频,迅雷看看等等一些视频播放器,如果在一个播放器里面视频下载到一半用户退出App之后,再次登录从头开始,那么就太可悲了,所以在做视频音频类的项目时,要实现的一个功能就是断点续传,就是将用户下载的视频或者音频等以字节流的形式存入数据库,下次用户再次下载时,将继续上次数据库的接着下载,这样用户体验就会很好,也大大节省了成本.

好了废话不多说,开始今天的正题.

一、先上效果图

二、使用GreenDao我们需要导入依赖

1.以下在项目gradle依赖中添加

compile 'org.greenrobot:greendao:3.2.2'//依赖 在最后一行插入apply plugin: 'org.greenrobot.greendao' //greenDao在第二行插入greendao {//在依赖导入汇总添加一个自动添加数据库表名的配置依赖 schemaVersion 1 //数据库版本号 daoPackage 'com.example.greendaodemo.database' //设置时生成代码的目录 targetGenDir 'src/main/java' //设置DaoMaster、DaoSession、Dao目录}

2.以下在工程gradle依赖中添加

classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'

3.既然我们要联网下载,读写权限肯定不能忘记了

<uses-permission androID:name="androID.permission.INTERNET"/>  <uses-permission androID:name="androID.permission.ACCESS_NETWORK_STATE"/>  <uses-permission androID:name="androID.permission.WRITE_EXTERNAL_STORAGE"/>  <uses-permission androID:name="androID.permission.READ_EXTERNAL_STORAGE"/>  <uses-permission androID:name="com.Google.androID.provIDers.gsf.permission.READ_GSERVICES" /> 

三、当然还要有实体类写入实体类后,build下make project一下,让他自动生成GreenDao的三个类

import org.greenrobot.greendao.annotation.Entity; import org.greenrobot.greendao.annotation.ID; import org.greenrobot.greendao.annotation.Generated; /**  * author:Created by ZhangPengFei.  * Email: 1271396448@qq.com  * data: 2018/1/18  */ @Entity public class User {  @ID  private Long ID;  private Integer thread_ID;  private Integer start_pos;  private Integer end_pos;  private Integer compelete_size;  private String url;  @Generated(hash = 2041931179)  public User(Long ID,Integer thread_ID,Integer start_pos,Integer end_pos,Integer compelete_size,String url) {   this.ID = ID;   this.thread_ID = thread_ID;   this.start_pos = start_pos;   this.end_pos = end_pos;   this.compelete_size = compelete_size;   this.url = url;  }  @Generated(hash = 586692638)  public User() {  }  public Long getID() {   return this.ID;  }  public voID setID(Long ID) {   this.ID = ID;  }  public Integer getThread_ID() {   return this.thread_ID;  }  public voID setThread_ID(Integer thread_ID) {   this.thread_ID = thread_ID;  }  public Integer getStart_pos() {   return this.start_pos;  }  public voID setStart_pos(Integer start_pos) {   this.start_pos = start_pos;  }  public Integer getEnd_pos() {   return this.end_pos;  }  public voID setEnd_pos(Integer end_pos) {   this.end_pos = end_pos;  }  public Integer getCompelete_size() {   return this.compelete_size;  }  public voID setCompelete_size(Integer compelete_size) {   this.compelete_size = compelete_size;  }  public String getUrl() {   return this.url;  }  public voID setUrl(String url) {   this.url = url;  } } 

四、本人使用了单例模式,所以在全局配置里初始化了数据库的 *** 作

import androID.app.Application; import com.example.greendaodemo.database.DaoMaster; import com.example.greendaodemo.database.DaoSession; import com.example.greendaodemo.database.UserDao; /**  * author:Created by ZhangPengFei.  * Email: 1271396448@qq.com  * data: 2018/1/18  */ public class App extends Application {  public static UserDao userDao;  @OverrIDe  public voID onCreate() {   super.onCreate();   DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(this,"zpf.db",null);   DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());   DaoSession daoSession = daoMaster.newSession();   userDao = daoSession.getUserDao();  } } 

五、因为我们是多线程,所以写一个保存每个线程下载信息的类

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     + "]";  } } 

六、写一个用来记录的类,修改,添加和下载完清空数据库的 *** 作

import androID.util.Log; import com.example.greendaodemo.database.UserDao; import java.util.ArrayList; import java.util.List; import static com.bwIE.mtd.App.userDao; /**  * author:Created by ZhangPengFei.  * Email: 1271396448@qq.com  * data: 2018/1/18  */ public class DownLoadsqlTool {  /**   * 创建下载的具体信息   */  public voID insertInfos(List<DownLoadInfo> infos) {   for (DownLoadInfo info : infos) {    User user = new User(null,info.getThreadID(),info.getStartPos(),info.getEndPos(),info.getCompeleteSize(),info.getUrl());    userDao.insert(user);   }  }  /**   * 得到下载具体信息   */  public List<DownLoadInfo> getInfos(String urlstr) {   List<DownLoadInfo> List = new ArrayList<DownLoadInfo>();   List<User> List1 = userDao.queryBuilder().where(UserDao.PropertIEs.Url.eq(urlstr)).build().List();   for (User user : List1) {    DownLoadInfo infoss = new DownLoadInfo(      user.getThread_ID(),user.getStart_pos(),user.getEnd_pos(),user.getCompelete_size(),user.getUrl());    Log.d("main-----",infoss.toString());    List.add(infoss);   }   return List;  }  /**   * 更新数据库中的下载信息   */  public voID updataInfos(int threadID,String urlstr) {   User user = userDao.queryBuilder()     .where(UserDao.PropertIEs.Thread_ID.eq(threadID),UserDao.PropertIEs.Url.eq(urlstr)).build().unique();   user.setCompelete_size(compeleteSize);   userDao.update(user);  }  /**   * 下载完成后删除数据库中的数据   */  public voID delete(String url) {   userDao.deleteall();  } } 

七、多线程下载的实践类

import androID.content.Context; import androID.os.Handler; import androID.os.Message; import androID.util.Log; import java.io.file; import java.io.inputStream; import java.io.RandomAccessfile; import java.net.httpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; /**  * author:Created by ZhangPengFei.  * Email: 1271396448@qq.com  * data: 2018/1/18  */ 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 DownLoadsqlTool 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 DownLoadsqlTool();  }  //在开始下载之前需要调用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.getUrl()).start();    }   }  }  public voID pause() {   state = Download_State.Pause;  }  public voID delete() {   compelete();   file file = new file(localPath + "/" + filename);   file.delete();  }  public voID compelete() {   sqlTool.delete(urlstr);  }  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,urlstr);    downloadInfos.add(info);   }   DownLoadInfo info = new DownLoadInfo(threadCount - 1,(threadCount - 1)     * range,fileSize - 1,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,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,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();     }    }   }  } } 

八、再写一个接口类

import androID.annotation.Suppresslint; import androID.content.Context; import androID.os.AsyncTask; import androID.os.Handler; import androID.os.Message; import androID.util.Log; /**  * author:Created by ZhangPengFei.  * Email: 1271396448@qq.com  * data: 2018/1/18  */ 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,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();  } } 

九、写一下自己的布局文件

<?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"  tools:context="com.mtd.MainActivity">  <Progressbar   androID:ID="@+ID/progressbar"      androID:layout_wIDth="fill_parent"   androID:layout_height="7.5dp"   androID:layout_centerInParent="true"   androID:layout_marginRight="8dp"   androID:max="100"   androID:progress="100"   androID:visibility="visible" />  <TextVIEw   androID:ID="@+ID/tv_Progress"   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"   androID:layout_below="@ID/progressbar"   androID:layout_centerHorizontal="true"   androID:layout_marginleft="23dp"   androID:layout_marginStart="23dp"   androID:layout_margintop="18dp"   androID:text="" />  <button   androID:ID="@+ID/downLoad"   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"   androID:layout_alignParentBottom="true"   androID:layout_marginleft="100dp"   androID:text="下载" />  <button   androID:ID="@+ID/pause"   androID:layout_toRightOf="@ID/downLoad"   androID:layout_wIDth="wrap_content"   androID:layout_height="wrap_content"   androID:layout_alignParentBottom="true"   androID:layout_marginleft="48dp"   androID:layout_marginStart="48dp"   androID:text="暂停" /> </relativeLayout> 

十、奉上自己的Java代码MainActivity类

import androID.os.Bundle; import androID.os.Environment; import androID.support.v7.app.AppCompatActivity; import androID.util.Log; import androID.vIEw.VIEw; import androID.Widget.button; import androID.Widget.Progressbar; import androID.Widget.TextVIEw; public class MainActivity extends AppCompatActivity {  private final String vIDeoUrl = "http://2449.vod.myqcloud.com/2449_22ca37a6ea9011e5acaaf51d105342e3.f20.mp4";  private TextVIEw tv_progress;//进度显示  private Progressbar progressbar;//进度条  private button downLoad;//下载按钮  private button pause;//暂停按钮  private String path;//下载路径  private int max;  @OverrIDe  protected voID onCreate(Bundle savedInstanceState) {   super.onCreate(savedInstanceState);   setContentVIEw(R.layout.activity_main);   tv_progress = (TextVIEw) findVIEwByID(R.ID.tv_Progress);   progressbar = (Progressbar) findVIEwByID(R.ID.progressbar);   downLoad = (button) findVIEwByID(R.ID.downLoad);   pause = (button) findVIEwByID(R.ID.pause);   path = Environment.getExternalStorageDirectory().getabsolutePath() + "/local";   final DownloadUtil downloadUtil = new DownloadUtil(4,path,"drum.mp4",vIDeoUrl,this);   downloadUtil.setonDownloadListener(new DownloadUtil.OnDownloadListener() {    @OverrIDe    public voID downloadStart(int fileSize) {     Log.i("TAG---fileSize",fileSize + "");     max = fileSize;//文件总长度     progressbar.setMax(fileSize);    }    @OverrIDe    public voID downloadProgress(int downloadedSize) {     Log.i("TAG---downloadedSize",downloadedSize + "");     progressbar.setProgress(downloadedSize);     tv_progress.setText((int) downloadedSize * 100 / max + "%");    }    @OverrIDe    public voID downloadEnd() {     Log.i("TAG---end","End");    }   });   /**    * 下载的点击事件    */   downLoad.setonClickListener(new VIEw.OnClickListener() {    @OverrIDe    public voID onClick(VIEw vIEw) {     downloadUtil.start();    }   });   /**    * 暂停的点击事件    */   pause.setonClickListener(new VIEw.OnClickListener() {    @OverrIDe    public voID onClick(VIEw vIEw) {     downloadUtil.pause();    }   });  } } 

您可能感兴趣的文章:Eclipse NDK迁移到Android Studio的方法示例在启动栏制作android studio启动图标深踩Android Studio 缓存的坑及解决方法Android Studio 3.0 Gradle 配置变更Android Studio设置、改变字体和主题的方法使用Android studio编写一个小的jni程序Android Studio 代码导航快捷键Android Studio多工程引用同一个library项目配置的解决方法Android Studio中Run按钮是灰色的快速解决方法详解Android Studio中Git的配置及协同开发Android Studio配置内嵌JDK的方法AndroidStudio 配置 AspectJ 环境实现AOP的方法详解如何在Android Studio中添加RecyclerView-v7支持包Android Studio 一个工程打包多个不同包名的APK实例详解android studio library 模块中正确引用aar的实例讲解Android Studio中导入module的方法(简单版)Android Studio 引用外部依赖时报错的解决方法android项目从Eclipse迁移到Android studio中常见问题解决方法 总结

以上是内存溢出为你收集整理的Android Studio 下载视频到本地全部内容,希望文章能够帮你解决Android Studio 下载视频到本地所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/web/1142924.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-05-31
下一篇2022-05-31

发表评论

登录后才能评论

评论列表(0条)

    保存