使用DownloadManager处理App升级的处理方式

使用DownloadManager来处理App下载功能的方式已经不算什么新鲜事,但我再真正使用时,却不断踩到坑,这也许就是许多人不推崇用它的原因吧,在此我说一些自己的处理方式。

先看整个代码:

public class UpdateService extends Service {

    private String mPath;
    private long mEnqueue;

    public UpdateService() {

    }

    /**
     * 安卓系统下载类
     **/
    DownloadManager manager;

    /**
     * 接收下载完的广播
     **/
    DownloadCompleteReceiver receiver;

    /**
     * 初始化下载器
     **/
    private void initDownManager() {


        receiver = new DownloadCompleteReceiver();

        //设置下载地址
        Uri parse = Uri.parse(mPath);
        DownloadManager.Request down = new DownloadManager.Request(parse);

        // 设置允许使用的网络类型,这里是移动网络和wifi都可以
        down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);

        // 下载时,通知栏显示途中
        down.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);

        // 显示下载界面
        down.setVisibleInDownloadsUi(true);

        // 设置下载后文件存放的位置
        File saveFile = new File(Environment.getExternalStorageDirectory(), "youjintang.apk");
        down.setDestinationUri(Uri.fromFile(saveFile));
//        down.setDestinationInExternalFilesDir(this, Environment.DIRECTORY_DOWNLOADS, "youjintang.apk");

        // 将下载请求放入队列
        mEnqueue = manager.enqueue(down);
        Util.putLongValue(this, "DownloadManagerId", mEnqueue);
        //注册下载广播

        registerReceiver(receiver, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        mPath = intent.getStringExtra("path");
//        mPath = "http://gdown.baidu.com/data/wisegame/fd84b7f6746f0b18/baiduyinyue_4802.apk";
//        判断文件是否已存在。
        File File = new File(Environment.getExternalStorageDirectory(), "youjintang.apk");
        if (File.exists()) {
            File.delete();
        }
        if (mPath != null && (!"".equals(mPath)) && mPath.endsWith(".apk")) {
            if (isNeedDownloadAgain()) {
                Toast.makeText(getApplicationContext(), "开始下载最新版App...", Toast.LENGTH_SHORT).show();
                // 调用下载
                initDownManager();
            }

        }

        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }


    @Override
    public void onDestroy() {

        // 注销下载广播
        if (receiver != null) unregisterReceiver(receiver);
        super.onDestroy();
    }

    // 接受下载完成后的intent
    class DownloadCompleteReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {

            //判断是否下载完成的广播
            if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {

                //获取下载的文件id
                long downId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//                mHelper.putLong("DownloadManagerId",downId);
                Log.d("kodulf", "id=" + downId);
                //自动安装apk
                Uri uriForDownloadedFile = manager.getUriForDownloadedFile(downId);
                Log.d("kodulf", "uri=" + uriForDownloadedFile);

                installApkNew(uriForDownloadedFile);
                //停止服务并关闭广播
                UpdateService.this.stopSelf();

            }
        }

        //安装apk
        protected void installApkNew(Uri uri) {
            Intent intent = new Intent();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                intent.setAction(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(uri, "application/vnd.android.package-archive");
            } else {
                intent.setAction(Intent.ACTION_DEFAULT);
                intent.addCategory(Intent.CATEGORY_DEFAULT);
                File apkFile = queryDownloadedApk();
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                intent.setDataAndType(Uri.fromFile(apkFile), "application/vnd.android.package-archive");
            }

            //执行动作

            // android.os.Process.killProcess(android.os.Process.myPid());
            try {
                startActivity(intent);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    //    转换文件格式,适配版本系统
    public File queryDownloadedApk() {
        File targetApkFile = null;
        if (mEnqueue != -1) {
            DownloadManager.Query query = new DownloadManager.Query();
            query.setFilterById(mEnqueue);
            query.setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
            Cursor cur = manager.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;
    }

    //    判断是否需要再次启动DownloadManager
    private boolean isNeedDownloadAgain() {
        boolean isNeedDownloadAgain = true;
        DownloadManager.Query query = new DownloadManager.Query();
        manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
        long id = Util.getLongValue(this, "DownloadManagerId", -1L);
        // Toast.makeText(getApplicationContext(), "id..."+id, Toast.LENGTH_SHORT).show();
        if (id != -1) {
            query.setFilterById(id);
            Cursor cursor = manager.query(query);
            if (cursor != null && cursor.moveToFirst()) {
                int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
                int status = cursor.getInt(columnIndex);
                int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
                int reason = cursor.getInt(columnReason);
                switch (status) {
                    case DownloadManager.STATUS_FAILED:
                        switch (reason) {
                            case DownloadManager.ERROR_CANNOT_RESUME:
                                //some possibly transient error occurred but we can't resume the download
                                break;
                            case DownloadManager.ERROR_DEVICE_NOT_FOUND:
                                //no external storage device was found. Typically, this is because the SD card is not mounted
                                break;
                            case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
                                //the requested destination file already exists (the download manager will not overwrite an existing file)
                                break;
                            case DownloadManager.ERROR_FILE_ERROR:
                                //a storage issue arises which doesn't fit under any other error code
                                break;
                            case DownloadManager.ERROR_HTTP_DATA_ERROR:
                                //an error receiving or processing data occurred at the HTTP level
                                break;
                            case DownloadManager.ERROR_INSUFFICIENT_SPACE://sd卡满了
                                //here was insufficient storage space. Typically, this is because the SD card is full
                                break;
                            case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
                                //there were too many redirects
                                break;
                            case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
                                //an HTTP code was received that download manager can't handle
                                break;
                            case DownloadManager.ERROR_UNKNOWN:
                                //he download has completed with an error that doesn't fit under any other error code
                                break;
                        }
                        isNeedDownloadAgain = true;
                        break;
                    case DownloadManager.STATUS_PAUSED:
                        switch (reason) {
                            case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
                                //the download exceeds a size limit for downloads over the mobile network and the download manager is waiting for a Wi-Fi connection to proceed

                                break;
                            case DownloadManager.PAUSED_UNKNOWN:
                                //the download is paused for some other reason
                                break;
                            case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
                                //the download is waiting for network connectivity to proceed
                                break;
                            case DownloadManager.PAUSED_WAITING_TO_RETRY:
                                //the download is paused because some network error occurred and the download manager is waiting before retrying the request
                                break;
                        }
                        isNeedDownloadAgain = false;
                        break;
                    case DownloadManager.STATUS_PENDING:
                        isNeedDownloadAgain = false;
                        //  Toast.makeText(getApplicationContext(), "STATUS_PENDING...", Toast.LENGTH_SHORT).show();
                        break;
                    case DownloadManager.STATUS_RUNNING:
                        Toast.makeText(getApplicationContext(), "正在下载...", Toast.LENGTH_SHORT).show();
                        isNeedDownloadAgain = false;
                        break;
                    case DownloadManager.STATUS_SUCCESSFUL:
                        //the download has successfully completed
                        isNeedDownloadAgain = true;
                        // isNeedDownloadAgain = false;
                        //  installApk(id, downloadManager, mContext);
                        break;

                }
            }

        }

        return isNeedDownloadAgain;
    }
}

遇到的问题和处理方法:

1.重复点击下载多次开启Downloadmanager问题:通过获取它的状态判断处理。

2.Downloadmanager本身解决了7.0的ur文件权限问题,所以不需fileprovider;但安装时候仍要判断系统版本,版本小于7.0转换 文件类型安装。

3.如果用户不安装下次下载文件名改变的问题:判断文件是否存在。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值