天天看點

android 多線程斷點下載下傳,listview 模式 開始 暫停等功能

android 多線程斷點下載下傳,listview 模式

android 多線程斷點下載下傳,listview 模式 開始 暫停等功能

代碼依次如下:

布局:

<?xml version="1.0" encoding="utf-8"?>

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

     android:orientation="vertical"

     android:layout_width="fill_parent"

     android:layout_height="fill_parent"

     android:id="@+id/llRoot">

     <ListView android:id="@android:id/list"

         android:layout_width="fill_parent"

         android:layout_height="fill_parent">

     </ListView>

 </LinearLayout>

item布局:

<?xml version="1.0" encoding="utf-8"?>

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

            android:orientation="vertical"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content">

     <LinearLayout

            android:orientation="horizontal"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:layout_marginBottom="5dip">

         <TextView 

             android:layout_width="fill_parent"

             android:layout_height="wrap_content"

             android:layout_weight="1"

             android:id="@+id/tv_resouce_name"/>

         <Button

             android:layout_width="fill_parent"

             android:layout_height="wrap_content"

             android:layout_weight="1"

             android:text="下載下傳"

             android:id="@+id/btn_start"

             android:onClick="startDownload"/>

         <Button

             android:layout_width="fill_parent"

             android:layout_height="wrap_content"

             android:layout_weight="1"

             android:text="暫停"

             android:visibility="gone"

             android:id="@+id/btn_pause"

             android:onClick="pauseDownload"/>

       </LinearLayout>

 </LinearLayout>

代碼:

package com.jiaruihuademo.download;

 import java.util.ArrayList;

import java.util.HashMap;

import java.util.List;

import java.util.Map;

import android.app.ListActivity;

import android.os.AsyncTask;

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.view.View;

import android.widget.Button;

import android.widget.LinearLayout;

import android.widget.LinearLayout.LayoutParams;

import android.widget.ProgressBar; 

import android.widget.TextView;

import android.widget.Toast;

 public class MainActivity extends ListActivity { 

     // 固定下載下傳的資源路徑,這裡可以設定網絡上的位址

//     private static final String URL = "http://download.haozip.com/";

     private static final String URL = "http://android.baoruan.com/download/downpage/down/subid/1605853/id/1604353/mid/12874";

     // 固定存放下載下傳檔案路徑:SD卡目錄下

     private static final String SD_PATH = "/mnt/sdcard/";

     // 存放各個下載下傳器

     private Map<String, Download> downloaders = new HashMap<String, Download>();

     // 存放與下載下傳器對應的進度條

     private Map<String, ProgressBar> ProgressBars = new HashMap<String, ProgressBar>();

     private Handler mHandler = new Handler() {

         public void handleMessage(Message msg) {

             if (msg.what == 1) {

                 String url = (String) msg.obj;

                 int length = msg.arg1;

                 ProgressBar bar = ProgressBars.get(url);

                 if (bar != null) {

                     // 設定進度條按讀取的length長度更新

                     bar.incrementProgressBy(length);

                     if (bar.getProgress() == bar.getMax()) {

                    LinearLayout layout = (LinearLayout) bar.getParent();

                    TextView resouceName=(TextView)layout.findViewById(R.id.tv_resouce_name);

                         Toast.makeText(MainActivity.this, "["+resouceName.getText()+"]下載下傳完成!", Toast.LENGTH_SHORT).show();

                         // 下載下傳完成後清除進度條并将map中的資料清空

                         layout.removeView(bar);

                         ProgressBars.remove(url);

                         downloaders.get(url).delete(url);

                         downloaders.get(url).reset();

                         downloaders.remove(url);

                         Button btn_start=(Button)layout.findViewById(R.id.btn_start);

                         Button btn_pause=(Button)layout.findViewById(R.id.btn_pause);

                         btn_pause.setVisibility(View.GONE);

                         btn_start.setVisibility(View.GONE);

                     }

                 }

             }

         }

     };

     @Override

     public void onCreate(Bundle savedInstanceState) {

         super.onCreate(savedInstanceState);

         setContentView(R.layout.main); 

         showListView();

     }

     // 顯示listView,這裡可以随便添加

     private void showListView() {

         List<Map<String, String>> data = new ArrayList<Map<String, String>>();

         Map<String, String> map = new HashMap<String, String>();

//         map.put("name", "haozip_v3.1.exe");

//         data.add(map);

//         map = new HashMap<String, String>();

//         map.put("name", "haozip_v3.1_hj.exe");

//         data.add(map);

//         map = new HashMap<String, String>();

//         map.put("name", "haozip_v2.8_x64_tiny.exe");

//         data.add(map);

//         map = new HashMap<String, String>();

//         map.put("name", "haozip_v2.8_tiny.exe");

//         data.add(map);

         map.put("name", "baoruan.com_8133f45539");

         data.add(map);

         DownLoadAdapter adapter=new DownLoadAdapter(this,data);  

         setListAdapter(adapter);

     }

     public void startDownload(View v) {

         // 得到textView的内容 

         LinearLayout layout = (LinearLayout) v.getParent();

         String resouceName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();

         String urlstr = URL + resouceName;

         String localfile = SD_PATH + resouceName;

         //設定下載下傳線程數為4,這裡是我為了友善随便固定的

         String threadcount = "4";

         DownloadTask downloadTask=new DownloadTask(v);

         downloadTask.execute(urlstr,localfile,threadcount);

     };

    class DownloadTask extends AsyncTask<String, Integer, LoadInfo>{

    Download downloader=null; 

    View v=null;

    String urlstr=null;

    public DownloadTask(final View v){

    this.v=v;

    }  

    @Override

    protected void onPreExecute() { 

    Button btn_start=(Button)((View)v.getParent()).findViewById(R.id.btn_start);

    Button btn_pause=(Button)((View)v.getParent()).findViewById(R.id.btn_pause);

    btn_start.setVisibility(View.GONE);

    btn_pause.setVisibility(View.VISIBLE);

    }

@Override

protected LoadInfo doInBackground(String... params) {

urlstr=params[0];

String localfile=params[1];

int threadcount=Integer.parseInt(params[2]);

// 初始化一個downloader下載下傳器

        downloader = downloaders.get(urlstr);

        if (downloader == null) {

            downloader = new Download(urlstr, localfile, threadcount, MainActivity.this, mHandler);

            downloaders.put(urlstr, downloader);

        }

        if (downloader.isdownloading())

        return null;

        // 得到下載下傳資訊類的個數組成集合

        return downloader.getDownloaderInfors(); 

}

@Override

protected void onPostExecute(LoadInfo loadInfo) {

if(loadInfo!=null){

// 顯示進度條

        showProgress(loadInfo, urlstr, v);

        // 調用方法開始下載下傳

        downloader.download();

}

};

     private void showProgress(LoadInfo loadInfo, String url, View v) {

         ProgressBar bar = ProgressBars.get(url);

         if (bar == null) {

             bar = new ProgressBar(this, null, android.R.attr.progressBarStyleHorizontal);

             bar.setMax(loadInfo.getFileSize());

             bar.setProgress(loadInfo.getComplete());

             ProgressBars.put(url, bar);

             LinearLayout.LayoutParams params = new LayoutParams(LayoutParams.FILL_PARENT, 5);

             ((LinearLayout) ((LinearLayout) v.getParent()).getParent()).addView(bar, params);

         }

     }

     public void pauseDownload(View v) {

         LinearLayout layout = (LinearLayout) v.getParent();

         String resouceName = ((TextView) layout.findViewById(R.id.tv_resouce_name)).getText().toString();

         String urlstr = URL + resouceName;

         downloaders.get(urlstr).pause();

         Button btn_start=(Button)((View)v.getParent()).findViewById(R.id.btn_start);

  Button btn_pause=(Button)((View)v.getParent()).findViewById(R.id.btn_pause);

         btn_pause.setVisibility(View.GONE);

         btn_start.setVisibility(View.VISIBLE);

     }

 }

下載下傳:

package com.jiaruihuademo.download;

import java.io.File;

import java.io.InputStream;

import java.io.RandomAccessFile;

import java.net.HttpURLConnection;

import java.net.URL;

import java.util.ArrayList;

import java.util.List;

import android.content.Context;

import android.os.AsyncTask;

import android.os.Handler;

import android.os.Message;

import android.util.Log;

public class Download {

    private String urlstr;// 下載下傳的位址

    private String localfile;// 儲存路徑

    private int threadcount;// 線程數

    private Handler mHandler;// 消息處理器 

    private int fileSize;// 所要下載下傳的檔案的大小

    private Context context; 

    private List<DownloadInfo> infos;// 存放下載下傳資訊類的集合

    private static final int INIT = 1;//定義三種下載下傳的狀态:初始化狀态,正在下載下傳狀态,暫停狀态

    private static final int DOWNLOADING = 2;

    private static final int PAUSE = 3;

    private int state = INIT;

    public Download(String urlstr, String localfile, int threadcount,

            Context context, Handler mHandler) {

        this.urlstr = urlstr;

        this.localfile = localfile;

        this.threadcount = threadcount;

        this.mHandler = mHandler;

        this.context = context;

    }

    public boolean isdownloading() {

        return state == DOWNLOADING;

    }

    public LoadInfo getDownloaderInfors() {

        if (isFirst(urlstr)) {

            Log.v("TAG", "isFirst");

            init();

            int range = fileSize / threadcount;

            infos = new ArrayList<DownloadInfo>();

            for (int i = 0; i < threadcount - 1; i++) {

                DownloadInfo info = new DownloadInfo(i, i * range, (i + 1)* range - 1, 0, urlstr);

                infos.add(info);

            }

            DownloadInfo info = new DownloadInfo(threadcount - 1,(threadcount - 1) * range, fileSize - 1, 0, urlstr);

            infos.add(info);

            //儲存infos中的資料到資料庫

            GetDownloadInfos.getInstance(context).saveInfos(infos);

            //建立一個LoadInfo對象記載下載下傳器的具體資訊

            LoadInfo loadInfo = new LoadInfo(fileSize, 0, urlstr);

            return loadInfo;

        } else {

            //得到資料庫中已有的urlstr的下載下傳器的具體資訊

            infos = GetDownloadInfos.getInstance(context).getInfos(urlstr);

            Log.v("TAG", "not isFirst size=" + infos.size());

            int size = 0;

            int compeleteSize = 0;

            for (DownloadInfo info : infos) {

                compeleteSize += info.getCompeleteSize();

                size += info.getEndPos() - info.getStartPos() + 1;

            }

            return new LoadInfo(size, compeleteSize, urlstr);

        }

    }

    private void init() {

        try {

            URL url = new URL(urlstr);

            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            connection.setConnectTimeout(5000);

            connection.setRequestMethod("GET");

            fileSize = connection.getContentLength();

            File file = new File(localfile);

            if (!file.exists()) {

                file.createNewFile();

            }

            // 本地通路檔案

            RandomAccessFile accessFile = new RandomAccessFile(file, "rwd");

            accessFile.setLength(fileSize);

            accessFile.close();

            connection.disconnect();

        } catch (Exception e) {

            e.printStackTrace();

        }

    }  

    private boolean isFirst(String urlstr) {

        return GetDownloadInfos.getInstance(context).isHasInfors(urlstr);

    }

    public void download() {

        if (infos != null) {

            if (state == DOWNLOADING)

                return;

            state = DOWNLOADING;

            for (DownloadInfo info : infos) {

                new MyThread(info.getThreadId(), info.getStartPos(),

                        info.getEndPos(), info.getCompeleteSize(),

                        info.getUrl()).start();

            }

        }

    }

    public class MyThread extends Thread {

        private int threadId;

        private int startPos;

        private int endPos;

        private int compeleteSize;

        private String urlstr;

        public MyThread(int threadId, int startPos, int endPos,

                int compeleteSize, String urlstr) {

            this.threadId = threadId;

            this.startPos = startPos;

            this.endPos = endPos;

            this.compeleteSize = compeleteSize;

            this.urlstr = urlstr;

        }

        @Override

        public void run() {

            HttpURLConnection connection = null;

            RandomAccessFile randomAccessFile = null;

            InputStream is = null;

            try {

                URL url = new URL(urlstr);

                connection = (HttpURLConnection) url.openConnection();

                connection.setConnectTimeout(5000);

                connection.setRequestMethod("GET");

                // 設定範圍,格式為Range:bytes x-y;

                connection.setRequestProperty("Range", "bytes="+(startPos + compeleteSize) + "-" + endPos);

                randomAccessFile = new RandomAccessFile(localfile, "rwd");

                randomAccessFile.seek(startPos + compeleteSize);

                // 将要下載下傳的檔案寫到儲存在儲存路徑下的檔案中

                is = connection.getInputStream();

                byte[] buffer = new byte[4096];

                int length = -1;

                while ((length = is.read(buffer)) != -1) {

                    randomAccessFile.write(buffer, 0, length);

                    compeleteSize += length;

                    // 更新資料庫中的下載下傳資訊

                    GetDownloadInfos.getInstance(context).updataInfos(threadId, compeleteSize, urlstr);

                    // 用消息将下載下傳資訊傳給進度條,對進度條進行更新

                    Message message = Message.obtain();

                    message.what = 1;

                    message.obj = urlstr;

                    message.arg1 = length;

                    mHandler.sendMessage(message);

                    if (state == PAUSE) {

                        return;

                    }

                }

            } catch (Exception e) {

                e.printStackTrace();

            }  

        }

    }

    //删除資料庫中urlstr對應的下載下傳器資訊

    public void delete(String urlstr) {

    GetDownloadInfos.getInstance(context).delete(urlstr);

    }

    //設定暫停

    public void pause() {

        state = PAUSE;

    }

    //重置下載下傳狀态

    public void reset() {

        state = INIT;

    }

}

package com.jiaruihuademo.download;

import java.util.List;

import java.util.Map;

import android.content.Context;

import android.view.LayoutInflater;

import android.view.View;

import android.view.View.OnClickListener;

import android.view.ViewGroup;

import android.widget.BaseAdapter;

import android.widget.Button;

import android.widget.TextView;

public class DownLoadAdapter extends BaseAdapter {

private LayoutInflater mInflater;

private List<Map<String, String>> data;

private Context context;

private OnClickListener click;

public DownLoadAdapter(Context context, List<Map<String, String>> data) {

this.context = context;

mInflater = LayoutInflater.from(context);

this.data = data;

}

public void refresh(List<Map<String, String>> data) {

this.data = data;

this.notifyDataSetChanged();

}

public void setOnclick(OnClickListener click) {

this.click = click;

}

@Override

public int getCount() {

return data.size();

}

@Override

public Object getItem(int position) {

return data.get(position);

}

@Override

public long getItemId(int position) {

return position;

}

@Override

public View getView(final int position, View convertView, ViewGroup parent) {

final Map<String, String> bean = data.get(position);

ViewHolder holder = null;

if (convertView == null) {

convertView = mInflater.inflate(R.layout.list_item, null);

holder = new ViewHolder();

holder.resouceName = (TextView) convertView

.findViewById(R.id.tv_resouce_name);

holder.startDownload = (Button) convertView

.findViewById(R.id.btn_start);

holder.pauseDownload = (Button) convertView

.findViewById(R.id.btn_pause);

convertView.setTag(holder);

} else {

holder = (ViewHolder) convertView.getTag();

}

holder.resouceName.setText(bean.get("name"));

return convertView;

}

public OnClickListener getClick() {

return click;

}

public void setClick(OnClickListener click) {

this.click = click;

}

private class ViewHolder {

public TextView resouceName;

public Button startDownload;

public Button pauseDownload;

}

}

package com.jiaruihuademo.download;

public class DownloadInfo {

    private int threadId;//下載下傳器id

    private int startPos;//開始點

    private int endPos;//結束點

    private int compeleteSize;//完成度

    private String url;//下載下傳器網絡辨別

    public DownloadInfo(int threadId, int startPos, int endPos,

            int compeleteSize,String url) {

        this.threadId = threadId;

        this.startPos = startPos;

        this.endPos = endPos;

        this.compeleteSize = compeleteSize;

        this.url=url;

    }

    public DownloadInfo() {

    }

    public String getUrl() {

        return url;

    }

    public void setUrl(String url) {

        this.url = url;

    }

    public int getThreadId() {

        return threadId;

    }

    public void setThreadId(int threadId) {

        this.threadId = threadId;

    }

    public int getStartPos() {

        return startPos;

    }

    public void setStartPos(int startPos) {

        this.startPos = startPos;

    }

    public int getEndPos() {

        return endPos;

    }

    public void setEndPos(int endPos) {

        this.endPos = endPos;

    }

    public int getCompeleteSize() {

        return compeleteSize;

    }

    public void setCompeleteSize(int compeleteSize) {

        this.compeleteSize = compeleteSize;

    }

    @Override

    public String toString() {

        return "DownloadInfo [threadId=" + threadId

                + ", startPos=" + startPos + ", endPos=" + endPos

                + ", compeleteSize=" + compeleteSize +"]";

    }

}

package com.jiaruihuademo.download;

import java.util.ArrayList;

import java.util.List;

import android.content.Context;

import android.database.Cursor;

import android.database.sqlite.SQLiteDatabase;

public class GetDownloadInfos {  

private static GetDownloadInfos dao=null;

private Context context; 

private  GetDownloadInfos(Context context) { 

this.context=context;

}

public static  GetDownloadInfos getInstance(Context context){

if(dao==null){

dao=new GetDownloadInfos(context); 

}

return dao;

}

public  SQLiteDatabase getConnection() {

SQLiteDatabase sqliteDatabase = null;

try { 

sqliteDatabase= new MyDbHelper(context).getReadableDatabase();

} catch (Exception e) {  

}

return sqliteDatabase;

}

public synchronized boolean isHasInfors(String urlstr) {

SQLiteDatabase database = getConnection();

int count = -1;

Cursor cursor = null;

try {

String sql = "select count(*)  from download_info where url=?";

cursor = database.rawQuery(sql, new String[] { urlstr });

if (cursor.moveToFirst()) {

count = cursor.getInt(0);

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != database) {

database.close();

}

if (null != cursor) {

cursor.close();

}

}

return count == 0;

}

public synchronized void saveInfos(List<DownloadInfo> infos) {

SQLiteDatabase database = getConnection();

try {

for (DownloadInfo info : infos) {

String sql = "insert into download_info(thread_id,start_pos, end_pos,compelete_size,url) values (?,?,?,?,?)";

Object[] bindArgs = { info.getThreadId(), info.getStartPos(),

info.getEndPos(), info.getCompeleteSize(),

info.getUrl() };

database.execSQL(sql, bindArgs);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != database) {

database.close();

}

}

}

public synchronized List<DownloadInfo> getInfos(String urlstr) {

List<DownloadInfo> list = new ArrayList<DownloadInfo>();

SQLiteDatabase database = getConnection();

Cursor cursor = null;

try {

String sql = "select thread_id, start_pos, end_pos,compelete_size,url from download_info where url=?";

cursor = database.rawQuery(sql, new String[] { urlstr });

while (cursor.moveToNext()) {

DownloadInfo info = new DownloadInfo(cursor.getInt(0),

cursor.getInt(1), cursor.getInt(2), cursor.getInt(3),

cursor.getString(4));

list.add(info);

}

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != database) {

database.close();

}

if (null != cursor) {

cursor.close();

}

}

return list;

}

public synchronized void updataInfos(int threadId, int compeleteSize, String urlstr) {

SQLiteDatabase database = getConnection();

try {

String sql = "update download_info set compelete_size=? where thread_id=? and url=?";

Object[] bindArgs = { compeleteSize, threadId, urlstr };

database.execSQL(sql, bindArgs);

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != database) {

database.close();

}

}

}

public synchronized void delete(String url) {

SQLiteDatabase database = getConnection();

try {

database.delete("download_info", "url=?", new String[] { url });

} catch (Exception e) {

e.printStackTrace();

} finally {

if (null != database) {

database.close();

}

}

}

}

package com.jiaruihuademo.download;

public class LoadInfo {

public int fileSize;// 檔案大小

private int complete;// 完成度

private String urlstring;// 下載下傳器辨別

public LoadInfo(int fileSize, int complete, String urlstring) {

this.fileSize = fileSize;

this.complete = complete;

this.urlstring = urlstring;

}

public LoadInfo() {

}

public int getFileSize() {

return fileSize;

}

public void setFileSize(int fileSize) {

this.fileSize = fileSize;

}

public int getComplete() {

return complete;

}

public void setComplete(int complete) {

this.complete = complete;

}

public String getUrlstring() {

return urlstring;

}

public void setUrlstring(String urlstring) {

this.urlstring = urlstring;

}

@Override

public String toString() {

return "LoadInfo [fileSize=" + fileSize + ", complete=" + complete

+ ", urlstring=" + urlstring + "]";

}

}

package com.jiaruihuademo.download;

import android.content.Context;

import android.database.sqlite.SQLiteDatabase;

import android.database.sqlite.SQLiteOpenHelper;

public class MyDbHelper extends SQLiteOpenHelper {

// download.db-->資料庫名

public MyDbHelper(Context context) {

super(context, "download.db", null, 1);

}

@Override

public void onCreate(SQLiteDatabase db) {

db.execSQL("create table download_info(_id integer PRIMARY KEY AUTOINCREMENT, thread_id integer, "

+ "start_pos integer, end_pos integer, compelete_size integer,url char)");

}

@Override

public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

}

}

權限:

<uses-permission android:name="android.permission.INTERNET" />

   

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

源碼下載下傳