Android问题7:在线检测更新包并下载更新遇到的问题

本文详细介绍了实现在线APP更新的全过程,包括配置文件解析、版本号对比、用户提示、APK下载与安装等关键步骤。特别针对高版本Android系统,阐述了如何解决权限申请、FileProvider设置等问题。

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

花了两天时间,百度n多文章,终于解决了在线更新的问题,现记录下来,以备后用。

注:以下内容虽然是自己写的,但是参考了大量的网上文章理解后的内容,参考的文章太多,也搞不清楚应该写转载谁的了,就厚颜标为原创,请见谅。

 

整个操作步骤如下:

1. 下载配置文件,解析配置文件内容,获取版本号、描述、apk包文件。

2. 判断版本号是否高于当前正在使用的app的版本号,否则放弃更新操作。

3. 显示提示框,提示用户有新的版本,需要更新吗?

4. 下载apk文件。

5. 完成后,自动运行apk,完成更新。

前面4步操作比较简单,在第5步的时候,卡了两天时间。

1. 下载文件需要写操作权限。

1.1 在app的AndroidManifest.xml文件里,添加申明读写安装权限。

<!-- 以下权限用于读写文件,执行apk包(用于升级安装) -->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />

1.2 还需要在代码中申请读写权限。

if (Build.VERSION.SDK_INT >= 23) {
        //android版本大于23(6.0)的,才需要此方法。

        boolean _b1 = false;
        if (_context.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            //没有读取文件权限
            _b1 = false;
        }

        if (_context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
            //没有写文件权限;
            _b1 = false;
        }
        if (_b1) {
            //已经请求了权限的,不再执行申请操作
            return;
        }

        String[] _ss = {
                Manifest.permission.READ_EXTERNAL_STORAGE,
                Manifest.permission.WRITE_EXTERNAL_STORAGE
        };

        //requestCode,自定义值,用于在Activity的onRequestPermissionsResult方法中识别当前操作是否成功,这里直接使用常量101代替。
        //如果不在Activity中重写onRequestPermissionsResult函数,此值就没啥意义。
        ActivityCompat.requestPermissions(_context, _ss, 101);
        
}

2. 执行apk文件需要申明权限

2.1 在AndroidManifest.xml添加申明:AndroidManifest.xml, 上面操作步骤1.1中已经完成。

2.2 API24以后,执行apk不能使用file://开始的uri,说是不安全,所以要在AndroidManifest.xml添加FileProvider的定义。

<provider
    android:name="androidx.core.content.FileProvider"
    android:authorities="com.trap.fileProvider"
    android:exported="false"
    android:grantUriPermissions="true">
    <meta-data
        android:name="android.support.FILE_PROVIDER_PATHS"
        android:resource="@xml/paths"/>
</provider>

注:

1) 在name项目中,旧版本使用的是:android.support.v4.content.FileProvider

2) 在authoritites一项中, com.trap 是app的包名称,后面的fileProvider也可以自定义,后面在引用的时候记得相同就好。

3) 在meta-data一项中,@xml=paths,指向的是res/xml/paths.xml文件,所以我们还需要在res下面创建一个xml文件夹,再添加一个paths.xml文件。

2.3 在res下,添加xml文件夹,并创建paths.xml文件,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <external-path path="." name="download" />
    </paths>
</resources>

2.4 在代码中,申请执行apk的权限。

 

if (Build.VERSION.SDK_INT >= 26) {
    boolean _b1 = _activity.getPackageManager().canRequestPackageInstalls();
    if (!_b1) {
        //requestCode,自定义值,用于在Activity的onRequestPermissionsResult方法中识别当前操作是否成功,这里用103代替,
        //如果不在Activity中重写onRequestPermissionsResult函数,此值就没啥意义。
        ActivityCompat.requestPermissions(_activity, new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, 103);
        //_activity.requestPermissions(new String[]{Manifest.permission.REQUEST_INSTALL_PACKAGES}, 103);
        }
}

2.5 权限已经申明(AndroidManifest.xml)了, 也向系统申请(代码)了,执行apk。

if (Build.VERSION.SDK_INT < 24) {
    //android 7.0及以下版本;
    Intent _intent = new Intent(Intent.ACTION_VIEW);
    _intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    _intent.setDataAndType(Uri.parse("file://" + _file), "application/vnd.android.package-archive");
    _activity.startActivity(_intent);
} else {
    //android 7.0及以上版本,需要apk安装权限;
    File _apkFile = new File(_file);
    if (_apkFile.isFile() && _apkFile.exists()) {
        // 这里必须和AndroidManifest.xml中定义的FileProvider中内容匹配。
        Uri _uri = FileProvider.getUriForFile(_activity, "com.trap.fileProvider", _apkFile);

        Intent _intent = new Intent(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");

        //requestCode:1这个值是自定义的,随便填;
        //如果不重写Activity的onActivityResult方法,此值没意义。
        _activity.startActivityForResult(_intent, 1);

    }
}

到此,在线更新基本完成。

之前想法是自动判断手机是否有SD卡,有则下载到SD卡下的download文件夹,无则下载到当前应用的cache/download文件夹下。因为使用file://描述的uri不支持解读,只能使用FileProvider.getUriForFile生成的uri,这样子的话,我就不知道在paths.xml中如何配置了,只好放弃。在getExternalStorageDirectory()下创建了download保存下载文件,这个download是否与paths.xml中的name一项有关系,没有深入研究,弄了两天,真累,就算误打误撞成功了吧。

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值