Android 通过 WebView 请求下载 APK

很少去研究 Webview 的具体使用,之前在项目中遇到,通过点击 H5 中的按钮来进行下载 Apk 。刚收到这个需求想到的第一个想法就是调用 JS 来实现。之后实际运用前去看了看 WebView 的 API 发现了  WebView 下有一个 setDownloadListener 方法。它主要就是负责当你需要在使用 webview 时下载资源用的。具体的下载 APK 方法:

一个 Downloader 下载工具:

import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.os.Environment;
import android.support.v4.content.FileProvider;
import android.widget.Toast;

import java.io.File;

/**
 * Created by 49829 on 2017/8/28.
 */

public class Downloader {
    //下载器
    private DownloadManager downloadManager;
    //上下文
    private Context mContext;
    //下载的ID
    private long downloadId;

    public Downloader(Context context) {
        this.mContext = context;
    }

    //下载apk
    public void downloadAPK(String url, String name) {

        //创建下载任务
        DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
        //移动网络情况下是否允许漫游
        request.setAllowedOverRoaming(false);

        //在通知栏中显示,默认就是显示的
        request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
        request.setTitle("雪豹外汇");
        request.setDescription("正在下载...");
        request.setVisibleInDownloadsUi(true);

        //设置下载的路径
        request.setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory().getAbsolutePath(), name);

        //获取DownloadManager
        downloadManager = (DownloadManager) mContext.getSystemService(Context.DOWNLOAD_SERVICE);
        //将下载请求加入下载队列,加入下载队列后会给该任务返回一个long型的id,通过该id可以取消任务,重启任务、获取下载的文件等等
        downloadId = downloadManager.enqueue(request);

        //注册广播接收者,监听下载状态
        mContext.registerReceiver(receiver,
                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
    }

    //广播监听下载的各个状态
    private BroadcastReceiver receiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            checkStatus();
        }
    };


    //检查下载状态
    private void checkStatus() {
        DownloadManager.Query query = new DownloadManager.Query();
        //通过下载的id查找
        query.setFilterById(downloadId);
        Cursor c = downloadManager.query(query);
        if (c.moveToFirst()) {
            int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
            switch (status) {
                //下载暂停
                case DownloadManager.STATUS_PAUSED:
                    break;
                //下载延迟
                case DownloadManager.STATUS_PENDING:
                    break;
                //正在下载
                case DownloadManager.STATUS_RUNNING:
                    break;
                //下载完成
                case DownloadManager.STATUS_SUCCESSFUL:
                    //下载完成安装APK
                    installAPK();
                    break;
                //下载失败
                case DownloadManager.STATUS_FAILED:
                    Toast.makeText(mContext, "下载失败", Toast.LENGTH_SHORT).show();
                    break;
            }
        }
    }

    //下载到本地后执行安装
    private void installAPK() {

        Intent intent = new Intent();
        File apkFile = queryDownloadedApk();
        Uri uri;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {//7.0启动姿势
    //com.xxx.xxx.fileprovider为上述manifest中provider所配置相同;apkFile为问题1中的外部存储apk文件
uri = FileProvider.getUriForFile(mContext, "com.zz.fileprovider", apkFile); intent.setAction(Intent.ACTION_INSTALL_PACKAGE); intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);//7.0以后,系统要求授予临时uri读取权限,安装完毕以后,系统会自动收回权限,次过程没有用户交互 } else {//7.0以下启动姿势 uri = Uri.fromFile(apkFile); intent.setAction(Intent.ACTION_VIEW); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); } intent.setDataAndType(uri, "application/vnd.android.package-archive"); mContext.startActivity(intent); } public File queryDownloadedApk() { File targetApkFile = null; if (downloadId != -1) { DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL); Cursor cur = downloadManager.query(query); if (cur != null) { if (cur.moveToFirst()) { String uriString = cur.getString(cur.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); if (!uriString.isEmpty()) { targetApkFile = new File(Uri.parse(uriString).getPath()); } } cur.close(); } } return targetApkFile; } }
直接在 WebView  的下载监听中使用:

   webView.setDownloadListener(new DownloadListener() {
                            @Override
                            public void onDownloadStart(final String url, String userAgent, String contentDisposition, String mimetype, long contentLength) {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        //使用前先判断是否有读取、写入内存卡权限
                                        if (ContextCompat.checkSelfPermission(RechargeActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                                            ActivityCompat.requestPermissions(RechargeActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_WRITE_EXTERNAL_STORAGE2);
                                        } else {
                                            downloadAPK.downloadAPK(url,"***.apk");//DownLoader 需要在oncreate 中初始化
                                        }
                                    }
                                });


                            }
                        });




你可能感兴趣的:(记录)