Android App更新安装APK

栏目: IOS · Android · 发布时间: 5年前

内容简介:一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:通常我们将apk文件存放在外部存储上.然后将 文件路径传递给系统, 进行apk的安装.安装代码如下:

概要

一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:

  1. 检测是否有新版本
  2. 下载新版本app apk文件
  3. 安装新的apk

通常我们将apk文件存放在外部存储上.然后将 文件路径传递给系统, 进行apk的安装.

文件路径传递过程

安装代码如下:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newApk), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

通常情况下这样没问题, 但是在Android7.0 系统上会出现异常 FileUriExposedException , 这是因为在7.0 系统上发生的权限变更:

系统权限更改

为了提高私有文件的安全性,面向 Android 7.0 或更高版本的应用私有目录被限制访问(0700)。此设置可防止私有文件的元数据泄漏,如它们的大小或存在性。此权限更改有多重副作用:

私有文件的文件权限不应再由所有者放宽,为使用 MODE_WORLD_READABLE 和/或 MODE_WORLD_WRITEABLE 而进行的此类尝试将触发 SecurityException。

注:迄今为止,这种限制尚不能完全执行。应用仍可能使用原生 API 或 File API 来修改它们的私有目录权限。但是,我们强烈反对放宽私有目录的权限。

传递软件包网域外的 file:// URI 可能给接收器留下无法访问的路径。因此,尝试传递 file:// URI 会触发 FileUriExposedException。分享私有文件内容的推荐方法是使用 FileProvider。

DownloadManager 不再按文件名分享私人存储的文件。旧版应用在访问 COLUMN_LOCAL_FILENAME 时可能出现无法访问的路径。面向 Android 7.0 或更高版本的应用在尝试访问 COLUMN_LOCAL_FILENAME 时会触发 SecurityException。通过使用 DownloadManager.Request.setDestinationInExternalFilesDir() 或 DownloadManager.Request.setDestinationInExternalPublicDir() 将下载位置设置为公共位置的旧版应用仍可以访问 COLUMN_LOCAL_FILENAME 中的路径,但是我们强烈反对使用这种方法。对于由 DownloadManager 公开的文件,首选的访问方式是使用ContentResolver.openFileDescriptor()。

上述说明在7.0 系统上使用新的 API 来进行文件传递.

Android 7.0 的文件传递

官方推荐使用 FileProvider , 那我们看看如何使用

1. 在 Manifest 文件添加 provider, 如下:

<manifest>
    ...
    <application>
        ...
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        ...
    </application>
</manifest>

添加 provider

2. 设置文件路径

res/ 目录下创建 xml 文件夹, 然后穿件文件 provider_paths.xml , 其内容格式如下:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <paths>
        <files-path name="files" path="" />
        <cache-path name="cache" path="" />
        <external-path name="external" path="" />
        <external-files-path name="external_file_path" path="" />
        <external-cache-path name="external_cache_path" path="" />
        <external-media-path name="external_media_path" path="" />
    </paths>
</resources>

指定的路径有6中,其中:

<files-path name="name" path="path" />

代表你的app内部存储区域 files/ 目录下的文件, 等同于 Context.getFilesDir() .

<cache-path name="name" path="path" />

代表你的app内部存储区域 files/ 目录下的文件, 等同于 Context.getCacheDir() .

<external-path name="name" path="path" />

代表外部存储根目录下的文件路径, 等同于 Environment.getExternalStorageDirectory() .

<external-files-path name="name" path="path" />

代表你的app外部存储区域根木目录下的路径, 等同于 Context#getExternalFilesDir(String) Context.getExternalFilesDir(null)

<external-cache-path name="name" path="path" />

代表你的app外部存储区域缓存目录下的路径, 等同于 Context.getExternalCacheDir()

<external-media-path name="name" path="path" />

代表你的app外部存储区域媒体目录下的路径, 等同于 Context.getExternalMediaDirs()

根据自己的需要,设置路径.

3. 代码中使用FileProvider

Uri contentUri = FileProvider.getUriForFile(this, getPackageName() + ".fileprovider", newApk);

这样可以将 Uri 进行传递.

安装过程

一般我们直接将apk路径传递给系统进行安装, 如上面的代码:

Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(Uri.fromFile(newApk), "application/vnd.android.package-archive");
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);

但是在 Android8.0 又有权限变更, 需要单独的安装权限:

<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>

所以当在 8.0及以上的系统安装apk是还需添加此权限到 Manifest 文件, 并做判断.

private void checkInstallApkPermission(String filePath) {
    L.i(TAG, "checkInstallApkPermission:" + filePath);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        if (getPackageManager().canRequestPackageInstalls()) {
            L.i(TAG, "can request package");
            launchUpgrade(new File(filePath));
        } else {
            L.i(TAG, "can not request package");
            launchUpgrade(new File(filePath));
        }
    } else {
        launchUpgrade(new File(filePath));
    }
}

可能会有人疑惑, 这里为什么if else 都是直接 启动升级安装?

因为目前国内的定制系统会已经添加授权弹窗, 如果你采用网络所说的直接跳到 Setting界面, 让用户手动选择是比较麻烦的, 如果直接调用安装, 则系统会弹窗提示.

原创文章, 转载请说明出处~


以上所述就是小编给大家介绍的《Android App更新安装APK》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

精通正则表达式

精通正则表达式

Jeffrey E. F. Friedl / 余晟 / 电子工业出版社 / 2007 / 75

随着互联网的迅速发展,几乎所有工具软件和程序语言都支持的正则表达式也变得越来越强大和易于使用。本书是讲解正则表达式的经典之作。本书主要讲解了正则表达式的特性和流派、匹配原理、优化原则、实用诀窍以及调校措施,并详细介绍了正则表达式在Perl、Java、.NET、PHP中的用法。 本书自第1 版开始着力于教会读者“以正则表达式来思考”,来让读者真正“精通”正则表达式。该版对PHP的相关内容、Ja......一起来看看 《精通正则表达式》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具