Android-多线程断点下载详解及源码下载(四)

本项目完成的功能类似与迅雷等下载工具所实现的功能——实现多线程断点下载。

主要设计的技术有:

1、android中主线程与非主线程通信机制。

2、多线程的编程和管理。

3、android网络编程

4、自己设计实现设计模式-监听器模式

5、Activity、Service、数据库编程

6、android文件系统

7、缓存

博文链接:

Android-多线程断点下载详解及源码下载(一)

Android-多线程断点下载详解及源码下载(二)

Android-多线程断点下载详解及源码下载(三)

本篇完结多线程断点下载,继续上面三篇文章的内容。

从上面三篇的内容已经全部给出了Activity界面所需要的内容,下面给出MainActivity代码:

public class MainActivity extends Activity {

    private EditText loaderPath;
    private Button start,stop;
    private ProgressBar progressBar;
    private TextView progressNum;
    private final int THREADNUM = 3;
    private Task task;

    private static final int PROGRESS = 0;
    private static final int FAILURE = 1;
    private MultiThreadManager manager;

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
            case PROGRESS:
//              float prog = (float)progressBar.getProgress()/(float)progressBar.getMax();
                float prog1 = ((float)manager.getDownedLen()/(float)manager.getFileLen())*100;
                progressBar.setProgress((int)prog1);
                progressNum.setText((int)(prog1)+"%"+100);
                if (prog1 >= 100) {
                    Toast.makeText(MainActivity.this, "下载完成", Toast.LENGTH_SHORT)
                    .show();
                }
                break;
            default:
                break;
            }
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        init();
        setListener();
    }
    private void setListener() {
        start.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    File saveDir = Environment.getExternalStorageDirectory();
                    task = new Task(saveDir, loaderPath.getText().toString());
                    new Thread(task).start();
                }else {
                    Toast.makeText(MainActivity.this,
                        "无SD卡", Toast.LENGTH_SHORT).show();
                }
                start.setClickable(false);
                stop.setClickable(true);
            }
        });
        stop.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                exit();
                start.setClickable(true);
                stop.setClickable(true);
            }
        });
    }
    private void init() {
        loaderPath = (EditText) findViewById(R.id.path);
        start = (Button) findViewById(R.id.start_loader);
        stop = (Button) findViewById(R.id.stop_loader);
        progressBar = (ProgressBar) findViewById(R.id.progressBar);
        progressNum = (TextView) findViewById(R.id.progress_num);
        progressBar.setMax(100);

    }

    private void exit(){
        if (task != null) {
            task.exit();
        }
    }

    private class Task implements Runnable{
        private String path;
        private File saveDir;
        public Task(File saveDir,String path){
            this.saveDir = saveDir;
            this.path = path;
            System.out.println("MainActivity.Task.Task() 下载路径="+this.path);
        }

        public void exit(){
            if (manager != null) {
                manager.setExist(true);
            }
        }
        @Override
        public void run() {
            try {
                manager = new MultiThreadManager(THREADNUM,
                        path, saveDir, MainActivity.this);
                progressBar.setMax(100);
                manager.downloader(new IDownProgressing() {
                    @Override
                    public void setDownLoaderNum(int size) {
                        Message msg = new Message();
                        msg.what = PROGRESS;
                        msg.obj = size;
                        handler.sendMessage(msg);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
                handler.sendMessage(handler.obtainMessage(FAILURE));
            }
        }

    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        this.exit();
    }
    @Override
    public void onBackPressed() {
        super.onBackPressed();
        finish();
    }
}

主界面就没有什么要特别说明得了,注释部分也比较详细。布局文件也非常简单:

<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
               tools:context="com.yin.multithreaddownloader.activity.MainActivity" >

    <EditText
        android:id="@+id/path"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="http://192.168.2.63:8080/ds/my.mp3" />
    <LinearLayout
        android:id="@+id/button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@id/path"
        android:orientation="horizontal">
        <Button
            android:id="@+id/start_loader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="开始下载"
            android:textSize="16sp"
            />
        <Button
            android:id="@+id/stop_loader"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="停止下载"
            android:textSize="16sp"
            />
    </LinearLayout>

    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/button"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="15dp"
         />
    <TextView
        android:id="@+id/progress_num"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/progressBar"
        android:layout_alignParentRight="true"
        android:layout_marginTop="10dp"/>
</RelativeLayout>

这里面要注意的是http://192.168.2.63:8080/ds/my.mp3这个值,这个值是服务器的地址,需要根据自己的配置进行更改的,所以不可以照搬的!

总结:

多线程断点续传下载涉及了android应用开发的大部分知识点和难点。特别是多线程管理、网络请求、文件管理、数据库编程等都是非常重要的内容。另外,如果大家对服务器开发有兴趣、或者想了解服务器开发的知识可以学习ssh框架,当然服务器框架有很多,不一定非要使用ssh,但是我个人觉得ssh还是比较简单的,特别是jsp servlet内容,需要达到比较熟悉的程度。

另外对于本项目中值得提醒的是,需要在AndroidManifest.xml配置相应的权限:

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

洋洋洒洒写了四篇,不知道是否说的明白,大家姑且看看,如果有什么不对的地方,希望大家踊跃指正,共同交流学习!【握手】

博文链接:

Android-多线程断点下载详解及源码下载(一)

Android-多线程断点下载详解及源码下载(二)

Android-多线程断点下载详解及源码下载(三)

源码下载(服务器端和客户端代码)

时间: 2024-10-14 03:04:05

Android-多线程断点下载详解及源码下载(四)的相关文章

Android-多线程断点下载详解及源码下载(三)

本项目完成的功能类似与迅雷等下载工具所实现的功能--实现多线程断点下载. 主要设计的技术有: 1.android中主线程与非主线程通信机制. 2.多线程的编程和管理. 3.android网络编程 4.自己设计实现设计模式-监听器模式 5.Activity.Service.数据库编程 6.android文件系统 7.缓存 博文链接: Android-多线程断点下载详解及源码下载(一) Android-多线程断点下载详解及源码下载(二) Android-多线程断点下载详解及源码下载(四) 本篇接着上

Android异步消息处理机制详解及源码分析

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 最近相对来说比较闲,加上养病,所以没事干就撸些自己之前的知识点为博客,方便自己也方便别人. 1 背景 之所以选择这个知识点来分析有以下几个原因: 逛GitHub时发现关注的isuss中有人不停的在讨论Android中的Looper , Handler , Me

Linux nohup命令详解pk10源码下载

现象:pk10源码下载(企 娥:217 1793 408) 把java程序打成jar包后,放到linux上通过putty或其它终端执行的时候, 如果按照:java -jar xxxx.jar执行,当我们退出putty或终端的时候,xxxx.jar这个程序也会停止. 为了保证程序能够一直运行,应该改为这样运行:nohup java -jar xxx.jar&命令,则程序会在后台一直运行, 值得注意的是,此时程序控制台输出会被转移到nohup.out文件中, 这个nohup.out文件的位置就在ja

Android应用Loaders全面详解及源码浅析

1 背景 在Android中任何耗时的操作都不能放在UI主线程中,所以耗时的操作都需要使用异步实现.同样的,在ContentProvider中也可能存在耗时操作,这时也该使用异步操作,而3.0之后最推荐的异步操作就是Loader.它可以方便我们在Activity和Fragment中异步加载数据,而不是用线程或AsyncTask,他的优点如下: 提供异步加载数据机制: 对数据源变化进行监听,实时更新数据: 在Activity配置发生变化(如横竖屏切换)时不用重复加载数据: 适用于任何Activit

Android应用AsyncTask处理机制详解及源码分析

[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 Android异步处理机制一直都是Android的一个核心,也是应用工程师面试的一个知识点.前面我们分析了Handler异步机制原理(不了解的可以阅读我的<Android异步消息处理机制详解及源码分析>文章),这里继续分析Android的另一个异步机制AsyncTask的原理. 当使用线程和Handler组合实现异步处理时,当每次执行耗时操作都创建一条新线程进行处理,性能开销会比

Android应用Context详解及源码解析

[工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果] 1 背景 今天突然想起之前在上家公司(做TV与BOX盒子)时有好几个人问过我关于Android的Context到底是啥的问题,所以就马上要诞生这篇文章.我们平时在开发App应用程序时一直都在使用Context(别说你没用过,访问当前应用的资源.启动一个activity等都用到了Context),但是很少有人关注过这玩意到底是啥,也很少有人知道getApplication与getApplica

Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇)

1 背景 还记得前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事件疑惑吗?当时说了,在那一篇咱们只讨论View的触摸事件派发机制,这个疑惑留在了这一篇解释,也就是ViewGroup的事件派发机制. PS:阅读本篇前建议先查看前一篇<Android触摸屏事件派发机制详解与源码分析一(View篇)>,这一篇承接上一篇. 关于View与ViewGroup的区别在前一篇的A

Android触摸屏事件派发机制详解与源码分析

请看下面三篇博客,思路还是蛮清晰的,不过还是没写自定义控件系列哥们的思路清晰: Android触摸屏事件派发机制详解与源码分析一(View篇) http://blog.csdn.net/yanbober/article/details/45887547 Android触摸屏事件派发机制详解与源码分析二(ViewGroup篇) http://blog.csdn.net/yanbober/article/details/45912661 Android触摸屏事件派发机制详解与源码分析三(Activi

Android ViewGroup触摸屏事件派发机制详解与源码分析

PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbober] 该篇承接上一篇<Android View触摸屏事件派发机制详解与源码分析>,阅读本篇之前建议先阅读. 1 背景 还记得前一篇<Android View触摸屏事件派发机制详解与源码分析>中关于透过源码继续进阶实例验证模块中存在的点击Button却触发了LinearLayout的事