• 安卓实训第七天---多线程下载实现(进度条)


     
     
     
     
     
     
     
     
     
    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、一定要注意下载速度的设置,不能太快。超过传输文件的大小。不然会导致模拟器死掉。;

  • 相关阅读:
    微服务治理istio
    基于Kubernetes构建Jenkins微服务发布平台
    gitlab
    微服务链路监控系统-Pinpoint
    Ceph Dashboard Promethus+Grafana监控
    kubernetes使用ceph存储
    ceph日常运维管理
    ceph-mimic版
    kubernetes集群网络
    Helm v3
  • 原文地址:https://www.cnblogs.com/mfmdaoyou/p/6718899.html
Copyright © 2020-2023  润新知