标签:
apply plugin: ‘com.android.application‘ android { compileSdkVersion 23 buildToolsVersion "23.0.3" defaultConfig { applicationId "xidian.dy.com.chujia" minSdkVersion 15 targetSdkVersion 23 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile(‘proguard-android.txt‘), ‘proguard-rules.pro‘ } } } dependencies { compile fileTree(dir: ‘libs‘, include: [‘*.jar‘]) testCompile ‘junit:junit:4.12‘ compile ‘com.android.support:appcompat-v7:23.4.0‘ }
亲测可用
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="输入url:" /> <EditText android:id="@+id/url" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="输入保存的文件名:" /> <EditText android:id="@+id/target" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <Button android:id="@+id/download" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下载" /> <ProgressBar android:id="@+id/progressBar" style="@android:style/Widget.ProgressBar.Horizontal" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout>
package xidian.dy.com.chujia; /** * Created by dy on 2016/6/29. */ import android.os.Environment; import android.os.StrictMode; import android.util.Log; import java.io.File; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; /** * Description: * 创建ServerSocket监听的主类 * @author jph * Date:2014.08.27 */ public class DownUtil { /**下载资源的URL**/ private String path; /**下载的文件的保存位置**/ private String targetFile; /**需要使用多少线程下载资源**/ private int threadNum; /**下载的线程对象**/ private DownThread[] threads; /**下载的文件的总大小**/ private int fileSize; public DownUtil(String path, String targetFile, int threadNum) { this.path = path; this.threadNum = threadNum; // 初始化threads数组 threads = new DownThread[threadNum]; this.targetFile = targetFile; } public void download() throws Exception { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(5 * 1000); conn.setReadTimeout(5*1000); conn.setRequestMethod("GET"); conn.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, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Connection", "Keep-Alive"); conn.connect(); if(conn.getResponseCode() == 200){ // 得到文件大小 fileSize = conn.getContentLength(); //关闭连接 conn.disconnect(); //计算每个线程下载文件大小 int currentPartSize = fileSize / threadNum; //创建本地文件 File myfile = new File(Environment.getExternalStorageDirectory(), targetFile); if(myfile.exists()) myfile.delete(); else myfile.createNewFile(); RandomAccessFile file = new RandomAccessFile(myfile, "rwd"); // 设置本地文件的大小 file.setLength(fileSize); file.close(); for (int i = 0; i < threadNum; i++) { // //计算线程下载的开始位置和结束位置 int startIndex = i * currentPartSize; int endIndex = (i + 1) *currentPartSize - 1; if(i == threadNum - 1){ endIndex = fileSize - 1; } // 每个线程使用一个RandomAccessFile进行下载 RandomAccessFile currentPart = new RandomAccessFile(myfile, "rwd"); threads[i] = new DownThread(currentPart,startIndex, endIndex); threads[i].start(); } } } // 获取下载的完成百分比 public double getCompleteRate() { // 统计多条线程已经下载的总大小 int sumSize = 0; for (int i = 0; i < threadNum; i++) { if(threads[i] == null) sumSize += 0; else sumSize += threads[i].length; } // 返回已经完成的百分比 return sumSize * 1.0 / fileSize; } private class DownThread extends Thread { /**当前线程的下载位置**/ private int startPos; /**当前线程下载的结束位置**/ private int endPos; /**当前线程需要下载的文件块**/ private RandomAccessFile currentPart; /**定义该线程已下载的字节数**/ public int length; public DownThread(RandomAccessFile currentPart, int startPos, int endPos) { this.startPos = startPos; this.currentPart = currentPart; this.endPos = endPos; } @Override public void run() { try { URL url = new URL(path); HttpURLConnection conn = (HttpURLConnection)url .openConnection(); conn.setConnectTimeout(5 * 1000); conn.setRequestMethod("GET"); conn.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, */*"); conn.setRequestProperty("Accept-Language", "zh-CN"); conn.setRequestProperty("Charset", "UTF-8"); conn.setRequestProperty("Range", "bytes=" + startPos + "-" + endPos); conn.connect(); if(conn.getResponseCode() == 206){ InputStream inStream = conn.getInputStream(); // 跳过startPos个字节,表明该线程只下载自己负责哪部分文件。 byte[] buffer = new byte[4*1024]; int hasRead; currentPart.seek(startPos); // 读取网络数据,并写入本地文件 while ((hasRead = inStream.read(buffer)) >0 ) { currentPart.write(buffer, 0, hasRead); // 累计该线程下载的总大小 length += hasRead; } Log.i(Thread.currentThread().getName(), String.valueOf(length)); currentPart.close(); inStream.close(); } } catch (Exception e) { e.printStackTrace(); } } } }
package xidian.dy.com.chujia; import android.content.Context; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.Message; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.ProgressBar; import android.widget.Toast; import java.util.Timer; import java.util.TimerTask; public class MainActivity extends AppCompatActivity { EditText url; EditText target; Button downBn; ProgressBar bar; DownUtil downUtil; private int mDownStatus; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 获取程序界面中的三个界面控件 url = (EditText) findViewById(R.id.url); target = (EditText) findViewById(R.id.target); downBn = (Button) findViewById(R.id.download); bar = (ProgressBar) findViewById(R.id.progressBar); // 创建一个Handler对象 final Handler handler = new Handler() { @Override public void handleMessage(Message msg) { if (msg.what == 0x123) { bar.setProgress(mDownStatus); } } }; downBn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) return; // 初始化DownUtil对象(最后一个参数指定线程数) downUtil = new DownUtil(url.getText().toString(), target.getText().toString(), 4); new Thread() { @Override public void run(){ try { // 开始下载 downUtil.download(); } catch (Exception e) { e.printStackTrace(); } // 定义每秒调度获取一次系统的完成进度 final Timer timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // 获取下载任务的完成比率 double completeRate = downUtil.getCompleteRate(); mDownStatus = (int) (completeRate * 100); // 发送消息通知界面更新进度条 Log.i(Thread.currentThread().getName(), String.valueOf(mDownStatus)); handler.sendEmptyMessage(0x123); // 下载完全后取消任务调度 if (mDownStatus >= 100) { showToastByRunnable(MainActivity.this, "下载完成", 2000); timer.cancel(); } } }, 0, 100); } }.start(); } }); } /** * 在非UI线程中使用Toast * @param context 上下文 * @param text 用以显示的消息内容 * @param duration 消息显示的时间 * */ private void showToastByRunnable(final Context context, final CharSequence text, final int duration) { Handler handler = new Handler(Looper.getMainLooper()); handler.post(new Runnable() { @Override public void run() { Toast.makeText(context, text, duration).show(); } }); } }
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="xidian.dy.com.chujia"> <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
标签:
原文地址:http://www.cnblogs.com/xidongyu/p/5634235.html