下载apk文件显示进度最后并执行安装
作者:飞入蓝天 来源: 网络 人气:91 类型: 免费 价格:¥5 所属课程:Android APP应用开发    
本文档有配套视频,购买本文档或加入该课程后可播放!

允许运行Flash播放器吗?如未安装,请先安装Flash Player(版本: 11.4.0)或更高版本.

1、  先创建布局文件

<RelativeLayout
    android:layout_below="@+id/headFrame"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@color/white">
 <LinearLayout
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:layout_gravity="center"
     android:layout_centerInParent="true"
     android:orientation="vertical">
    <ProgressBar
        android:id="@+id/progressBar"
        android:layout_marginTop="50dp"
        style="?android:attr/progressBarStyleHorizontal"
        android:layout_width="match_parent"
        android:layout_marginLeft="10dp"
        android:layout_marginRight="10dp"
        android:layout_height="wrap_content" />
    
     <TextView
            android:id="@+id/downInfo"
            android:layout_width="wrap_content"
            android:layout_height="30dp"
            android:layout_marginLeft="5dp"
            android:layout_marginRight="5dp"
            android:layout_gravity="center"
            android:layout_marginTop="10dp"
            android:text="正在下载..."
            android:gravity="center"
            android:layout_weight="1"
            android:clickable="true" />

    <LinearLayout/>
<RelativeLayout/>


2、  获得权限

AndroidManifest.xml文件里添加外部存储的权限:


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


 

对于android高版本,要动态获取权限:


public static void verifyStoragePermissions(android.app.Activity activity) {
    try {
    //检测是否有写的权限
        int permission = android.support.v4.app.ActivityCompat.checkSelfPermission(activity,
                "android.permission.WRITE_EXTERNAL_STORAGE");
        if (permission != android.content.pm.PackageManager.PERMISSION_GRANTED) {
    // 没有写的权限,去申请写的权限,会弹出对话框
            android.support.v4.app.ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE,REQUEST_EXTERNAL_STORAGE);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

 在onCreate里调用该函数即可。


3、  下载文件代码

/**
 * 开始下载
 */
public void down(){
    //获取下载资源的路径
    final String path = "http://www.wave12.com/bigfish/tmp/autoAcid.apk";

    //开启一个线程进行下载
    new Thread(){
        public void run() {
            try {
                //构造URL地址
                URL url=new URL(path);
                //打开连接
                HttpURLConnection conn=(HttpURLConnection) url.openConnection();
                //设置请求超时的时间
                conn.setConnectTimeout(5000);
                //设置请求方式
                conn.setRequestMethod("GET");
                //获取相应码
                int code=conn.getResponseCode();
                if (code==200) {//请求成功
                    //获取请求数据的长度
                    int length=conn.getContentLength();
                    //设置进度条的最大值
                    mProgressBar.setMax(length);
                    //在客户端创建一个跟服务器文件大小相同的临时文件
                    //String path =Environment.getExternalStorageDirectory().getPath();
                    File pathDir = getFilesDir();
                    File Folder = new File(getBaseContext().getFilesDir(), "download");
                    if (!Folder.exists())//判断文件夹是否存在,不存在则创建文件夹,已经存在则跳过
                    {
                        Folder.mkdir();//创建文件夹
                    }
                    String pathRet = pathDir.getAbsolutePath();
                    RandomAccessFile raf=new RandomAccessFile( Environment.getExternalStorageDirectory() + "/autoAcid.apk", "rwd");
                    //指定临时文件的长度
                    raf.setLength(length);
                    raf.close();
                    //假设3个线程去下载资源
                    //平均每一个线程要下载的文件的大小
                    int blockSize=length/threadCount;
                    for (int threadId = 1; threadId <= threadCount; threadId++) {
                        //当前线程下载数据的开始位置
                        int startIndex=blockSize*(threadId-1);
                        //当前线程下载数据的结束位置
                        int endIndex=blockSize*threadId-1;
                        //确定最后一个线程要下载数据的最大位置
                        if (threadId==threadCount) {
                            endIndex=length;
                        }
                        //显示下载数据的区间
                        System.out.println("线程【"+threadId+"】开始下载:"+startIndex+"---->"+endIndex);
                        //开启下载的子线程
                        new DownloadThread(path, threadId, startIndex, endIndex).start();
                        //当前下载活动的线程数加1
                        activeThread++;
                        System.out.println("当前活动的线程数:"+activeThread);
                    }

                }else{//请求失败
                    System.out.println("服务器异常,下载失败!");
                }
            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("服务器异常,下载失败!");
            }
        };
    }.start();

}
/**
 * 下载文件的子线程 每一个文件都下载对应的数据
 * @author YUANYUAN
 *
 */
public class DownloadThread extends Thread{
    private String path;
    private int threadId;
    private int startIndex;
    private int endIndex;

    /**
     * 构造方法
     * @param path 下载文件的路径
     * @param threadId 下载文件的线程
     * @param startIndex 下载文件开始的位置
     * @param endIndex 下载文件结束的位置
     */
    public DownloadThread(String path, int threadId, int startIndex,
                          int endIndex) {
        this.path = path;
        this.threadId = threadId;
        this.startIndex = startIndex;
        this.endIndex = endIndex;
    }



    @Override
    public void run() {
        //构造URL地址
        try {
            File tempFile=new File("sdcard/"+threadId+".txt");
            //检查记录是否存在,如果存在读取数据,设置真实下载开始的位置
            if (tempFile.exists()) {
                FileInputStream fis=new FileInputStream(tempFile);
                byte[] temp=new byte[1024];
                int length=fis.read(temp);
                //读取到已经下载的位置
                int downloadNewIndex=Integer.parseInt(new String(temp, 0, length));
                //计算出已经下载的数据长度
                int areadyDown=downloadNewIndex-startIndex;
                //累加已经下载的数据量
                curDownCount+=areadyDown;
                //设置进度条已经下载的数据量
                mProgressBar.setProgress(curDownCount);
                //设置重新开始下载的开始位置
                startIndex=downloadNewIndex;
                fis.close();
                //显示真实下载数据的区间
                System.out.println("线程【"+threadId+"】真实开始下载数据区间:"+startIndex+"---->"+endIndex);
            }

            URL url = new URL(path);
            HttpURLConnection conn=(HttpURLConnection) url.openConnection();
            conn.setConnectTimeout(5000);
            conn.setRequestMethod("GET");
            //设置请求属性,请求部分资源
            conn.setRequestProperty("Range", "bytes="+startIndex+"-"+endIndex);
            int code=conn.getResponseCode();
            if (code==206) {//下载部分资源,正常返回的状态码为206
                InputStream is=conn.getInputStream();//已经设置了请求的位置,所以返回的是对应的部分资源
                //构建随机访问文件
                //String path =Environment.getExternalStorageDirectory().getPath();
                File pathDir = getFilesDir();
                String pathRet = pathDir.getAbsolutePath();
                RandomAccessFile raf=new RandomAccessFile(Environment.getExternalStorageDirectory() + "/autoAcid.apk", "rwd");
                //设置 每一个线程随机写文件开始的位置
                raf.seek(startIndex);
                //开始写文件
                int len=0;
                byte[] buffer=new byte[1024];
                //该线程已经下载数据的长度
                int total=0;

                while((len=is.read(buffer))!=-1){//读取输入流
                    //记录当前线程已下载数据的长度
                    RandomAccessFile file=new RandomAccessFile("sdcard/"+threadId+".txt","rwd");
                    raf.write(buffer,0,len);//写文件
                    total+=len;//更新该线程已下载数据的总长度
                    System.out.println("线程【"+threadId+"】已下载数据:"+(total+startIndex));
                    //将已下载数据的位置记录写入到文件
                    file.write((startIndex+total+"").getBytes());
                    //累加已经下载的数据量
                    curDownCount+=len;
                    //更新进度条【进度条的更新可以在非UI线程直接更新,具体见底层源代码】
                    mProgressBar.setProgress(curDownCount);

                    //更新下载进度
                    Message msg=Message.obtain();
                    msg.what=UPDATE_PROGRESS;
                    msg.obj = curDownCount;
                    handler.sendMessage(msg);

                    file.close();
                }
                is.close();
                raf.close();
                //提示下载完毕
                System.out.println("线程【"+threadId+"】下载完毕");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("线程【"+threadId+"】下载出现异常!!");
        }finally{
            //活动的线程数减少
            activeThread--;
            if (activeThread==0) {
                for (int i = 1; i <= threadCount; i++) {
                    File tempFile=new File("sdcard/"+i+".txt");
                    tempFile.delete();
                }
                System.out.println("下载完毕,已清除全部临时文件");
                //界面消息提示下载完毕
                Message msg=new Message();
                msg.what=downloadOver;
                handler.sendMessage(msg);
            }
        }

    }
}


4、  下载完成后执行安装

//加入消息处理机制
private Handler handler;

{
    handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case downloadOver:
                    Toast.makeText(UpgradeActivity.this, "文件已下载完毕!", Toast.LENGTH_LONG).show();
                    mDownInfo.setText("下载完成");

                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    //String path =Environment.getExternalStorageDirectory().getPath();
                    File pathDir = getFilesDir();
                    String pathRet = pathDir.getAbsolutePath();
                    String apkPath = Environment.getExternalStorageDirectory() + "/autoAcid.apk";
                    if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N) {
                        File file = (new File(apkPath));
                        // 由于没有在Activity环境下启动Activity,设置下面的标签
                        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        //添加这一句表示对目标应用临时授权该Uri所代表的文件
                        intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                        //参数1:上下文, 参数2:Provider主机地址 和配置文件中保持一致,参数3:共享的文件
                        Uri apkUri = FileProvider.getUriForFile(getApplicationContext(),
                                "com.wave12.autoacid.fileProvider", file);
                        intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                    } else {
                        intent.setDataAndType(Uri.fromFile(new File(apkPath)),
                                "application/vnd.android.package-archive");
                    }
                    startActivity(intent);
                    break;
                case UPDATE_PROGRESS:
                    //更新进度显示
                    int curProgressValue = (int) (msg.obj);
                    int maxValue = mProgressBar.getMax();
                    int percent = (int) ((curProgressValue * 100.0) / maxValue);
                    mDownInfo.setText("当前进度:" + (curProgressValue * 100.0 / maxValue) + "%");
                    break;
                default:
                    break;
            }
        }
    };
}
   

对于高版本,要配置FileProvider, AndroidManifest.xml文件的application节内部添加

<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.wave12.autoacid.fileProvider"
    android:grantUriPermissions="true"
    android:exported="false">
    
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
<provider/>

 com.wave12.autoacid是包名,要和handler里的getUriForFile函数代码处的第二个参数一致。


本文为付费文档,请购买或加入所属课程查阅全部内容!

评论

正在加载评论...
提交评论

  •  1. 获取android顶部状态栏的高度
  •  2. android通过代码隐藏和显示标题栏 试看
  •  3. 使用surfaceview和MediaPlayer播放视频 试看
  •  4. Android布局
  •  5. Android开发环境搭建之Android Studio安装 试看
  •  6. 实现Activity页面延迟跳转的两种方法 试看
  •  7. Android APP集成支付宝支付功能 试看
  •  8. 下载apk文件显示进度最后并执行安装 试看
十二维网, 版权所有©2005-2018
电话:15013459492 (宋生)  
Email:wave12@126.com
深圳总部:深圳市福田区八卦四路先科机电大厦6楼
网站备案:粤ICP备10018904号