Android简单的异步下载文件更新进度条

我的整个操作在fragment中进行,与在活动中进行无异;

一、在xml中添加两个控件:按钮(用于开启下载操作),进度条(用于查看下载进度);

二、准备好所需常量(用于handler传递消息)以及下载链接;


 三、实例化控件对象,以及为按钮设置监听;

 点击按钮便开始进行下载操作,download方法用于进行下载操作,传入的形参为下载链接,由于下载方法内有相关网络操作,需放在线程中进行(线程通过Thread匿名内部类简单实现,由于并没有创建线程池,AS给出相应提示(冒黄线),但并不影响程序执行);


四、准备好handler对象,使用handler进行异步操作,并通过handler传送下载进度;

重写handler类的handMessage方法,用于接收download方法传来的消息,消息定义为两种:网络连接成功和网络连接失败;

DOWNLOAD_MESSAGE_CODE表示网络连接成功,DOWNLOAD_MESSAGE_FILE_CODE则表示传输失败

被注释掉的行为放在后面讲解;


五、实现download方法(核心),代码稍微有点长,但是细节慢慢、通俗易懂,请耐心观看!!!

private void download(String appUrl) {
        try {
            //创建URL对象
            URL url = new URL(appUrl);
            //获取URL连接对象
            URLConnection connection = url.openConnection();

            //获取连接的输入流对象
            InputStream inputStream = connection.getInputStream();
            //获取文件总长度
            int contentLength = connection.getContentLength();
            Log.d(TAG, "文件总长度: " + contentLength);

            /*
            getContext().getFilesDir()表示外部存储
            通过getAbsolutePath()获得外部存储路径
            File.separator表示分隔符 "\"
            以下路径表示SD卡的”imooc“文件
             */
            //创建存储apk的目录文件路径
            String downloadFolderName = getContext().getFilesDir().getAbsolutePath()
                    + File.separator + "APP" + File.separator;

            //通过路径创建文件夹对象,用于存放apk文件
            File file = new File(downloadFolderName);
            //如果该目录文件不存在则创建
            if (!file.exists()){
                file.mkdir();
            }

            //在刚创建的文件下,创建文件名,用于存放下载的apk
            String fileName = downloadFolderName + "APP.apk";
            //定义一个下载的长度
            int downloadSize = 0;

            //用于传输文件
            byte[] bytes = new byte[1024];

            //用于判断
            int length = 0;

            /*
            OutputStream需要注意的细节:
            1、如何文件夹存在则先清空文件夹,如果不存在则创建,然后再写入(但如果目标文件所在的文件夹不存在,则抛出异常)
            2、如果目标文件已经存在,则会先清空文件中的数据,然后再写入新的数据
             */
            OutputStream outputStream = new FileOutputStream(fileName,false);
            //读取数据
            while((length = inputStream.read(bytes)) != -1){
                outputStream.write(bytes,0,length);
                downloadSize += length;
                
                /*
                message对象可携带四个参数:what、arg1、arg2、obj;
                第一个参数为消息编码,整形。用于区分不同消息
                第二和第三都为整形参数,用于传输整形数据
                第四个为obj类型。可携带任意对象
                 */
                //创建消息对象,用于发送进度值给主线程来更新UI
                Message message = Message.obtain();
                //将下载进度比作为对象进行传输(由于我给进度条设置的最大值是一百,算出进度比,然后乘以100便是对应的进度值)
                message.obj = downloadSize * 100 /contentLength;
                message.what = DOWNLOAD_MESSAGE_CODE;
                //发送消息
                handler.sendMessage(message);
            }
            //关闭流
            inputStream.close();
            outputStream.close();

        } catch (MalformedURLException e) {
            notifyDownloadFile(e.getMessage());
            e.printStackTrace();
        } catch (IOException e) {
            notifyDownloadFile(e.getMessage());
            e.printStackTrace();
        }
    }

 该方法用于发送错误消息

protected void notifyDownloadFile(String error){
   Message message = Message.obtain();
   message.obj = error;
   message.what = DOWNLOAD_MESSAGE_FILE_CODE;
   handler.sendMessage(message);
}

再回到接收消息的地方

switch (msg.what){
                    //传输成功
                    case DOWNLOAD_MESSAGE_CODE:
                        // TODO: 设置进度条
                        bar.setProgress((Integer) msg.obj);
                        if (bar.getProgress() == 100){
                            Toast.makeText(getActivity(),"下载完成",Toast.LENGTH_SHORT).show();
                            bar.setProgress(0);
                        }
                        break;
                    //传输失败
                    case DOWNLOAD_MESSAGE_FILE_CODE:
                        // TODO: 打印错误日志
                        /*String Message = (String) msg.obj;
                        Log.d(TAG, "ErrorMessage: " + Message);*/
                        break;
                    default:
                }

通过switch区分开消息类型,在下载的过程中,download方法会远远不断的向主线程发送消息,直到下载完成,而主线程(UI线程)则来完成进度条的加载操作;


六、最后一步,同时也是最最最不应该忘记的一步,在AndroidManifest.xml写入相关权限

 一个为网络访问权限,二为读文件权限,三为写文件权限;


七、!!!重要的事情说三遍

在Android9.0版本中,对网络安全有较高的要求,如果访问的是https协议则不受影响;

而若是访问了http协议的网站,则还需要添加安全配置文件,步骤如下:

1、创建安全配置文件

在res中创建一个xml目录,在此目录下新建一个”network_security_config"文件(文件名和内容不可修改),文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted = "true"/>
</network-security-config>

2、添加安全配置

在 AndroidManifest.xml添加该配置

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值