Android多线程实现文件断点下载详解编程语言
download_main_layout.xml:
LinearLayout xmlns:android= http://schemas.android.com/apk/res/android
xmlns:tools= http://schemas.android.com/tools
android:layout_width= match_parent
android:layout_height= match_parent
android:orientation= vertical
EditText
android:id= @+id/down_load_edt
android:layout_width= match_parent
android:layout_height= wrap_content
android:layout_marginTop= 20dp
android:hint= 请输入下载文件的网址! /
Button
android:layout_marginTop= 20dp
android:id= @+id/down_load_btn
android:layout_width= match_parent
android:layout_height= wrap_content
android:text= 点击下载 /
ProgressBar
android:id= @+id/down_load_pbar
> android:layout_width= match_parent
android:layout_height= wrap_content /
/LinearLayout
下载入口Activity:
public class MainActivity extends Activity implements OnClickListener {
/**下载文件按钮 */
private Button downLoadBtn;
/**下载文件地址 */
private EditText downLoadEdt;
/**下载进度 */
private ProgressBar downLoadPbar;
/**定义发送消息的字段*/
private static final int MESSAGE_NUMBER = 1;
/**所要下载文件总大小 */
private int fileSize;
/**已下载大小 */
private int downLoadSize;
/**所下载文件的保存路径 */
private String path;
/**更新进度条的值 */
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == MESSAGE_NUMBER) {
/**设置进度*/
downLoadPbar.setProgress(Double.valueOf(downLoadSize * 1.0 / fileSize * 100).intValue());
}
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.download_activity_main);
findViews();
setListeners();
initdata();
}
private void findViews() {
downLoadEdt=(EditText) findViewById(R.id.down_load_edt);
downLoadBtn = (Button) findViewById(R.id.down_load_btn);
downLoadPbar = (ProgressBar) findViewById(R.id.down_load_pbar);
}
private void setListeners() {
downLoadBtn.setOnClickListener(this);
}
private void initdata() {
downLoadPbar.setVisibility(View.GONE);
downLoadPbar.setMax(100);
downLoadPbar.setProgress(0);
}
@Override
public void onClick(View v) {
/**获取SDcard */
path = Environment.getExternalStorageDirectory() + /downloads/
File file = new File(path);
if (!file.exists()) {
file.mkdir();
}
/**下载操作 */
new Thread(new DownLoadTask()).start();
/**显示进度条 */
downLoadPbar.setVisibility(View.VISIBLE);
}
/**子线程,计算下载量,更新UI */
class DownLoadTask implements Runnable {
/**线程块大小,每个线程的下载量 */
private int blockSize;
/** 默认为5个线程 */
private int threadNum = 5;
/** 下载后的文件名 */
private String fileName = myDownLoad.zip
@Override
public void run() {
/**数组保存线程对象,便于后面的每个线程下载量计算总和 */
DownLoadThread[] fileDownLoads = new DownLoadThread[threadNum];
/** 计算总大小 */
URL url;
try {
url = new URL(downLoadEdt.getText().toString().trim());
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
/**计算下载量 */
fileSize = conn.getContentLength();
/** 计算每个线程的下载量 */
blockSize = fileSize / threadNum;
/** 执行下载操作 */
for (int i = 0; i threadNum; i++) {
/** 每个线程的开始位置 */
int begin = i * blockSize;
/** 每个线程的结束位置 */
int end = (i + 1) * blockSize 1;
DownLoadThread thread = new DownLoadThread(url, begin, end, path + fileName);
thread.start();
fileDownLoads[i] = thread;
}
/** 更新UI */
boolean flag = false;
while (!flag) {
flag = true;
for (int i = 0; i threadNum; i++) {
downLoadSize += fileDownLoads[i].getDownloadsize();
if (!fileDownLoads[i].isFinish()) {
flag = false;
}
}
MainActivity.this.handler.sendEmptyMessage(MESSAGE_NUMBER);
Thread.sleep(1000);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
下载线程工具类:
public class DownLoadThread extends Thread {
/**文件年在Url*/
private URL url;
/**文件下载开始位置*/
private int startPostion;
/**文件下载结束位置*/
private int endPostion;
/**文件下载当前位置*/
private int currentPostion;
/**文件名*/
private String filename;
/**缓冲输入流*/
private BufferedInputStream buffin;
/**写入流,支持断点*/
private RandomAccessFile raf;
/**缓冲大小*/
byte[] buffsize = new byte[1024];
/**已经下载大小*/
private int downloadsize;
/**下载是否完成*/
private boolean isFinish;
public int getDownloadsize() {
return downloadsize;
}
public boolean isFinish() {
return isFinish;
}
public DownLoadThread(URL url, int begin, int end, String filename) {
super();
this.url = url;
this.startPostion = begin;
this.endPostion = end;
this.filename = filename;
}
@Override
public void run() {
try {
/**
* 抽象类 URLConnection 是所有类的超类,它代表应用程序和 URL 之间的通信链接。此类的实例可用于读取和写入此 URL 引用的资源。通常,创建一个到 URL 的连接需要几个步骤:
* openConnection() connect()对影响到远程资源连接的参数进行操作。 与资源交互;查询头字段和内容。
* 通过在 URL 上调用 openConnection 方法创建连接对象。 处理设置参数和一般请求属性。 使用 connect 方法建立到远程对象的实际连接。 远程对象变为可用。远程对象的头字段和内容变为可访问。
*/
URLConnection conn = url.openConnection();
/**指定下载的范围*/
conn.setRequestProperty( Range , bytes= +startPostion+ - +endPostion);
/**此URL将在一定的上下文环境中被检验,是否允许用户交互,比如弹出一个认证对话框。如果为 false,那么不允许用户交互。*/
conn.setAllowUserInteraction(true);
/**做缓冲优化处理*/
buffin = new BufferedInputStream(conn.getInputStream());
/**写入本地文件*/
raf = new RandomAccessFile(new File(filename), rw );
/**移动到新的位置*/
raf.seek(startPostion);
while(currentPostion endPostion){//如果当前下载没有结束
int size = buffin.read(buffsize, 0, 1024);
/**已经读完*/
if(size==-1){
break;
}
raf.write(buffsize, 0, size);
currentPostion+=size;
/**下载量*/
downloadsize+=size;
}
isFinish = true;
/**下载完成就要关闭输入流与写入流*/
buffin.close();
raf.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
super.run();
}
}
不要忘记在清单文件AndroidManifest.xml中设置相应权限:
! 网络访问权限
uses-permission android:name= android.permission.INTERNET /
! sdcard权限
uses-permission android:name= android.permission.MOUNT_UNMOUNT_FILESYSTEMS /
uses-permission android:name= android.permission.WRITE_EXTERNAL_STORAGE /
10363.html
cgomacxml相关文章
- Android Studio 4.1 的 Dagger 导航更新
- android onresume方法,非静态方法’onResume’Android Studio
- Android listView长按删除
- Android angle_android 界面悬停
- Android 编译_android线程
- Eclipse安装android插件
- 【OpenGL ES】 Android OpenGL ES -- 透视投影 和 正交投影
- 【Android 应用开发】Paint 滤镜原理 之 图像结构 ( 图片文件二进制分析 | PNG文件结构 | 数据块结构 | IHDR 数据块详解 )
- 【Android 逆向】x86 汇编 ( 使用 IDA 解析 x86 架构的动态库文件 | 使用 IDA 打开动态库文件 | IDA 中查找指定的方法 )
- 【Android 逆向】Android 进程注入工具开发 ( 远程进程注入动态库文件操作 | 注入动态库 加载 业务动态库 | 业务动态库启动 | pthread_create 线程开发 )
- 【Android 逆向】类加载器 ClassLoader ( 使用 DexClassLoader 动态加载字节码文件 | 拷贝 DEX 文件到内置存储 | 加载并执行 DEX 字节码文件 )
- SkeyeVSS综合安防视频云服务WEB H5无插件播放RTSP摄像机解决方案,拒绝插件,拥抱H5,Windows PC、 Liunx、 Android
- 【Android Gradle 插件】build.gradle 中的 android 配置 ( 配置项 | compileSdkVersion 配置 | buildToolsVersion 配置 )
- [android] 保存文件到手机内存详解手机开发
- java android网络监测详解编程语言
- LG表示即便退出手机市场也会发布Android 12版更新 对此我们深表怀疑
- Android中资源文件(非代码部分)的使用概览
- Android利用方向传感器获得手机的相对角度实例说明
- android读取assets文件示例
- Android中扫描多媒体文件操作详解