Android 10(Q)
作用域存储
最近手机版本升到了 10,突然发现音频功能无效了。明明解决了动态申请权限,却还是报错 open failed: EACCES (Permission denied) 的问题。这是因为在安卓 Q(10) 开始,就采用存储的分区控制。导致明明已经申请了android.permission.WRITE_EXTERNAL_STORAGE 权限,却还是报错。解决办法:manifest 文件的 applicaiton 标签添加 android:requestLegacyExternalStorage="true"
标识。
分析原因:
Android Q 文件存储机制修改成了沙盒模式,有点模仿苹果的意思。APP 只能访问自己目录下的文件和公共媒体文件。对于 Android Q 以下,还是使用老的文件存储方式。Android Q 仍然使用 READ_EXTERNAL_STORAGE 和WRITE_EXTERNAL_STORAGE 作为存储相关运行时权限,但现在即使获取了这些权限,访问外部存储也受到了限制。
android:requestLegacyExternalStorage=”true” 的意思就是使用旧的存储策略,不使用 androidQ 的新策略。但这个不是长久之计,很快将会强制都使用新策略。最好的解决策略就是:
1、需要长期保存并且卸载也不能删除的,使用公有目录。
公有目录:Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones等
地址:/storage/emulated/0/Downloads(Pictures) 等(公有目录下的文件不会跟随APP卸载而删除)
2、不需要长期保存的,并且涉及安全问题的,使用私有目录。
APP私有目录
地址:/storage/emulated/0/Android/data/包名/files
深色主题
深色主题除了让眼部在夜间使用时更加舒适之外,还可以减少电量消耗,从而延长手机续航,是一项非常有用的功能。
在 Android 10.0 及以上系统的手机,都可以在 ”设置 -> 显示“ 内对深色主题进行开启和关闭。开启深色主题后,系统的界面风格包括一些内置的应用程序都会变成深色主题的色调。为了让我们的应用程序保持与系统的主题风格一致,接下来对深色主题进行适配。
Force Dark
最简单的一种实现方式是使用 Force Dark,它是一种能让应用程序快速适配深色主题,并且几乎不用编写额外代码的方式。它的工作原理是系统会分析浅色主题应用下的每一层 View,并且在这些 View 绘制到屏幕之前,自动将它们的颜色转换成更加适合深色主题的颜色。(注意,只有原本使用浅色主题的应用才能使用这种方式。)
启用 Force Dark 功能要借助 android:forceDarkAllowed 属性:这个属性是 API 29(Android 10)才开始有的,所以需要进行一些系统差异性编程(values-v29 目录是只有 Android 10.0 及以上的系统才会去读取的,因此这是一种系统差异性编程的实现方式)。
res 目录 -> 新建 values-v29 目录 -> 新建 Values resource file -> 新建文件 styles.xml
1 | // 内容都是从 res/values/styles.xml 中复制过来的。 |
但实际上,这种简单粗暴的转换方式实现的转换效果通常是不尽如人意的。一般推荐使用更加传统的手动实现方式。
手动实现
更好的方式,应该是针对每一个界面都进行浅色和深色两种主题的界面设计。
关于系统主题,除了常用的深色(Theme.AppCompat.NoActionBar)与浅色(Theme.AppCompat.Light.NoActionBar)主题外,现在有了另一种选择,使用 DayNight(Theme.AppCompat.DayNight.NoActionBar) 主题。
使用 DayNight 主题后,当用户在系统设置中开启深色主题时,应用程序会自动使用深色主题,反之则使用浅色主题。
1 | <resources> |
还有一些问题,比如当一些控件使用定义在 colors.xml 中的颜色值时,这种指定颜色值引用的方式相当于对控件的颜色进行了硬编码,DayNight 主题是不能对这些颜色进行动态转换的。这时需要进行一些主题差异型编程。
res 目录 -> 新建 values-night 目录 -> 新建 Values resource file -> 新建文件 colors.xml。
1 | // 在此文件中指定深色主题下的颜色值 |
虽说使用主题差异型的编程方式几乎可以解决所有的适配问题,但是在 DayNight 主题下,最好还是尽量减少通过硬编码的方式来指定控件的颜色,而是应该更多地使用能够根据当前主题自动切换颜色的主题属性。比如说黑色文字通常应该衬托在白色的背景下,反之白色文字通常应该衬托在黑色背景下。
1 | // 使用主题属性会自动根据系统当前的主题模式选择最合适的颜色值呈现给用户 |
并且,还可以在浅色主题和深色主题下分别执行不同的代码逻辑。
1 | /** |
备注
欢迎关注微信公众号:非也缘也
备注
参考资料: