天天看点

android文件存储适配,AndroidQ适配(暗黑模式和文件存储)

android文件存储适配,AndroidQ适配(暗黑模式和文件存储)

AndroidQ版本发布已经快一年了 虽然市场使用的占有率还不是太高 但是新手机 5G手机基本搭载的都是AndroidQ 所以AndroidQ的适配已经近在眼前了

AndroidQ两大主要变动:

1.暗黑模式适配

2.私有目录与公共目录文件的交互

首先我们来谈谈暗黑模式

在 Android Q 里,Dark theme 暗黑模式得到了系统级的支持。 暗黑模式不仅酷炫,而且有降低屏幕耗电、在光线较暗的环境中使用更舒适等好处。

Force Dark

其实我们的需求很明确,就是使用了硬编码也能被适配成暗黑模式。Android 10 新增的 Force Dark 强制暗黑就实现了这个功能。

android文件存储适配,AndroidQ适配(暗黑模式和文件存储)

增加了一个 forceDarkAllowed 的配置,这是 compileSdkVersion 升级到 29 新增的配置,按字面意思就是「开启强制暗黑」。 这样就已经完成配置了,在 Android 10 的机器上运行一下,切换暗黑模式,背景被强制转换成黑色了,连我们写死的色值都改了,虽然方便,但这也给我们一种不安全感。 要是 Force Dark 适配出来的颜色不是我们想要的怎么办?我们还能自定义暗黑色值吗?也是可以的。

Force Dark 自定义适配

除了主题新增了 forceDarkAllowed 这个配置,View 里面也有。 如果某个 View 的需要使用自定义色值适配暗黑模式,我们需要对这个 View 添加这个配置,让 Force Dark 排除它:

android:forceDarkAllowed="false"然后在代码里根据当前是否处于暗黑模式,对色值进行动态设置。 对于 View 的 forceDarkAllowed,有几点需要注意:

在 View 中使用这个配置的前提是,当前主题开启了 Force Dark

默认值是 true,所以设为 true 和不设是一样的

作用范围是当前 View 以及它所有的子 View

综上可以看出,其实目前并没有很好的 Force Dark 自定义方案。好在 Force Dark 的整体效果没什么大问题,就算要自定义,我们也尽量只对子 View 进行自定义。

接下来我们谈谈AndroidQ文件存储问题

临时性解决方案

...

永久性解决方案(研究中...如果有问题望提出,大家一起进步)

首先AndroidQ上不允许对公共目录直接访问和操作

AndroidQ之前我们可以使用

File file =new File(Environment.getExternalStorageDirectory() + File.separator + "文件名");

存储和操作文件

AndroidQ之后我们对于一些只需要保存 然后app内存使用的资源保存方式采用私有目录保存

File file =new File(context.getExternalFilesDir(null), "文件名");

getExternalFilesDir参数是表示文件会保存在app内部的什么类型文件夹下

默认传null为files

但是对于一些我们需要外部使用的文件资源上述存储就不能实现了

例如下载的视频和图片 拍照裁剪后保存的图片等等

以下示例为保存视频到相册

首先使用AndroidQ存储私有文件的方法存储文件

然后copy一份到相册

ContentValues contentValues =new ContentValues();

contentValues.put(MediaStore.Video.Media.DISPLAY_NAME, "文件名");

contentValues.put(MediaStore.Video.Media.MIME_TYPE, "文件类型例如video/mp4");

contentValues.put(MediaStore.Video.Media.RELATIVE_PATH, "文件存放路径例如Movies/my_video");

Uri uri = ContextUtil.getContext().getContentResolver().insert(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, contentValues);

PBitmapUtils.copyFile(ContextUtil.getContext(), "私有文件的路径", uri);

//contentValues除了上述关键信息外 还有很多其他信息 如有需要请自行度娘

//如果要保存图片MediaStore.Video.Media中的Video替换为Images

//文件类型改为image/png等等 类型很多自行动态获取修改不要写死

//文件路径改为Pictures/my_image 类型很多自定动态传入

public static boolean copyFile(Context context, String sourceFilePath, final Uri insertUri) {

if (insertUri ==null) {

return false;

}

ContentResolver resolver = context.getContentResolver();

InputStream is =null;//输入流

OutputStream os =null;//输出流

try {

os = resolver.openOutputStream(insertUri);

if (os ==null) {

return false;

}

File sourceFile =new File(sourceFilePath);

if (sourceFile.exists()) {// 文件存在时

is =new FileInputStream(sourceFile); // 读入原文件

//输入流读取文件,输出流写入指定目录

return copyFileWithStream(os, is);

}

return false;

}catch (Exception e) {

e.printStackTrace();

return false;

}finally {

try {

if (is !=null) {

is.close();

}

if (os !=null) {

os.close();

}

}catch (IOException e) {

e.printStackTrace();

}

}

}

private static boolean copyFileWithStream(OutputStream os, InputStream is) {

if (os ==null || is ==null) {

return false;

}

int read =0;

while (true) {

try {

byte[] buffer =new byte[1444];

while ((read = is.read(buffer)) != -1) {

os.write(buffer, 0, read);

os.flush();

}

return true;

}catch (IOException e) {

e.printStackTrace();

return false;

}finally {

try {

os.close();

is.close();

}catch (IOException e) {

e.printStackTrace();

}

}

}

}

有人可能问不判断版本直接用androidQ的写法可不可以

也可以也不可以 contentValues中还是需要做判断的

AndroidQ以下使用MediaStore.Video.Media.Data

AndroidQ 使用MediaStore.Video.Media.RELATIVE_PATH

举报/反馈