安卓实训第七天---多线程下载实现(进度条)
Posted mfmdaoyou
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了安卓实训第七天---多线程下载实现(进度条)相关的知识,希望对你有一定的参考价值。
packagecom.example.download; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.text.TextUtils; import android.view.View; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { // 定义正在执行的线程 private int threadRunning = 3; // 线程开启的数量 private int threadNum = 3; private EditText et_url; // 进度条 private ProgressBar progressBar; private TextView tv_pb; private int currentProgress = 0; private boolean flag = true; // 记录进度条的值 public static int pb_count = 0; public static Handler handler; public static final int TEXTVALUE = 1; public static int pb_num = 0; public static int size = 0; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取控件对象 et_url = (EditText) findViewById(R.id.et_url); progressBar = (ProgressBar) findViewById(R.id.tv_jindu); tv_pb = (TextView) findViewById(R.id.tv_pb); File sdDir = Environment.getExternalStorageDirectory(); File pdFile = new File(sdDir, "pb.txt"); InputStream is = null; try { if (pdFile.exists()) { is = new FileInputStream(pdFile); } } catch (FileNotFoundException e) { e.printStackTrace(); } if (is != null) { String value = StreamTools.streamTostr(is); String arr[] = value.split(";"); progressBar.setMax(Integer.valueOf(arr[0]));// 最大值 currentProgress = Integer.valueOf(arr[1]);// 当前值 progressBar.setProgress(currentProgress); ; tv_pb.setText("当前的进度是" + arr[2] + "%"); } } public void downLoadFile(View v) { // 訪问地址: final String spec = et_url.getText().toString();// "http://172.16.237.144:8080/Login/football.jpg"; if (TextUtils.isEmpty(spec)) { Toast.makeText(this, "下载地址不能为空", Toast.LENGTH_LONG).show(); } else { new Thread() { public void run() { try { URL url = new URL(spec); HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); // 设置请求的头文件信息还有时间 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); httpURLConnection.setReadTimeout(5000); if (httpURLConnection.getResponseCode() == 200) { int fileLength = httpURLConnection .getContentLength(); // 设置进度条的最大值 progressBar.setMax(fileLength); // 推断你的设备SDCard是否可用 if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED)) { // 外部存储设备的路径 File sdfile = Environment .getExternalStorageDirectory(); // 获取文件的名称 String fileName = spec.substring(spec .lastIndexOf("/") + 1); // 创建保存的文件 File file = new File(sdfile, fileName); // 创建随机能够訪问的文件对象 RandomAccessFile accessFile = new RandomAccessFile( file, "rwd"); // 设置文件大小 accessFile.setLength(fileLength); // 关闭操作 accessFile.close(); // 首先计算出每一个线程下载的大小 開始位置 结束位置 int threadSize = fileLength / threadNum; // for循环开启线程处理 for (int threadId = 1; threadId <= 3; threadId++) { int startIndex = (threadId - 1) * threadSize;// 開始位置 int endIndex = threadId * threadSize - 1; if (threadId == threadNum) {// 最后一个线程 endIndex = fileLength - 1; } System.out.println("当前线程--" + threadId + "開始位置---" + startIndex + "结束位置---" + endIndex + "线程大小---"); // 开启线程下载要用Start方法 new DownLoadThread(threadId, startIndex, endIndex, spec, fileName).start(); } } else { MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "设备的SD卡不可用", Toast.LENGTH_LONG) .show(); } }); } } else { // 这里用这个能够让它在主线程中执行 MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "server端返回错误", Toast.LENGTH_LONG) .show(); } }); } } catch (Exception e) { e.printStackTrace(); } }; }.start(); } } class DownLoadThread extends Thread { private int threadId; private int startIndex; private int endIndex; private String path; private String fileName; public DownLoadThread(int threadId, int startIndex, int endIndex, String path, String fileName) { super(); this.threadId = threadId; this.startIndex = startIndex; this.endIndex = endIndex; this.path = path; this.fileName = fileName; } @Override public void run() { // 能够通过每一个线程去下载文件了。 try { File sdfile = Environment.getExternalStorageDirectory(); // 获取每一个线程下载的记录文件 File recordFile = new File(sdfile, threadId + ".txt"); // 推断记录文件是否存在 if (recordFile.exists()) { // 读取文件的内容 InputStream is = new FileInputStream(recordFile); // 利用工具类转换 String value = StreamTools.streamTostr(is); // 获取记录位置 int recordIndex = Integer.parseInt(value); // 记录的位置复制给開始的位置就可以 startIndex = recordIndex; } // 通过path路径构建URL对象 URL url = new URL(path); // 通过URL对象的打开连接,返回对象 HttpURLConnection httpURLConnection = (HttpURLConnection) url .openConnection(); // 设置请求头 httpURLConnection.setRequestMethod("GET"); httpURLConnection.setConnectTimeout(5000); // 设置下载文件的開始位置和结束位置 httpURLConnection.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex); // 获取的状态吗 int code = httpURLConnection.getResponseCode(); if (code == 206) { // 获取每一个线程返回的流对象: InputStream inputStream = httpURLConnection .getInputStream(); // 获取文件名 由于已经通过那边传过来了 // String fileName = // path.substring(path.lastIndexOf("/")+1); // 外部存储设备的路径 File file = new File(sdfile, fileName); // 依据文件创建她RandomAccessFile对象 RandomAccessFile raf = new RandomAccessFile(file, "rwd"); raf.seek(startIndex); // 定义读取的长度 int len = 0; byte buffer[] = new byte[50]; int total = 0; // 循环读取 while ((len = inputStream.read(buffer)) != -1) { System.out.println("当前线程--" + threadId + "--已经下载了" + (startIndex + total)); // 创建线程下载记录的文件 RandomAccessFile threadfile = new RandomAccessFile( new File(sdfile, threadId + ".txt"), "rwd"); threadfile.writeBytes((startIndex + total) + ""); threadfile.close(); raf.write(buffer, 0, len); total += len; synchronized (MainActivity.this) { currentProgress += len; progressBar.setProgress(currentProgress); // 计算百分比的操作 int final String percent = currentProgress * 100L / progressBar.getMax() + ""; MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { tv_pb.setText("当前的进度是:" + percent + "%"); } }); RandomAccessFile pbfile = new RandomAccessFile( new File(sdfile, "pb.txt"), "rwd"); pbfile.writeBytes(progressBar.getMax() + ";" + currentProgress + ";" + percent); pbfile.close(); } } raf.close(); inputStream.close(); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { // System.out.println("当前线程----"+threadId+"完成下载"); Toast.makeText(MainActivity.this, "当前线程----" + threadId + "完成下载", Toast.LENGTH_LONG).show(); } }); deleteRecordFiles(); } else { MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { Toast.makeText(MainActivity.this, "server端下载错误", Toast.LENGTH_LONG).show(); } }); } } catch (Exception e) { e.printStackTrace(); } } } public synchronized void deleteRecordFiles() { File sdfile = Environment.getExternalStorageDirectory(); System.out.println("-------------------------"); threadRunning--; if (threadRunning == 0) { for (int i = 1; i <= 3; i++) { File recordFile = new File(sdfile, i + ".txt"); if (recordFile.exists()) { boolean flag1 = recordFile.delete();// 删除掉文件 System.out.println("下载记录" + i + "文件已" + flag1 + "删除"); } File pdFile = new File(sdfile, "pb.txt"); if (pdFile.exists()) { boolean flag2 = pdFile.delete(); System.out.println("进度条记录文件已" + flag2 + "删除"); } } } } public void displayMsg() { } }
BUG注意事项:
1、继续线程下载的文件一定要运行threadfile.close(),不然就无法运行后面的删除TXT文件部分。
2、一定要注意下载速度的设置,不能太快。超过传输文件的大小。不然会导致模拟器死掉。;
以上是关于安卓实训第七天---多线程下载实现(进度条)的主要内容,如果未能解决你的问题,请参考以下文章
实训第八天 有关python orm 的学习记录 常用方法01
实训第八天 有关python orm 的学习记录 常用方法02