android实现下载的核心代码

一:使用多线程实现下载

private EditText etpath;//服务地址
    private LinearLayout ll ;
    // 访问服务器
    String path ;
    // 设定线程的数量
    int threadcount = 3;
    //定义正在执行的线程数量
    int runningThreadcount = threadcount ;   
    //建一个集合存放进度条
    List<ProgressBar> list = new ArrayList<ProgressBar>() ;

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        etpath = (EditText) findViewById(R.id.etpath);       
        ll = (LinearLayout) findViewById(R.id.ll) ;

// 加载进度条控件
        for (int i = 0; i < threadcount; i++) {
            ProgressBar pb = (ProgressBar)View.inflate(this, R.layout.pb, null) ;           
        }
    }

public void download(View view){

//将进度条加入到线性组件中显示出来

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

ll.addView(list.get(i));}

new Thread() {
            public void run() {
                
                path = etpath.getText().toString().trim();

if (TextUtils.isEmpty(path)) {
                    runOnUiThread(new Runnable() {

@Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "路径不能为空", 0)
                                    .show();
                        }
                    });
                    return;
                }
                // 下载文件
                try {
                    // 创建连接服务器对象
                    URL url = new URL(path);
                    HttpURLConnection http = (HttpURLConnection) url
                            .openConnection();
                    // 设定连接参数
                    http.setRequestMethod("GET");
                    // 设定连接的超时时间
                    http.setConnectTimeout(5000);
                    // 获取返回的状态吗
                    int code = http.getResponseCode();
                    if (code == 200) {
                        // 获得返回的文件的大小
                        int length = http.getContentLength();
                        // 2.创建一个文件和下载的文件大小一样
                        RandomAccessFile raf = new RandomAccessFile(
                                getFileName(path), "rw");
                        // 设置文件的大小
                        raf.setLength(length);
                        // 3.启动多个线程下载文件
                        for (int id = 0; id < threadcount; id++) {
                            // 计算每个线程要下载的区块大小
                            int blocksize = length / threadcount;
                            // 计算每个线程下载的开始和结束位置
                            int startIndex = id * blocksize;
                            int endIndex = (id + 1) * blocksize - 1;
                            // 特殊情况:最后一个线程需要承担更多的数据
                            if (id == threadcount - 1) {
                                endIndex = length - 1;
                            }
                            // 启动线程下载数据
                            DownLoadThread dlt = new DownLoadThread(path, id,
                                    startIndex, endIndex);
                            dlt.start();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    runOnUiThread(new Runnable() {
                        
                        @Override
                        public void run() {
                            Toast.makeText(MainActivity.this, "网络连接错误", 0).show() ;
                        }
                    }) ;
                }
            };
        }.start();

}

//专门下载的类

// 专门下载的类
    public class DownLoadThread extends Thread {
        private String path;
        private int id;
        private int startIndex;
        private int endIndex;

public DownLoadThread(String path, int id, int startIndex, int endIndex) {
            this.path = path;
            this.id = id;
            this.startIndex = startIndex;
            this.endIndex = endIndex;
        }
        @Override
        public void run() {           
            //设置进度条
            ProgressBar pb =  list.get(id) ;                      
            int total = 0;// 记录每个线程已经下载了多少字节
            try {
                URL url = new URL(path);
                HttpURLConnection http = (HttpURLConnection) url
                        .openConnection();
                http.setRequestMethod("GET");
                http.setConnectTimeout(5000);
                // 读取相应的文件,判断文件是否存在,存在的话,应读取里面的数据
                //拿到sd卡的文件an存储路径
                String cunPath = Environment.getExternalStorageDirectory().getAbsolutePath() ;
                File file = new File(cunPath + "/" + id + ".txt");
                if (file.exists() && file.length() > 0) {
                    FileInputStream fis = new FileInputStream(file);
                    BufferedReader br = new BufferedReader(
                            new InputStreamReader(fis));
                    total = Integer.parseInt(br.readLine());
                    br.close();
                    // 改变线程下载的起始位置
                    startIndex =  startIndex + total;
                    System.out.println("线程" + id + "下载的真实范围:" + startIndex
                            + "~" + endIndex);
                }              
                //设置最大值
                pb.setMax(endIndex-startIndex) ;

// 注意,一定要设置一个请求头(范围),指定此线程要下载的数据的范围
                http.setRequestProperty("Range", "bytes=" + startIndex + "-"
                        + endIndex);

int code = http.getResponseCode();
                // 200代表的是服务器把数据向客户端传输完毕,206代表的是服务端传输局部数据完毕
                System.out.println("code =" + code);
                if (code == 206) {

InputStream is = http.getInputStream();
                    // 拿到已经在硬盘上的对应的文件
                    RandomAccessFile raf = new RandomAccessFile(
                            getFileName(path), "rw");
                    // 将文件的指针移动到开始写入的位置
                    raf.seek(startIndex);
                    // 将流中的数据写入到文件中

byte[] bs = new byte[1024];
                    int b = 0;

while ((b = is.read(bs)) != -1) {
                        raf.write(bs, 0, b);

total += b;

// 真正同步写入到底层的存储设备上
                        RandomAccessFile f = new RandomAccessFile(cunPath + "/" + id + ".txt",
                                "rws");
                        f.write((total + "").getBytes());
                        f.close();
                        
                        //改变进度条的当前位置
                        pb.setProgress(total) ;
                    }

raf.close();
                    is.close();

System.out.println("线程" + id + "下载完毕");
                    System.out.println("线程" + id + "下载的范围是:" + startIndex
                            + " ~" + endIndex);
                    
                    runningThreadcount-- ;
                    System.out.println(runningThreadcount);
                    if(runningThreadcount == 0){
                        //所有的线程都下载完毕了
                        runOnUiThread(new Runnable() {
                            
                            @Override
                            public void run() {
                                Toast.makeText(MainActivity.this, "文件下载成功", 0).show() ;
                            }
                        }) ;
                    }
                    // 将对应的临时文件删除
                    File tempFile = new File(cunPath + "/" + id + ".txt");
                    if (tempFile.exists())
                        tempFile.delete();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

/**
     * 通过用户传递的路径拿到文件名
     *
     * @param path
     * @return
     */
    public static String getFileName(String path) {
        String externalPath = Environment.getExternalStorageDirectory().getAbsolutePath() ;
        return  externalPath + "/" +path.substring(path.lastIndexOf("/") + 1);
    }

时间: 2024-10-11 19:34:45

android实现下载的核心代码的相关文章

Android版多线程下载器核心代码分享

首先给大家分享多线程下载核心类: 1 package com.example.urltest; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.io.RandomAccessFile; 6 import java.net.HttpURLConnection; 7 import java.net.MalformedURLException; 8 import java.net.URL; 9 im

Android发送短信核心代码

核心代码:(1)SmsManager manager = SmsManager.getDefault(); //获得默认的消息管理器(2)ArrayList<String> list = manager.divideMessage(String txt); //拆分长短信(3)manager.sendTextMessage(String phone,null,String content,null,null); //发送短信

android 后台截屏核心代码

RootCommand("su -c 'screencap /mnt/sdcard/screenaaa.png' && adb pull /sdcard/screenaaa.png") ; /** * 应用程序运行命令获取 Root权限,设备必须已破解(获得ROOT权限) * * @param command * 命令:String apkRoot="chmod 777 "+getPackageCodePath(); * RootCommand(ap

Libgdx: android单机斗地主支持局域网wifi联网的网络模块核心代码

这个作品是我最近写的,结合我的毕业设计的通信模块和之前的单机版斗地主.我已经上架到豌豆荚了,贴了点广告,看看能不能赚点茶钱.可是一点也不乐观.因此我想分享给大家源码.只要不用于商业. 下面先贴网络模块的核心代码,第一次写这种逻辑用的udp, 经验不够,没有写的那么好看. 这里是我上架的apk,大家下载来试试也无妨: 地址 http://www.wandoujia.com/apps/com.hj.joker package com.hj.net; import java.io.ByteArrayI

【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

译者地址:[翻]Android Design Support Library 的 代码实验--几行代码,让你的 APP 变得花俏 原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session--Make your app fancy with few lines of code 原文项目 demo: Lab-Android-DesignLibrary 双语对照地址: [翻-双语]Android D

Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

译者地址:[翻]Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏 原文:Codelab for Android Design Support Library used in I/O Rewind Bangkok session----Make your app fancy with few lines of code 原文项目 demo: Lab-Android-DesignLibrary 双语对照地址: [翻-双语]Android

Android 多线程下载原理剖析

今天带来一个多线程下载的 例子.先看一下效果,点击 下载 开始下载,同时显示下载进度,下载完成,变成程 安装,点击安装 提示 安装应用. 界面效果 这里写图片描述 线程池 ThreadPoolExecutor 在下面介绍实现下载原理的时候,我想尝试倒着来说,这样是否好理解一点? 我们都知道,下载助手,比如360, 百度的 手机助手,下载APP 的时候 ,都可以同时下载多个,所以,下载肯定是多线程的,所以我们就需要一个线程工具类 来管理我们的线程,这个工具类的核心,就是 线程池. 线程池Threa

android离线下载的相关知识

离线下载的功能点如下:      1.下载管理(开始.取消下载).      2.网络判断(Wi-Fi,3G).      3.独立进程.      4.定时和手机催醒.      5.自启动. 选择离线下载的核心方法 后台独立运行,我们很容易想到服务(Service),但是有以下几种问题 (1)如果服务的进程和应用一致,那么在应用退出后,服务会重启一次 (2)如果服务的进程和应用不一致,进程间的通信就会麻烦一点 (3)如果服务的进程和应用一致,选择IntentService,可以避免重启问题

【转】【翻】Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏

转自:http://mrfufufu.github.io/android/2015/07/01/Codelab_Android_Design_Support_Library.html [翻]Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏 Jul 1, 2015 译者地址:[翻]Android Design Support Library 的 代码实验——几行代码,让你的 APP 变得花俏 原文:Codelab for Androi