AndroidQ版本釋出已經快一年了 雖然市場使用的占有率還不是太高 但是新手機 5G手機基本搭載的都是AndroidQ 是以AndroidQ的适配已經近在眼前了
AndroidQ兩大主要變動:
1.暗黑模式适配
2.私有目錄與公共目錄檔案的互動
首先我們來談談暗黑模式
在 Android Q 裡,Dark theme 暗黑模式得到了系統級的支援。 暗黑模式不僅酷炫,而且有降低螢幕耗電、在光線較暗的環境中使用更舒适等好處。
Force Dark
其實我們的需求很明确,就是使用了寫死也能被适配成暗黑模式。Android 10 新增的 Force Dark 強制暗黑就實作了這個功能。
增加了一個 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
舉報/回報