内容简介:一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:通常我们将apk文件存放在外部存储上.然后将 文件路径传递给系统, 进行apk的安装.安装代码如下:
概要
一般地, Android App 都会被要求在App内进行软件更新提示, 让用户下载apk文件, 然后更新安装新版本, 一般过程如下:
- 检测是否有新版本
- 下载新版本app apk文件
- 安装新的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》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- ShowDoc 更新:新增一键自动安装/升级脚本
- ShowDoc 更新:新增一键自动安装/升级脚本
- Solr安装、中文分词以及定时更新索引
- Flutter 实现 App 内更新安装包
- Windows 10 十月更新推出,安装时间缩短 31%
- 深度系统更新 —— Deepin 15.10.1 安装镜像发布
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。