Android (注意点超详细)检测软件版本更新 安装apk +解决 尝试在空对象引用

本文详细介绍了在Android开发中如何检测软件版本更新并安装apk,特别强调了高版本手机的安装权限问题。在实现过程中,遇到了尝试在空对象引用的错误,通过在清单文件的《application》部分加入特定权限设置解决了问题,同时提醒开发者注意file_paths.xml可能存在的缺陷,建议使用服务进行下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一看啥都会 一敲啥都醉  真的是各种坑 

首先附上代码 下面在一一介绍:(现在博客更新的加入代码的背景颜色为白色 好chou啊 实名吐槽 哈哈哈)

 //显示 showDownloadProgressDialog
    private void showDownloadProgressDialog(Context context) {
        ProgressDialog progressDialog = new ProgressDialog(context);
        progressDialog.setTitle("提示");
        progressDialog.setMessage("正在下载...");
        progressDialog.setIndeterminate(false);
        progressDialog.setMax(100);
        progressDialog.setCancelable(false); //设置不可点击界面之外的区域让对话框小时
        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); //进度条类型
        progressDialog.show();
        new DownloadAPK(progressDialog).execute(urlApk);//urlApk为apk路径
    }
 @Override
        protected Object doInBackground(Object[] objects) {
            URL url;
            HttpURLConnection conn;
            BufferedInputStream bis = null;
            FileOutputStream fos = null;

            try {
                url = new URL((String) objects[0]);
                conn = (HttpURLConnection) url.openConnection();
                conn.setRequestMethod("GET");
                conn.setConnectTimeout(5000);

                int fileLength = conn.getContentLength();
                bis = new BufferedInputStream(conn.getInputStream());
                //这个为在本地创建文件的路径
                //创建的文件路径:路径+名字.apk
                String fileName = Environment.getExternalStorageDirectory().getPath() + "/sysf.apk";
                file = new File(fileName);
                if (!file.exists()) {
                    if (!file.getParentFile().exists()) {
                        file.getParentFile().mkdirs();
                    }
                    file.createNewFile();
                }
                fos = new FileOutputStream(file);
                byte data[] = new byte[4 * 1024];
                long total = 0;
                int count;
                while ((count = bis.read(data)) != -1) {
                    total += count;
                    publishProgress((int) (total * 100 / fileLength));
                    fos.write(data, 0, count);
                    fos.flush();
                }
                fos.flush();

            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fos != null) {
                        fos.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (bis != null) {
                        bis.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            return null;
        }

        @Override
        protected void onProgressUpdate(Object[] values) {
            super.onProgressUpdate(values);
            // 这里 改变ProgressDialog的进度值
            progressDialog.setProgress((int) values[0]);
        }


        @Override
        protected void onPostExecute(Object o) {
            super.onPostExecute(o);
            openFile(file); //打开安装apk文件操作
            progressDialog.dismiss(); //关闭对话框
        }


        private void openFile(File file) {
            if (file != null) {
                Intent intent = new Intent(Intent.ACTION_VIEW);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                //判读版本是否在7.0以上
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
                    Uri apkUri = FileProvider.getUriForFile(getContext(), getPackageName() + ".FileProvider", file);
                    intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
                    intent.setDataAndType(apkUri, "application/vnd.android.package-archive");
                } else {
                    intent.setDataAndType(Uri.fromFile(file), "application/vnd.android.package-archive");
                }
                startActivity(intent);
            }
        }
    }

注意点一:

注意点二:

这里要有个版本的判断 否则高版本的手机无法安装

注意点三:《清单文件》

除了读写的权限还应该加上安装的权限 这个就是高版本安装的权限设置

<!-- 读取数据 -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<!-- 写入数据 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!--安装 高版本安装apk权限申请-->
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

到这里 一切看着都完美无缺 谁能想到运行时会报一个这样的错误:

Attempt to invoke virtual method 'android.content.res.XmlResourceParser android.content.pm.ProviderInfo.loadXmlMetaData(android.content.pm.PackageManager, java.lang.String)' on a null object reference

解决:清单文件 《application》中加入:

<!--文件的路径 会把具体的路径给你换成你的包名-->
<provider
    android:name="android.support.v4.content.FileProvider"
    android:authorities="com.*.FileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/file_paths" />
</provider>

注意authorities :包名.fileprovider

否则安装失败

res--xml--file_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">

    <!--
    name属性的值可以随便写,别名
    path属性的值表示共享的具体位置,设置空就表示将整个SD卡进行共享
     -->
    <external-path
        name="external_files"
        path="." />
    <!-- /storage/emulated/0/Download/${applicationId}/.beta/apk-->
    <external-path
        name="beta_external_path"
        path="Download/" />
    <!--/storage/emulated/0/Android/data/${applicationId}/files/apk/-->
    <external-path
        name="beta_external_files_path"
        path="Android/data/" />
</paths>

有缺陷,建议使用服务进行下载

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值