android文件分段下载
2016-03-08 23:31
375 查看
以下代码非原创,其中我的分析作为注释添加在代码,特此声明!
FileDownloadThread的代码
public class MainApp extends Activity implements OnClickListener { private static final String TAG = MainApp.class.getSimpleName(); private TextView mMessageView; private ProgressBar mProgressbar; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.progress_activity); findViewById(R.id.download_btn).setOnClickListener(this); mMessageView = (TextView) findViewById(R.id.download_message); mProgressbar = (ProgressBar) findViewById(R.id.download_progress); } @Override public void onClick(View v) { if (v.getId() == R.id.download_btn) { doDownload(); } } /** * ʹ使用Handler来处理UI */ @SuppressLint("HandlerLeak") Handler mHandler = new Handler() { @Override public void handleMessage(Message msg) { //根据key值size获取数据 mProgressbar.setProgress(msg.getData().getInt("size")); //获得已下载长度所占的比例 float temp = (float) mProgressbar.getProgress() / (float) mProgressbar.getMax(); //获得已下载长度所占的百分比 int progress = (int) (temp * 100); if (progress == 100) { Toast.makeText(MainApp.this, "下载成功", Toast.LENGTH_LONG).show(); } mMessageView.setText("已下载:" + progress + " %"); } }; /** * 下载文件 */ private void doDownload() { // 获取手机里的存储介质路径 String path = Environment.getExternalStorageDirectory() + "/amosdownload/"; //创建文件 File file = new File(path); // 如果文件不存在,则按path路径创建文件夹 if (!file.exists()) { file.mkdir(); } // 设置mProgressbar为0 mProgressbar.setProgress(0); //所下载的文件所处的地址 String downloadUrl = "http://gdown.baidu.com/data/wisegame/91319a5a1dfae322/baidu_16785426.apk"; //String downloadUrl = "http://192.168.253.1/My_Learn/uploads/love.txt"; //下载后的文件名 String fileName = "baidu.apk"; //将文件分成5段下载 int threadNum = 5; //下载后的文件所处的绝对文件路径 String filepath = path + fileName; Log.d(TAG, "download file path:" + filepath); //启动下载任务线程 downloadTask task = new downloadTask(downloadUrl, threadNum, filepath); task.start(); } /** * 文件下载线程 * */ class downloadTask extends Thread { private String downloadUrl;//文件下载路径ַ private int threadNum;// 分成段数 private String filePath;// 存储路径ַ private int blockSize;// 每一文件块大小 public downloadTask(String downloadUrl, int threadNum, String fileptah) { this.downloadUrl = downloadUrl; this.threadNum = threadNum; this.filePath = fileptah; } @Override public void run() { FileDownloadThread[] threads = new FileDownloadThread[threadNum]; try { URL url = new URL(downloadUrl); Log.d(TAG, "download file http path:" + downloadUrl); //打开网络连接 URLConnection conn = url.openConnection(); // 获得文件的以byte计算的长度 int fileSize = conn.getContentLength(); if (fileSize <= 0) { System.out.println("无法获得文件信息"); return; } // 设置进度条的最大值 mProgressbar.setMax(fileSize); //每一个文件块的长度 blockSize = (fileSize % threadNum) == 0 ? fileSize / threadNum : fileSize / threadNum + 1; Log.d(TAG, "fileSize:" + fileSize + " blockSize:"+blockSize); File file = new File(filePath); for (int i = 0; i < threads.length; i++) { //让每一个FileDownloadThread线程分段下载 threads[i] = new FileDownloadThread(url, file, blockSize, (i + 1)); //为线程设置一个名字 threads[i].setName("Thread:" + i); threads[i].start(); } //是否下载完成标志 boolean isfinished = false; int downloadedAllSize = 0; while (!isfinished) { isfinished = true; // downloadedAllSize为已下载总长度 downloadedAllSize = 0; for (int i = 0; i < threads.length; i++) { downloadedAllSize += threads[i].getDownloadLength(); if (!threads[i].isCompleted()) { isfinished = false; } } // Message msg = new Message(); msg.getData().putInt("size", downloadedAllSize); mHandler.sendMessage(msg); // Log.d(TAG, "current downloadSize:" + downloadedAllSize); Thread.sleep(1000);// 每个1秒刷新一次 } Log.d(TAG, " all of downloadSize:" + downloadedAllSize); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } }
FileDownloadThread的代码
public class FileDownloadThread extends Thread { private static final String TAG = FileDownloadThread.class.getSimpleName(); /** 是否完成标志 */ private boolean isCompleted = false; /** 已下载长度 */ private int downloadLength = 0; /**生成文件路径 */ private File file; /**文件地址*/ private URL downloadUrl; /** 下载线程编号 */ private int threadId; /** 文件块大小 */ private int blockSize; public FileDownloadThread(URL downloadUrl, File file, int blocksize, int threadId) { this.downloadUrl = downloadUrl; this.file = file; this.threadId = threadId; this.blockSize = blocksize; } @Override public void run() { //缓冲输入流 BufferedInputStream bis = null; RandomAccessFile raf = null; try { URLConnection conn = downloadUrl.openConnection(); //如果为 true,则在允许用户交互 conn.setAllowUserInteraction(true); int startPos = blockSize * (threadId - 1);//该线程开始下载位置 int endPos = blockSize * threadId - 1;//该线程结束下载位置 //用来设置请求头文报属性,这里设置range范围 conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); System.out.println(Thread.currentThread().getName() + " bytes=" + startPos + "-" + endPos); byte[] buffer = new byte[1024]; bis = new BufferedInputStream(conn.getInputStream()); //能对file进行随意读写 raf = new RandomAccessFile(file, "rwd"); //移到所处该线程所应使用的位置 raf.seek(startPos); int len; //每次最多读1024个byte while ((len = bis.read(buffer, 0, 1024)) != -1) { //在buffer中写len个字节到文件file中 raf.write(buffer, 0, len); downloadLength += len; } isCompleted = true; Log.d(TAG, "current thread task has finished,all size:" + downloadLength); } catch (IOException 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 boolean isCompleted() { return isCompleted; } /** * 返回已下载长度 */ public int getDownloadLength() { return downloadLength; } }
相关文章推荐
- ViewTreeObserver.OnPreDrawListener()第一次无法监听或View第一次加载无图像;
- Android开发60条技术经验总结
- Android中自定义Dialog布局的两种方式比较
- 注册谷歌帐号以及用其他镜像解决android sdk的下载问题(已解决)
- 注册谷歌帐号以及用其他镜像解决android sdk的下载问题(已解决)
- 注册谷歌帐号以及用其他镜像解决android sdk的下载问题(已解决)
- android使用AIDL实现跨进程通讯(IPC)
- android开发时R文件丢失解决方案
- Android 快速开发系列 打造万能的ListView GridView 适配器
- Android中自定义样式与View的构造函数中四个参数的意义
- Android中使用AsyncTask实现异步加载
- AndroidStudio创建的LoginActivity分析
- Android开发环境配置
- android自学第二天
- 加载手机磁盘里的图片文件(BitmapFactory.decodeFile()
- Android Notification总结
- Android开发——避免内存泄露
- 4.4.5 Android 属性动画Animator
- Android 中使用Bundle传递大容量数据问题
- android项目的文件介绍