Android版多线程下载器核心代码分享
首先给大家分享多线程下载核心类:
- package com.example.urltest;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.RandomAccessFile;
- import java.net.HttpURLConnection;
- import java.net.MalformedURLException;
- import java.net.URL;
- import java.net.URLDecoder;
- public class DownUtil {
- private String urlPath;
- private String defaultTargetPath;
- private int threadNum;
- private DownThread[] threads;
- private int fileSize = -100;
- private String fileName = "未知文件";
- private boolean isGetFileInformation = false;
- public DownUtil(String urlPath, int threadNum) {
- this.urlPath = urlPath;
- this.defaultTargetPath = "/mnt/sdcard/";
- this.threadNum = threadNum;
- this.threads = new DownThread[threadNum];
- }
- private HttpURLConnection connection() throws IOException {
- URL url = new URL(urlPath);
- HttpURLConnection connection = (HttpURLConnection) url.openConnection();
- connection.setConnectTimeout(5 * 1000);
- connection.setRequestMethod("GET");
- connection.setRequestProperty(
- "Accept",
- "image/gif, image/jpeg, image/pjpeg, image/pjpeg, "
- + "application/x-shockwave-flash, application/xaml+xml, "
- + "application/vnd.ms-xpsdocument, application/x-ms-xbap, "
- + "application/x-ms-application, application/vnd.ms-excel, "
- + "application/vnd.ms-powerpoint, application/msword, */*");
- connection.setRequestProperty("Accept-Language", "zh-CN");
- connection.setRequestProperty("Charset", "UTF-8");
- connection.setRequestProperty("Connection", "Keep-Alive");
- return connection;
- }
- public void getFileInformation() throws IOException {
- HttpURLConnection connection = connection();
- connection.setInstanceFollowRedirects(false);
- int status = connection.getResponseCode();
- if (status != -1) {
- if (status / 100 == 3) {// 当响应码是302时,说明可以获得重定向的资源地址
- // 得到文件名(此方法不能正确的获取所有url的资源文件名)
- String name = connection.getHeaderField("Location");
- name = URLDecoder.decode(name.substring(name.lastIndexOf('/')), "UTF-8");
- this.fileName = name;
- }
- // 得到文件大小
- this.fileSize = connection.getContentLength();
- if (fileSize <= 0) {
- isGetFileInformation = false;
- } else {
- isGetFileInformation = true;
- }
- connection.disconnect();
- } else {
- connection.disconnect();
- isGetFileInformation = false;
- }
- }
- public boolean download(String targetPath, String fileName) throws IOException {
- if (isGetFileInformation == false) {
- getFileInformation();
- }
- if (isGetFileInformation) {
- String absFilePath = targetPath + fileName;
- int currentPartSize = (fileSize / threadNum) + 1;// 每一部分需要下载的大小,注意此处加1是为了避免不能整除带来的误差
- RandomAccessFile file = new RandomAccessFile(absFilePath, "rw");
- file.setLength(fileSize);
- file.close();
- for (int i = 0; i < threadNum; i++) {
- int startPos = i * currentPartSize;
- RandomAccessFile currentPart = new RandomAccessFile(absFilePath, "rw");// 打开目标文件
- currentPart.seek(startPos);
- threads[i] = new DownThread(startPos, currentPartSize, currentPart);
- threads[i].start();
- }
- return true;
- } else {
- return false;
- }
- }
- public boolean download() throws IOException {
- if (isGetFileInformation) {
- return download(this.defaultTargetPath, this.getFileName());
- } else {
- getFileInformation();
- return download(this.defaultTargetPath, this.getFileName());
- }
- }
- public double getCompleteRate() {
- int sumSize = 0;
- for (int i = 0; i < threadNum; i++) {
- sumSize += threads[i].length;
- }
- return sumSize * 1.0 / fileSize;
- }
- public String getDefaultTargetPath() {
- return defaultTargetPath;
- }
- public int getFileSize() {
- return fileSize;
- }
- public String getFileName() {
- return fileName;
- }
- public void setFileName(String fileName) {
- this.fileName = fileName;
- }
- public boolean isGetFileInformation() {
- return isGetFileInformation;
- }
- private class DownThread extends Thread {
- private int startPos;
- private int currentPartSize;
- private RandomAccessFile currentPart;
- int length; // 该线程已经下载的字节数
- public DownThread(int startPos, int currentPartSize, RandomAccessFile currentPart) {
- this.startPos = startPos;
- this.currentPartSize = currentPartSize;
- this.currentPart = currentPart;
- }
- @Override
- public void run() {
- try {
- HttpURLConnection connection = connection();
- int endPos = startPos + currentPartSize;
- connection.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos);// 使用http来设置一个文件的下载范围(startPos-endPos)
- InputStream inStream = connection.getInputStream();
- // inStream.skip(startPos); // skip函数有时候不起作用
- byte[] buffer = new byte[1024];
- int hasRead = 0;
- while (length < currentPartSize && (hasRead = inStream.read(buffer)) > 0) {
- currentPart.write(buffer, 0, hasRead);
- length = length + hasRead;
- }
- inStream.close();
- currentPart.close();
- connection.disconnect();
- } catch (MalformedURLException e2) {
- e2.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
下面是界面的逻辑代码:
- package com.example.urltest;
- import android.app.Activity;
- import android.app.AlertDialog;
- import android.app.ProgressDialog;
- import android.content.DialogInterface;
- import android.os.Bundle;
- import android.os.Message;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.widget.Button;
- import android.widget.EditText;
- import android.widget.ProgressBar;
- import android.widget.TextView;
- import android.widget.Toast;
- import java.io.IOException;
- import java.util.Timer;
- import java.util.TimerTask;
- public class MultiThreadDown extends Activity {
- EditText url, target;
- Button downButton;
- ProgressBar bar;
- ProgressDialog progressDialog;
- View downView;
- DownUtil downUtil;
- private int mDownStatus;
- private int threadNum = 6; // 默认的线程数
- android.os.Handler handler = new android.os.Handler() {
- @Override
- public void handleMessage(Message msg) {
- if (msg.what == 0x123) {
- bar.setProgress(mDownStatus);
- if (mDownStatus >= 100) {
- Toast.makeText(MultiThreadDown.this, "下载完成", Toast.LENGTH_SHORT).show();
- }
- // Log.i("csx", "" + mDownStatus);
- }
- }
- };
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.layout_down);
- url = (EditText) findViewById(R.id.url);
- downButton = (Button) findViewById(R.id.down);
- bar = (ProgressBar) findViewById(R.id.bar);
- progressDialog = new ProgressDialog(this);
- progressDialog.setTitle("尝试连接");
- progressDialog.setMessage("正在连接...");
- downButton.setOnClickListener(new DownButtonOnClickListener());
- }
- private class DownButtonOnClickListener implements OnClickListener {
- EditText targetFilePath, fileName;
- TextView fileSize;
- Thread connectionThread;
- public Thread instanceOfConnectionThread() {
- return new Thread() {
- @Override
- public void run() {
- try {
- downUtil.getFileInformation();
- } catch (IOException e1) {
- e1.printStackTrace();
- }
- }
- };
- }
- @Override
- public void onClick(View v) {
- String urlPath = url.getText().toString();
- if (urlPath == null || urlPath.equals("")) {
- return;
- }
- progressDialog.show();
- downUtil = new DownUtil(urlPath, threadNum);
- connectionThread = instanceOfConnectionThread();
- connectionThread.start();
- int connectionNum = 3;
- while (!downUtil.isGetFileInformation() && connectionNum > 0) {// 循环请求连接,如果3次之后还没有连接成功,就退出
- if (!connectionThread.isAlive()) {
- connectionThread = null;
- connectionThread = instanceOfConnectionThread();
- connectionThread.start();
- connectionNum--;
- }
- }
- progressDialog.cancel();
- if (!downUtil.isGetFileInformation()) {
- Toast.makeText(MultiThreadDown.this, "请求失败!", Toast.LENGTH_SHORT).show();
- return;
- }
- downView = getLayoutInflater().inflate(R.layout.layout_download_view, null);
- targetFilePath = (EditText) downView.findViewById(R.id.editText_target_path);
- fileName = (EditText) downView.findViewById(R.id.editText_file_name);
- fileSize = (TextView) downView.findViewById(R.id.textView_file_size);
- targetFilePath.setText(downUtil.getDefaultTargetPath());
- fileName.setText(downUtil.getFileName());
- fileSize.append("" + ((double) downUtil.getFileSize()) / 1024 + "k");
- new AlertDialog.Builder(MultiThreadDown.this).setView(downView)
- .setPositiveButton("确定", new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- if (!downUtil.isGetFileInformation()) {
- dialog.dismiss();
- return;
- }
- final String path = targetFilePath.getText().toString();
- final String name = fileName.getText().toString();
- new Thread() {
- @Override
- public void run() {
- try {
- downUtil.download(path, name);
- } catch (IOException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- final Timer timer = new Timer();
- TimerTask task = new TimerTask() {
- @Override
- public void run() {
- mDownStatus = (int) (downUtil.getCompleteRate() * 100);
- handler.sendEmptyMessage(0x123);
- if (mDownStatus >= 100) {
- timer.cancel();
- }
- }
- };
- timer.schedule(task, 0, 100);
- }
- }.start();
- }
- }).setNegativeButton("取消", null)
- .setTitle(downUtil.isGetFileInformation() ? "链接可用" : "链接不可用").show();
- }
- }
- }
下面是主页面布局:layout_down.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <ScrollView
- android:id="@+id/scrollView1"
- android:layout_width="match_parent"
- android:layout_height="wrap_content" >
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="要下载的资源的URL:" />
- <EditText
- android:id="@+id/url"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="在在这里输入URL" />
- <Button
- android:id="@+id/down"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text="下载" />
- <!-- 定义一个水平进度条,用于显示下载进度 -->
- <ProgressBar
- android:id="@+id/bar"
- style="?android:attr/progressBarStyleHorizontal"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:max="100" />
- </LinearLayout>
- </ScrollView>
- </LinearLayout>
下面是下载选项dialog布局:layout_download_view.xml
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical" >
- <TextView
- android:id="@+id/textView1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="下载路径:" />
- <EditText
- android:id="@+id/editText_target_path"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:ems="10" >
- <requestFocus />
- </EditText>
- <TextView
- android:id="@+id/textView2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="文件名:" />
- <EditText
- android:id="@+id/editText_file_name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:maxLines="1"
- android:ems="10" />
- <TextView
- android:id="@+id/textView_file_size"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="文件大小:" />
- </LinearLayout>
效果图如下:输入URL,点击下载弹出对话框,输入路径和文件名 点击确定开始下载
Android版多线程下载器核心代码分享的更多相关文章
- 教你如何在 Android 使用多线程下载文件
# 教你如何在 Android 使用多线程下载文件 前言 在 Android 日常开发中,我们会经常遇到下载文件需求,这里我们也可以用系统自带的 api DownloadManager 来解决这个问题 ...
- Android中多线程下载列表的封装实现(含进度反馈)
来源:http://blog.csdn.net/u011638883/article/details/17347015 实现了一下Android中的文件多线程下载模块,支持自定义线程数.断点续传.下载 ...
- <基于Qt与POSIX线程>多线程下载器的简易搭建
原创博客,转载请联系博主! 本项目已托管到本人Git远程库:https://github.com/yue9944882/Snow 项目目标 Major Functionality 开发环境: Ce ...
- python10min系列之多线程下载器
今天群里看到有人问关于python多线程写文件的问题,联想到这是reboot的架构师班的入学题,我想了一下,感觉坑和考察的点还挺多,可以当成一个面试题来问,简单说一下我的想法和思路吧,涉及的代码和注释 ...
- 图解:HTTP 范围请求,助力断点续传、多线程下载的核心原理
题图:by Charles Loyer 一.序 Hi,大家好,我是承香墨影! HTTP 协议在网络知识中占据了重要的地位,HTTP 协议最基础的就是请求和响应的报文,而报文又是由报文头(Header) ...
- Android之——多线程下载演示样例
转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46883927 一.概述 说到Android中的文件下载.Android API中明 ...
- 06-python进阶-多线程下载器练手
我们需要用python 写一个多线程的下载器 我们要先获取这个文件的大小 然后将其分片 然后启动多线程 分别去下载 然后将其拼接起来 #!/usr/bin/env python#coding:utf- ...
- Java多线程下载器FileDownloader(支持断点续传、代理等功能)
前言 在我的任务清单中,很早就有了一个文件下载器,但一直忙着没空去写.最近刚好放假,便抽了些时间完成了下文中的这个下载器. 介绍 同样的,还是先上效果图吧. Jar包地址位于 FileDownload ...
- java编写的Http协议的多线程下载器
断点下载器还在实现中...... //////////////////////////////////界面/////////////////////////////////////////// pac ...
随机推荐
- PC-如何提高计算机的启动和关机的速度?
如何提高计算机的启动和关机的速度? 一.bios的优化设置 在bios设置的首页我们进入"advanced bios features"选项,将光标移到"frist bo ...
- [delphi技术]Delphi常见图象格式转换技术
TJPEGScale = (jsFullSize, jsHalf, jsQuarter, jsEighth);//图片大小(全部,1/2,1/4,1/8)TBitmap.pixelFormat:=pf ...
- java实现下载文件到本地
代码如下: URL url = new URL("http://www.cnblogs.com/images/logo_small.gif"); URLConnection con ...
- POJ#2065. SETI
题目描述 For some years, quite a lot of work has been put into listening to electromagnetic radio signal ...
- Delphi- 调用存储过程的方法
Delphi控件里拉一个TADOStoredProc,配置好相关链系,具体的操作列子如下: procedure TForm1.btnFirstClick(Sender: TObject); begin ...
- SVN版本控制安装配置说明
版本控制好工具有SVN.CVS.VSS等多种,他们的优劣在此不说明,请网络参阅. SVN支持多种平台,此文仅描述Windows平台下使用说明. SVN客户包含客户端和服务端.Windows平台下客户端 ...
- [置顶] linux 解压版安装
1:下载mysql解压版包去官网下载www.mysq.com 下载.下载linux通用版本就好了 2.基本配置 首先,我们准备好Linux环境,我们使用CentOS 5.8进行试验安装.第一步,我们需 ...
- ubuntu14.04源代码安装postgresql 9.1
项目须要使用gisgraphy,怎奈gisgraphy3.0仅仅支持postgis1.5.因此仅仅能安装老版本号的posgresql和postgis了.从postgis的support matrix图 ...
- ubuntu 远程 ubuntu
一:被远程端ubuntu配置 參考windows远程ubuntu这篇文章里面的ubuntu配置 二:远程端ubuntu配置 1:打开Remmina Remote Desktop Client软件,例如 ...
- MP3的频率、比特率、码率与音质的关系
想知道MP3的频率.比特率.码率与音质的关系,是不是频率越高,码率越高,音质就越好.好像MP3大多数的频率都是44100HZ的.码率有128,192等等. 这里所说的频率是採样率,一般都是44100K ...