异步任务下载apk文件并弹出对话框提示当前进度,文件下载结束后弹出安装界面

原创 2016年08月30日 17:44:11

主要任务

1.下载apk保存到sd卡指定目录
2.下载时显示下载的进度
3.下载完成后弹出对话框提示安装

分析过程:

  1. 联网操作不能在UI线程(主线程)进行 需要开启线程下载,为了效率我们这里采用异步线程(AsyncTask)。
  2. 异步下载的同时需要在主界面更新UI,所以利用接口回调设置一个DialogProgress的进度条展示。
  3. 下载完成提示安装。


下面是完整代码:

先创建异步任务执行下载操作


package com.android.download;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import android.os.AsyncTask;
import android.os.Environment;

/**
 * 下载apk任务
 * 泛型一:String:表示下载的URL
 * 泛型二:Integer:每次读取进度条的返回值,用于界面更新
 * 泛型三:String:表示返回值类型,返回被下载的apk文件 的路径,为启动apk安装做准备
 * 
 */
public class MyTask extends AsyncTask<String, Integer, String> {

    public interface CallBack {
        public void start();  //任务开始这里面应该弹出进度条对话框

        public void updataProgress(int progress);//获取到更新的进度值为进度条对话框设置值

        /**
         * 下载完成,
         * 
         * 1.对话框消失
         * 
         * 2.启动安装apk界面,需要apk路径
         */
        public void finish(String apkPath);
    }

    CallBack cb;

    public MyTask(CallBack cb) {
        super();
        this.cb = cb;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        if (cb != null) {
            cb.start();
        }
    }

    @Override
    protected String doInBackground(String... params) {
        // 1.HttpURLConnection
        HttpURLConnection conn = null;
        String apkPath = null;
        // 2.URL
        try {
            URL url = new URL(params[0]);
            // 3.url.openConnection
            conn = (HttpURLConnection) url.openConnection();
            // 4.InputStream
            InputStream in = conn.getInputStream();
            // 获取该文件的总长度
            int total = conn.getContentLength();
            // 5.获取保存文件的路径及文件 名/sdcard/abcdefg/tmp.apk
            String path_sdcard = Environment.getExternalStorageDirectory()
                    .getAbsolutePath() + "/abcdefg";
            File fileParent = new File(path_sdcard);
            // 判断该目录是否存在,如果不存在,创建该目录
            if (!fileParent.exists()) {
                // 创建目录
                fileParent.mkdirs();
            }
            // 6.创建File对象,再拿到OutputStream
            File file = new File(path_sdcard, "tmp.apk");
            //用来返回该apk路径
            apkPath = file.getAbsolutePath();
            OutputStream out = new FileOutputStream(file);
            // 7.创建byte[] buffer
            byte[] buffer = new byte[4096];
            // 8.inputStream==>OutputStream
            // 循环读写时,应该要把每次读入的长度进行累加,再把累加的值与总长度除一下,得到百分比用于更新进度条的值
            int sum = 0;
            int len = 0;
            while ((len = in.read(buffer)) != -1) {
                out.write(buffer, 0, len);
                // 累加
                sum = sum + len;
                // 计算百分比
                int per = (int) (sum * 100f / total);
                // 发布进度值
                publishProgress(per);
            }
            out.flush();
            // 收尾
            out.close();
            in.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            if (conn != null) {
                conn.disconnect();
            }
        }
        // 返回当前被保存的apk的绝对路径
        return apkPath;
    }

    @Override
    protected void onProgressUpdate(Integer... values) {
        // TODO Auto-generated method stub
        super.onProgressUpdate(values);
        if (cb != null) {
            cb.updataProgress(values[0]);
        }
    }

    /*
     * result表示的是apk的路径
     */
    @Override
    protected void onPostExecute(String result) {
        // TODO Auto-generated method stub
        super.onPostExecute(result);
        if (cb != null) {
            cb.finish(result);
        }
    }

}

package com.android.download;

import java.io.File;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;

import com.android.download.MyTask.CallBack;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    ProgressDialog pd;

    // 点击下载apk
    public void downlaod(View view) {
        // 1.启动下载任务
        MyTask task = new MyTask(new CallBack() {

            @Override
            public void updataProgress(int progress) {
                pd.setProgress(progress);

            }

            @Override
            public void start() {
                pd = new ProgressDialog(MainActivity.this);
                pd.setTitle("下载提示");
                pd.setMessage("正在下载apk...");
                pd.setCancelable(false); //设置下载过程对话框不能消失
                pd.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                pd.show();

            }

            @Override
            public void finish(String apkPath) {
                // 消失对话框
                pd.dismiss();
                // 启动安装
                installApk(apkPath);
            }
        });
        task.execute("apkPath");//需要下载的apk链接
    }

    /**
     * 安装apk
     * 
     * @param url
     */
    private void installApk(String apkFilePath) {
        File apkfile = new File(apkFilePath);
        if (!apkfile.exists()) {
            return;
        }
        Intent i = new Intent(Intent.ACTION_VIEW);
        i.setDataAndType(Uri.parse("file://" + apkfile.toString()),
                "application/vnd.android.package-archive");
        startActivity(i);
    }
}

xml

<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.example.day012_downloadapk.MainActivity" >

    <Button
        android:onClick="downlaod"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="下载apk" />

</RelativeLayout>


不要忘了添加联网权限和读写sd卡权限:

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

界面效果图:
这里写图片描述

最后读者可以自己加个判断文件是否已经存在 如果已经存在启动安装即可


版权声明:本文为博主原创文章,转载请注明出处

AsyncTask 异步任务 + ProgressDialog 进度条对话框

一, 什么是异步任务     使用子线程执行耗时的操作, 然后通过回调把结果返回给主线程 二, 为什么要使用异步任务 1, android 使用线程的规则: ...

关于创建Excel表格问题(保存至指定文件/弹出直接打开还是下载,并可以选择保存路径的对话框)

本文主要是针对在Action中创建Excel表格,一种是直接将文件写入指定的路径,另一种是弹出直接打开还是下载,并可以选择保存路径的提示 第一步:导入poi包 第二步:编写代码 import java...

JS实现弹出下载对话框及常见文件类型的下载

原文链接:http://www.cnblogs.com/liuxianan/p/js-download.html S要实现下载功能,一般都是这么几个过程:生成下载的URL,动态创建一个A标签,并将其...
  • lltaoyy
  • lltaoyy
  • 2017年11月24日 16:26
  • 62

jquery jBox弹出层 确认对话框 提示信息 加载进度条等

简介:jqueryjBox弹出层确认对话框提示信息加载进度条等。 jquery jBox弹出层 确认对话框 提示信息 加载进度条等。 ...

Code::Blocks代码自动提示设置及常用快捷键(适用windows和linux) 1)以下需要设置的地方均在Settings->Editor...弹出的对话框中。 2)不少命令都可针对当前行或

Code::Blocks代码自动提示设置及常用快捷键(适用windows和linux) 1)以下需要设置的地方均在Settings->Editor...弹出的对话框中。 2)不少命令都...

解决matlab安装后没有快捷方式启动弹出DOS界面并且m文件无关联的方法

试了matlab的2011版和2013a两个版本,默认安装后都出现了yix

不使用控件弹出文件对话框

  • 2004年01月11日 00:00
  • 5KB
  • 下载

弹出文件选择对话框(支持多选)

不多说,贴出代码
  • wwkaven
  • wwkaven
  • 2014年07月03日 09:31
  • 1912
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:异步任务下载apk文件并弹出对话框提示当前进度,文件下载结束后弹出安装界面
举报原因:
原因补充:

(最多只允许输入30个字)