Android 下载apk提示更新以及解决Android 6.0 Marshmallow提示更新报错问题

简介: 下载并安装apk的方法很多,但是谷歌还是建议我们采用DownloadManager。下载更新的代码比较简单,分如下几块:启动下载public long startDownload(String uri, St...

下载并安装apk的方法很多,但是谷歌还是建议我们采用DownloadManager。

下载更新的代码比较简单,分如下几块:

启动下载

public long startDownload(String uri, String title, String description) {
        DownloadManager.Request req = new DownloadManager.Request(Uri.parse(uri));

        req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
        //req.setAllowedOverRoaming(false);

        req.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);

        //设置文件的保存的位置[三种方式]
        //第一种
        //file:///storage/emulated/0/Android/data/your-package/files/Download/update.apk
        req.setDestinationInExternalFilesDir(context, Environment.DIRECTORY_DOWNLOADS, "update.apk");
        //第二种
        //file:///storage/emulated/0/Download/update.apk
        //req.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "update.apk");
        //第三种 自定义文件路径
        //req.setDestinationUri()


        // 设置一些基本显示信息
        req.setTitle(title);
        req.setDescription(description);
        //req.setMimeType("application/vnd.android.package-archive");

        return dm.enqueue(req);
    }

然后是监听下载完成的Receive

public class ApkInstallReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
            long downloadApkId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
            long id = PrefUtils.getDownloadId();
            if (downloadApkId == id) {
                installApk(context, downloadApkId);
            }
        }
    }

 private  void installApk(Context context, long downloadApkId) {
            Intent install = new Intent(Intent.ACTION_VIEW);
            DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
            Uri downloadFileUri = dManager.getUriForDownloadedFile(downloadApkId);
            if (downloadFileUri != null) {
                Log.d("DownloadManager", downloadFileUri.toString());
                install.setDataAndType(downloadFileUri, "application/vnd.android.package-archive");
                install.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                context.startActivity(install);
            } else {
                Log.e("DownloadManager", "下载失败");
            }

    }

上面的做法在Android 6.0 Marshmallow 系统之前是没有问题的,但是在6.0之后,会报错,倒是应用直接挂掉;报错LOG如下:

Caused by: android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.VIEW dat=content: typ=application/vnd.android.package-archive flg=0x10000000 }

经过查看Uri的值,发现6.0与之前的不一样

6.0的downloadFileUri 值为: content://downloads/my_downloads/10 
6.0之前的downloadFileUri 值为:file:///storage/emulated/0/Android/data/com.chiclam.download/files/Download/update-2.apk


完整的解决写法:

private  void installApk(Context context, long downloadApkId) {

        DownloadManager dManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
        DownloadManager.Query query = new DownloadManager.Query();
        query.setFilterById(downloadApkId);
        Cursor c = dManager.query(query);
        if(c != null) {
            if (c.moveToFirst()) {
                int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
                if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
                    String downloadFileUrl = c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI));
                    startInstall(context, Uri.parse(downloadFileUrl));
                }
            }
            c.close();
        }
    }

private boolean startInstall(Context context, Uri uri) {
        if(!new File( uri.getPath()).exists()) {
            System.out.println( " local file has been deleted! ");
            return false;
        }
        Intent intent = new Intent();
        intent.addFlags( Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.setAction( Intent.ACTION_VIEW);
        intent.setDataAndType( uri, "application/vnd.android.package-archive");
        context.startActivity( intent);
        return true;
    }

这样便完美解决了6.0上自动启动更新界面BUG

目录
相关文章
|
2月前
|
Android开发 开发者
Android Split APK介绍
【2月更文挑战第5天】
|
3月前
|
数据安全/隐私保护 Android开发
2023安卓逆向 -- 某合伙apk登录加密分析
2023安卓逆向 -- 某合伙apk登录加密分析
26 0
|
4月前
|
XML Java Android开发
Android App开发网络通信中使用okhttp下载和上传图片、文件讲解及实战(超详细实现用户注册信息上传 附源码)
Android App开发网络通信中使用okhttp下载和上传图片、文件讲解及实战(超详细实现用户注册信息上传 附源码)
142 0
|
3天前
|
Android开发
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
Android JNI 报错(signal 6 (SIGABRT), code -1 (SI_QUEUE), fault addr )
20 1
|
2天前
|
安全 编译器 API
Android HAL深入探索(5): 调试HAL报错与解决方案
Android HAL深入探索(5): 调试HAL报错与解决方案
6 1
|
16天前
|
Android开发 开发者
安卓投屏神器 Scrcpy安 报错ERROR: Could not find any ADB device
使用Scrcpy安卓投屏工具时遇到报错,问题根源是未开启开发者模式。解决步骤:进入设置,点击【关于手机】→连续点击版本号激活开发者模式,然后在【系统设置】→【开发者选项】中开启USB调试。参照此方法后可正常执行。Scrcpy软件下载链接和GitHub页面也已提供。
26 1
|
1月前
|
Shell 开发工具 Android开发
ADB 下载、安装及使用教程:让你更好地管理 Android 设备
ADB 下载、安装及使用教程:让你更好地管理 Android 设备
508 2
|
1月前
|
Android开发 对象存储
OSS对象储存android开发进行下载到本地文件时异步操作失效
android vivo80使用官方示例代码进行文件下载,但是使用oss.asyncGetObject(get, new OSSCompletedCallback<GetObjectRequest, GetObjectResult>()时onSuccess和onFailure不执行
|
2月前
|
算法 数据库 Android开发
安卓逆向 -- APK文件结构
安卓逆向 -- APK文件结构
22 0
|
2月前
|
算法 Java Android开发
安卓逆向 -- 调用其他APK的SO文件
安卓逆向 -- 调用其他APK的SO文件
17 0