当前位置:首页 » 安卓系统 » androidallowbackup

androidallowbackup

发布时间: 2023-02-03 02:14:43

① 如何解决Android7.0及以上的权限崩溃问题

话说自从google出来Android 7.0系统之后,我们公司的测试小伙伴就向我提出了7.0的bug,接下来就着手查阅了下问题是出在哪里的,该如何来解决呢。
bug日志是长这样子的:
android.os.FileUriExposedException: file:///storage/emulated/0/ys_toutiao.apk exposed beyond app through Intent.getData()
at android.os.StrictMode.onFileUriExposed(StrictMode.java:1816)
at android.net.Uri.checkFileUriExposed(Uri.java:2350)
at android.content.Intent.prepareToLeaveProcess(Intent.java:9076)
at android.content.Intent.prepareToLeaveProcess(Intent.java:9037)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1530)
at android.app.Activity.startActivityForResult(Activity.java:4391)
at android.support.v4.app.BaseFragmentActivityJB.startActivityForResult(BaseFragmentActivityJB.java)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java)
at android.app.Activity.startActivityForResult(Activity.java:4335)
at android.support.v4.app.FragmentActivity.startActivityForResult(FragmentActivity.java)
at android.app.Activity.startActivity(Activity.java:4697)
at android.app.Activity.startActivity(Activity.java:4665)
at com.ijuyin.prints.news.utils.VersionUtils$1.handleMessage(VersionUtils.java)
at android.os.Handler.dispatchMessage(Handler.java:105)
at android.os.Looper.loop(Looper.java:156)
at android.app.ActivityThread.main(ActivityThread.java:6524)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)

也就是说是在什么情况下会出现呢?
1、是在调用系统相机的时候;
2、是在写入文件的时候, 在我这里是强制升级后下载完成安装Apk时;
关于FileUriExposedException 异常的描述是这样子的:
针对于权限部分,Android7.0是google推出的对权限做了一个更新即不允许出现以file://的形式调用隐式APP系统,也就是说以前呢,Uri的获取方式是以file://xxx的样式来,那么我们也就是通过Uri.fromFile()来获取如今放在7.0及以上系统呢,这样子就不行啦;
如今的解决关键在哪里呢,需要在应用间共享文件,也就是需要发送一项content://URI,并授予 URI 临时访问权限。进行此授权的最简单方式是使用FileProvider类。
嗯的,FileProvider
1、首先我们需要在AndroidManifest中的application下添加provider:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="com.ijuyin.prints.news">

<application
android:name="com.ijuyin.prints.news.base.BaseApplication"
android:allowBackup="true"
android:hardwareAccelerated="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/text_app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme"
tools:replace="android:label"
android:fullBackupContent="false">

<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.ijuyin.prints.news.provider"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths"/>
</provider>

</application>

</manifest>

在这里我们需要注意一下其中设置的各种属性的含义:
authorities:是该项目的包名+provider
grantUriPermissions:必须是true,表示授予 URI 临时访问权限
exported:必须是false
resource:中的@xml/file_paths是我们接下来要在资源文件目录下添加的文件
2、在res目录下新建一个xml文件夹,并且新建一个file_paths的xml文件
设置file_path路径.png
3、打开file_paths.xml文件添加如下内容
<?xml version="1.0" encoding="utf-8"?>
<resources>
<paths>
<external-path
name="camera_photos"
path="."/>
<external-path
name="files_root"
path="Android/data/com.ijuyin.prints.news/"/>
<external-path
name="external_storage_root"
path="."/>
</paths>
</resources>

需要注意的是:
path:需要临时授权访问的路径(.代表在相机调用时候访问的是所有路径,而文件写入时访问的路径是Android/data/com.ijuyin.prints.news/)
name: 是你为设置的这个访问路径起的名字
4、接下来便是修改适配Android 7.0及以上系统的代码
第一部分是对于相机模块的修改
/**
* Open camera
*/
private void showCameraAction() {
if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission
.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE,
getString(R.string.mis_permission_rationale_write_storage),
REQUEST_STORAGE_WRITE_ACCESS_PERMISSION);
} else {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
if (intent.resolveActivity(getActivity().getPackageManager()) != null) {
try {
mTmpFile = FileUtils.createTmpFile(getActivity());
} catch (IOException e) {
e.printStackTrace();
}
Uri imageUri;
if (mTmpFile != null && mTmpFile.exists()) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
String authority = getActivity().getPackageName() + ".provider";
imageUri = FileProvider.getUriForFile(getActivity(), authority, mTmpFile);
} else {
imageUri = Uri.fromFile(mTmpFile);
}
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
startActivityForResult(intent, REQUEST_CAMERA);
} else {
Toast.makeText(getActivity(), R.string.mis_error_image_not_exist, Toast
.LENGTH_SHORT).show();
}
} else {
Toast.makeText(getActivity(), R.string.mis_msg_no_camera, Toast.LENGTH_SHORT)
.show();
}
}
}

第二部分是对文件写入模块的代码修改
private static Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
if (msg.what == DOWN_UPDATE) {
mProgress.setProgress(progress);
} else if (msg.what == DOWN_OVER) {
if (null != downloadDialog && downloadDialog.isShowing()) {
try {
downloadDialog.dismiss();
} catch (Exception e) {
e.printStackTrace();
}
}
File apkfile = new File(apkPath);
if (!apkfile.exists()) {
return;
}
Intent intent = new Intent(Intent.ACTION_VIEW);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
String authority = mContext.getPackageName() + ".provider";
Uri contentUri = FileProvider.getUriForFile(mContext, authority, apkfile);
intent.setDataAndType(contentUri, "application/vnd.android.package-archive");
} else {
intent.setDataAndType(Uri.fromFile(apkfile), "application/vnd.android" +
".package-archive");
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
}
mContext.startActivity(intent);
}
}
};

其中最核心的部分是

配置provider.png

需要注意的地方是:
首先我们对Android系统的型号做出判断
添加flags,表明我们要被授予什么样的临时权限
以前我们直接 Uri.fromFile(apkFile)构建出一个Uri,现在我们使用FileProvider.getUriForFile(getActivity(), getActivity().getPackageName() + ".provider", mTmpFile);
其中getActivity().getPackageName()指的是该项目的应用包名(此处调用的是在fragment,所以使用的是getActivity())
通过以上4步的设置操作,就可以完全解决android 7.0及以上权限问题导致的崩溃问题。

② Android 12 已来,你的 App 崩溃了吗

Android 12 已来,你的 App 崩溃了吗?我们已经开始做 Android 12 的适配了,在 Android 12 中包含了很多的功能和一些行为的变更,接下来我们一起来分析这些行为的变更对我们的应用产生了那些影响。

通过这篇文章你将学习到以下内容:

如果对上面的异常产生的条件,不是很理解,可以点击下方链接查看,目前已经有很多开源项目都已经开始适配这个行为的变更了,例如 leakcanary 等等,详情前往查看下列地址:

这个行为的变更无论是对库开发者 和 还是应用开发者影响都非常大。

android:exported 属性的默认值取决于是否包含 ,如果包含 那么默认值为 true,否则 false。

正因为 android:exported 的属性的默认值的问题,Twicca App 发生过一次安全性问题,因为另一个没有访问 SD 卡或网络权限的 App,可以通过 Twicca App 将存储在 SD 卡上的图片或电影上传到 Twicca 用户的 Twitter 账户上的社交网络上。

产生问题的代码如下所示:

因为添加了 intent-filter 所以 android:exported 的属性的默认值为 true,因此可以接受来自其他 App 的访问,进而造成了上述问题(通过 Twicca App 将存储在 SD 卡上的图片或电影上传到 Twicca 用户的 Twitter 账户上的社交网络上),而解决方案有两个:

这种方案也是可行的,因为在一台设备上,不可能会出现两个包名相同的应用,更多详细的信息可以前往查看 Restrict access to sensitive activities。
https://wiki.sei.cmu.e/confluence/display/android/DRD09.+Restrict+access+to+sensitive+activities

这仅仅是关于 activity 的安全漏洞的其中一个,在不同的场景下利用这些漏洞做的事情也可能不一样。当然还有 service 和 receiver 组件也都是一样,存在安全性问题。

为什么在 Android 12 上需要显示的指定 PendingIntent 的可变性

在 Adnroid 12 之前,默认创建一个 PendingIntent 它是可变的,因此其他恶意应用程序可能会拦截,重定向或修改此 Intent。(但是是有条件限制的)

一个 PendingIntent 是一个可以给另一个应用程序使用的 Intent,PendingIntent 接收待处理意图的应用程序可以使用与产生待处理意图的应用程序相同的权限和身份执行待处理意图中指定的操作。

因此,创建待处理意图时必须小心,为了安全性 Google 在 Android 12 中需要开发者自己来指定 PendingIntent 的可变性。

更多关于 PendingIntent 安全性介绍,可以前往查看 Always pass explicit intents to a PendingIntent。
https://wiki.sei.cmu.e/confluence/display/android/DRD21-J.+Always+pass+explicit+intents+to+a+PendingIntent

Android 开发者都应该知道这个命令 adb backup , 它可以备份应用的数据,在 Android 12 中,为了保护私有应用数据,用户运行 adb backup 命令时,从设备导出的任何其他系统数据都不包含应用数据。

如果你在测试和开发过程中需要使用 adb backup 来备份应用数据,你可以在 AndroidManifest 中将 android:debuggable 设置为 true 来导出应用数据。

注意:在发布应用前将 android:debuggable 设置为 false。

为什么在 Android 12 上限制了 adb backup 命令的默认行为

因为这个存在严重的安全问题,当初 Google 为了提供 App 数据备份和恢复功能,可以在 AndroidManifest 中添加 android:allowBackup 属性,默认值为 true, 当你创建一个应用的时候,会默认添加这个属性,如下所示。

当 android:allowBackup="true" 时,用户可以通过 adb backup 和 adb restore 命令对应用数据进行备份和恢复,也就是说可以在其他的 Android 手机上安装同一个应用,通过如上命令恢复用户的数据。

为了安全起见,我们在发布出去的 Apk 中一定要将 android:allowBackup 属性设置为 false 来关闭应用程序的备份和恢复功能,以免造成信息泄露。国民级应用 XX 信, 在曾今发出的版本中 allowBackup 的属性值是 true,被其他逆向开发者利用之后,现在的版本中这个值已经修改为 false了,有兴趣的小伙们可以反编译看看。

在这里推荐一个开源项目 linkedin/qark 这是由 LinkedIn 开源的项目,这个工具被设计用来寻找与安全相关的 Android 应用程序漏洞,无论是源代码还是打包的 APK,具体的用法文档上写的非常的清楚了,这里不做详细的介绍了。
https://github.com/linkedin/qark

这个开源项目的检查结果,作为参考即可。当然也有很多公司花了重金去购买第三方的服务来检查 App 的安全漏洞。

在 Android 12 上这几个行为的变更它们都有一个共性:安全性,可见 Google 这几年在安全上做了很多的努力,当然还有其他的一些行为的变更,可以前往查看 行为变更:以 Android 12 为目标平台的应用。
https://developer.android.com/about/versions/12/behavior-changes-12

在这里还分享一份由大佬亲自收录整理的 学习PDF+架构视频+面试文档+源码笔记 高级架构技术进阶脑图、Android开发面试专题资料,高级进阶架构资料

这些都是我现在闲暇时还会反复翻阅的精品资料。里面对近几年的大厂面试高频知识点都有详细的讲解。相信可以有效地帮助大家掌握知识、理解原理,帮助大家在未来取得一份不错的答卷。

当然,你也可以拿去查漏补缺,提升自身的竞争力。

真心希望可以帮助到大家,Android路漫漫,共勉!

如果你有需要的话,只需 私信我【进阶】即可获取

热点内容
真我手机如何解除手机密码 发布:2024-05-04 18:24:44 浏览:707
数据库嵌套 发布:2024-05-04 18:24:29 浏览:144
豌豆荚源码 发布:2024-05-04 18:10:54 浏览:115
苹果消息的声音安卓怎么弄 发布:2024-05-04 18:06:23 浏览:553
减配配置有哪些 发布:2024-05-04 18:04:58 浏览:961
查询密码单是什么 发布:2024-05-04 17:54:03 浏览:40
安卓系统不支持网络怎么办 发布:2024-05-04 17:49:31 浏览:128
oraclesqlserver 发布:2024-05-04 17:49:16 浏览:47
关爱脚本 发布:2024-05-04 17:43:47 浏览:422
linuxshellif 发布:2024-05-04 17:09:47 浏览:17