用到的知识点:
1.Http 协议字段"Range", "bytes="+start+"-"+end
2.RandomAccessFile设置写入的位置
3.开启线程发送网络请求以及线程池操作
首先,在服务器端放一张图片,如下在WebRoot下放置了一张lufei.jpg图片
跟访问网页一样通过url直接访问:http://pc-20141102midc:8080/DownLoadFile/lufei.jpg
然后在Android端写多线程下载的代码:
为了防止遗忘现在配置文件中声明权限:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
布局文件:
<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" tools:context="com.example.download_file.MainActivity" > <Button android:id="@+id/start_download_bt" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="下载" android:textColor="@android:color/background_dark" /> <TextView android:id="@+id/my_tv" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/hello_world" /> </LinearLayout>
下载类:
DownLoad.java
package com.example.download_file; import java.io.File; 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.util.concurrent.Executor; import java.util.concurrent.Executors; import android.os.Environment; import android.os.Handler; import android.os.Message; /** * 多线程下载例子 * @author weichongchong * */ public class DownLoad { private Handler mHandler; public DownLoad(Handler handle){ this.mHandler= handle; } //通过线程池下载,创建线程池对象 private Executor threadPool = Executors.newFixedThreadPool(3);//创建三个线程池 static class DownLoadRunnable implements Runnable{ private String url; private String fileName; private long start; private long end; private Handler handler; public DownLoadRunnable(String url ,String fileName,long start,long end,Handler handler ){ this.url=url; this.fileName = fileName; this.start = start; this.end = end; this.handler= handler; } @Override public void run() { // TODO Auto-generated method stub try { URL httpUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection(); conn.setReadTimeout(5000); conn.setRequestProperty("Range", "bytes="+start+"-"+end);//指定长度 conn.setRequestMethod("GET"); //创建随机读取流进行读取 RandomAccessFile access = new RandomAccessFile(new File(fileName), "rwd");//第二个参数代表可读,可写,可执行 access.seek(start); InputStream in = conn.getInputStream(); byte[] b = new byte[1024*4]; int len=0; while((len = in.read())!=-1){ access.write(b,0,len); } if(access!=null){ access.close(); } if(in!=null){ in.close(); } //下载完成通知更新UI Message message = new Message(); message.what=1; handler.sendMessage(message); // int count = conn.getContentLength();//拿到下载对象的长度 // int block = count/3;//平均到每个线程池 } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } public void downLoadFile(String url){ try { URL httpUrl = new URL(url); HttpURLConnection conn = (HttpURLConnection) httpUrl.openConnection(); conn.setReadTimeout(5000); conn.setRequestMethod("GET"); int count = conn.getContentLength();//拿到下载对象的长度 int block = count/3;//平均到每个线程池 String fileName = getFileName(url); // File parent = Environment.getExternalStorageDirectory(); // File fileDownLoad = new File(parent,fileName); File fileDownLoad = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),fileName); /** * 11/3 3 * 第一个线程0-2 * 第二个3-5 * 第三个6-10 */ for(int i=0;i<3;i++){ long start = i*block; long end = (i+1)*block-1; if(i==2){ end=count; } DownLoadRunnable runnable = new DownLoadRunnable(url,fileDownLoad.getAbsolutePath(),start,end,mHandler); threadPool.execute(runnable);//通过线程池提交任务 } } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } /** * * @return * 得到url后缀名,即文件名 */ public String getFileName(String url){ return url.substring(url.lastIndexOf("/")+1); } }
package com.example.download_file; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { private Button start_download_bt; private TextView mytv; private int count = 0; private Handler mHandler = new Handler(){ public void handleMessage(android.os.Message msg) { int result = msg.what; count+=result;//如果三个线程都下载完成,都返回一个1,相加为3 if(count==3){ mytv.setText("下载完成"); start_download_bt.setText("下载完成"); } }; }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); start_download_bt = (Button) findViewById(R.id.start_download_bt); mytv = (TextView) findViewById(R.id.my_tv); start_download_bt.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub start_download_bt.setText("正在下载"); Toast.makeText(MainActivity.this, "正在下载", 0).show(); new Thread(){ @Override public void run() { // TODO Auto-generated method stub DownLoad mDownLoad = new DownLoad(mHandler); mDownLoad.downLoadFile("http://192.168.1.105:8080/DownLoadFile/lufei.jpg"); } }.start(); } }); } }