天天看點

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

舉報/回報