更新外部存储路径获取方式

This commit is contained in:
lyswhut 2023-12-17 22:18:32 +08:00
parent 89a282ff56
commit 2fb4db83e6
8 changed files with 70 additions and 18 deletions

View File

@ -1,6 +1,11 @@
package cn.toside.music.mobile.utils; package cn.toside.music.mobile.utils;
import android.content.Context;
import android.os.storage.StorageManager;
import com.facebook.react.bridge.ReactApplicationContext;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
@ -8,6 +13,8 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.concurrent.Callable; import java.util.concurrent.Callable;
public class Utils { public class Utils {
@ -26,6 +33,31 @@ public class Utils {
return dir.delete(); return dir.delete();
} }
// https://gist.github.com/PauloLuan/4bcecc086095bce28e22?permalink_comment_id=2591001#gistcomment-2591001
public static String getExternalStoragePath(ReactApplicationContext mContext, boolean is_removable) {
StorageManager mStorageManager = (StorageManager) mContext.getSystemService(Context.STORAGE_SERVICE);
Class<?> storageVolumeClazz;
try {
storageVolumeClazz = Class.forName("android.os.storage.StorageVolume");
Method getVolumeList = mStorageManager.getClass().getMethod("getVolumeList");
Method getPath = storageVolumeClazz.getMethod("getPath");
Method isRemovable = storageVolumeClazz.getMethod("isRemovable");
Object result = getVolumeList.invoke(mStorageManager);
final int length = Array.getLength(result);
for (int i = 0; i < length; i++) {
Object storageVolumeElement = Array.get(result, i);
String path = (String) getPath.invoke(storageVolumeElement);
boolean removable = (Boolean) isRemovable.invoke(storageVolumeElement);
if (is_removable == removable) {
return path;
}
}
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String convertStreamToString(InputStream is) throws Exception { public static String convertStreamToString(InputStream is) throws Exception {
BufferedReader reader = new BufferedReader(new InputStreamReader(is)); BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();

View File

@ -395,5 +395,10 @@ public class UtilsModule extends ReactContextBaseJavaModule {
public void requestIgnoreBatteryOptimization(Promise promise) { public void requestIgnoreBatteryOptimization(Promise promise) {
promise.resolve(BatteryOptimizationUtil.requestIgnoreBatteryOptimization(reactContext.getApplicationContext(), reactContext.getPackageName())); promise.resolve(BatteryOptimizationUtil.requestIgnoreBatteryOptimization(reactContext.getApplicationContext(), reactContext.getPackageName()));
} }
@ReactMethod
public void getExternalStoragePath(Promise promise) {
promise.resolve(Utils.getExternalStoragePath(reactContext, true));
}
} }

View File

@ -14,7 +14,7 @@
- 优化播放详情页歌曲封面、控制按钮对各尺寸屏幕的适配,修改横屏下的控制栏按钮布局 - 优化播放详情页歌曲封面、控制按钮对各尺寸屏幕的适配,修改横屏下的控制栏按钮布局
- 优化横竖屏界面的暂时判断,现在趋于方屏的屏幕按竖屏的方式显示,横屏下的播放栏添加上一曲切歌按钮 - 优化横竖屏界面的暂时判断,现在趋于方屏的屏幕按竖屏的方式显示,横屏下的播放栏添加上一曲切歌按钮
- 添加对wy源某些歌曲有问题的歌词进行修复#370 - 添加对wy源某些歌曲有问题的歌词进行修复#370
- 文件选择器允许(在旧系统)选择外置存储设备上的路径`/storage` - 文件选择器允许(在旧系统)选择外置存储设备上的路径
- 图片显示改用第三方的图片组件支持gif类型的图片显示尝试解决某些设备上图片过多导致的应用崩溃问题 - 图片显示改用第三方的图片组件支持gif类型的图片显示尝试解决某些设备上图片过多导致的应用崩溃问题
- 歌曲评论内容过长时自动折叠,需手动展开 - 歌曲评论内容过长时自动折叠,需手动展开
- 改进本地音乐在线信息的匹配机制 - 改进本地音乐在线信息的匹配机制

View File

@ -44,7 +44,7 @@ export default forwardRef<MetadataEditType, MetadataEditProps>((props, ref) => {
readLyric(filePath), readLyric(filePath),
]).then(([_metadata, pic, lyric]) => { ]).then(([_metadata, pic, lyric]) => {
if (!_metadata) return if (!_metadata) return
if (isUnmounted) return if (isUnmounted.current) return
metadata.current = { metadata.current = {
name: _metadata.name, name: _metadata.name,
singer: _metadata.singer, singer: _metadata.singer,

View File

@ -126,6 +126,7 @@ export default forwardRef<ListType, ListProps>(({
// console.log('prevPath', prevPath) // console.log('prevPath', prevPath)
// if (isReadingDir.current) return // if (isReadingDir.current) return
// setPath(prevPath) // setPath(prevPath)
throw err
}).finally(() => { }).finally(() => {
isReadingDir.current = false isReadingDir.current = false
}) })
@ -134,7 +135,7 @@ export default forwardRef<ListType, ListProps>(({
const onSetPath = (pathInfo: PathItem) => { const onSetPath = (pathInfo: PathItem) => {
// console.log('onSetPath') // console.log('onSetPath')
if (pathInfo.isDir) { if (pathInfo.isDir) {
void readDir(pathInfo.path, readOptions.current.dirOnly, readOptions.current.filter) void readDir(pathInfo.path, readOptions.current.dirOnly, readOptions.current.filter).catch(_ => _)
} else { } else {
onConfirm(pathInfo.path) onConfirm(pathInfo.path)
// setPath(pathInfo.path) // setPath(pathInfo.path)
@ -143,7 +144,9 @@ export default forwardRef<ListType, ListProps>(({
const toParentDir = () => { const toParentDir = () => {
const parentPath = path.substring(0, path.lastIndexOf('/')) const parentPath = path.substring(0, path.lastIndexOf('/'))
void readDir(parentPath.length ? parentPath : externalStorageDirectoryPath, readOptions.current.dirOnly, readOptions.current.filter) void readDir(parentPath.length ? parentPath : externalStorageDirectoryPath, readOptions.current.dirOnly, readOptions.current.filter).catch(() => {
void readDir(externalStorageDirectoryPath, readOptions.current.dirOnly, readOptions.current.filter).catch(_ => _)
})
} }
const handleHide = () => { const handleHide = () => {

View File

@ -1,4 +1,4 @@
import { forwardRef, memo, useEffect, useImperativeHandle, useRef, useState } from 'react' import { forwardRef, memo, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react'
import { View, TouchableOpacity } from 'react-native' import { View, TouchableOpacity } from 'react-native'
import Input, { type InputType } from '@/components/common/Input' import Input, { type InputType } from '@/components/common/Input'
import Text from '@/components/common/Text' import Text from '@/components/common/Text'
@ -9,6 +9,8 @@ import { createStyle, toast } from '@/utils/tools'
import { mkdir, readDir } from '@/utils/fs' import { mkdir, readDir } from '@/utils/fs'
import { useTheme } from '@/store/theme/hook' import { useTheme } from '@/store/theme/hook'
import { scaleSizeH } from '@/utils/pixelRatio' import { scaleSizeH } from '@/utils/pixelRatio'
import { getExternalStoragePath } from '@/utils/nativeModules/utils'
import { useUnmounted } from '@/utils/hooks'
const filterFileName = /[\\/:*?#"<>|]/ const filterFileName = /[\\/:*?#"<>|]/
@ -45,8 +47,6 @@ const NameInput = forwardRef<NameInputType, {}>((props, ref) => {
) )
}) })
const storagePath = '/storage'
export default memo(({ export default memo(({
title, title,
path, path,
@ -59,26 +59,34 @@ export default memo(({
const theme = useTheme() const theme = useTheme()
const confirmAlertRef = useRef<ConfirmAlertType>(null) const confirmAlertRef = useRef<ConfirmAlertType>(null)
const nameInputRef = useRef<NameInputType>(null) const nameInputRef = useRef<NameInputType>(null)
const storagePathRef = useRef('')
const [isShowStorage, setIsShowStorage] = useState(false) const [isShowStorage, setIsShowStorage] = useState(false)
const isUnmounted = useUnmounted()
const checkExternalStoragePath = useCallback(() => {
void getExternalStoragePath().then((storagePath) => {
if (storagePath) {
void readDir(storagePath).then(() => {
if (isUnmounted.current) return
storagePathRef.current = storagePath
setIsShowStorage(true)
}).catch(() => {
setIsShowStorage(false)
})
} else setIsShowStorage(false)
})
}, [])
useEffect(() => { useEffect(() => {
let isUnmounted = false checkExternalStoragePath()
void readDir(storagePath).then(() => {
if (isUnmounted) return
setIsShowStorage(true)
}).catch(_ => _)
return () => {
isUnmounted = true
}
}, []) }, [])
const refresh = () => { const refresh = () => {
void onRefreshDir(path) void onRefreshDir(path)
checkExternalStoragePath()
} }
const toggleStorageDir = () => { const toggleStorageDir = () => {
void onRefreshDir(storagePath) void onRefreshDir(storagePathRef.current)
} }
const handleShow = () => { const handleShow = () => {

View File

@ -9,5 +9,5 @@ export function useUnmounted() {
} }
}, []) }, [])
return isUnmountedRef.current return isUnmountedRef
} }

View File

@ -70,6 +70,10 @@ export const onScreenStateChange = (handler: (state: 'ON' | 'OFF') => void): ()
} }
} }
export const getExternalStoragePath = async(): Promise<string | null> => {
return UtilsModule.getExternalStoragePath()
}
export const getWindowSize = async(): Promise<{ width: number, height: number }> => { export const getWindowSize = async(): Promise<{ width: number, height: number }> => {
return UtilsModule.getWindowSize() return UtilsModule.getWindowSize()
} }