diff --git a/README.md b/README.md index 95cb842..6ea58d7 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ > [Android Q & Android 11存储适配(二) FileOperator文件管理框架](https://juejin.im/post/6854573214451335175) ## 最新版说明 -☀ 2023年8月29日 09:48:39 ```kotlin 🌴最新版增加了一些常用功能, 获取媒体文件的创建时间,修改时间等/重命名文件, @@ -41,9 +40,9 @@ repositories { maven { url "https://s01.oss.sonatype.org/content/groups/public" } } -implementation 'com.github.javakam:file.core:3.9.0@aar' //核心库必选(Core library required) -implementation 'com.github.javakam:file.selector:3.9.0@aar' //文件选择器(File selector) -implementation 'com.github.javakam:file.compressor:3.9.0@aar'//图片压缩,修改自Luban(Image compression, based on Luban) +implementation 'com.github.javakam:file.core:3.9.8@aar' //核心库必选(Core library required) +implementation 'com.github.javakam:file.selector:3.9.8@aar' //文件选择器(File selector) +implementation 'com.github.javakam:file.compressor:3.9.8@aar'//图片压缩,修改自Luban(Image compression, based on Luban) ``` #### 2. `Application`中初始化(Initialization in Application) @@ -319,8 +318,7 @@ fun getPathByUri(uri: Uri?): String? { Method | Remark :-|:- `getMediaShotTime(uri: Uri?, block: (Long))` | 获取媒体文件拍摄时间 -`formatMediaMetadataKeyDate(date: String?): Date?` | 转换`MediaMetadataRetriever.METADATA_KEY_DATE` -特殊的时间格式 +`formatMediaMetadataKeyDate(date: String?): Date?` | 转换`MediaMetadataRetriever.METADATA_KEY_DATE`的特殊时间格式 `dumpMediaInfoByMediaMetadataRetriever(uri)` | 打印`音频或视频`的详细信息 `(Use MediaMetadataRetriever)` `dumpMediaInfoByExifInterface(uri)` | 打印`图片`的详细信息 `(Use ExifInterface)` `checkImage(uri)` | 检查`Uri`对应的文件是否为`图片` @@ -344,15 +342,11 @@ Method | Remark `isLocal` | 检验是否为本地URI `isGif()` | 检验是否为 gif -> `copyFile`效率和`kotlin-stdlib-1.4.21.jar`中的`kotlin.io.FilesKt__UtilsKt.copyTo`基本相当 : +> `copyFile`用法(copyFile usage) : ```kotlin fun File.copyTo(target: File, overwrite: Boolean = false, bufferSize: Int = DEFAULT_BUFFER_SIZE): File -``` - -Usage: -```kotlin boolean copyResult = FileUtils . copyFile (fileOld, getExternalFilesDir(null).getPath(), "test.txt"); File targetFile = new File(getExternalFilesDir(null).getPath() + "/" + "test.txt"); ``` @@ -370,13 +364,10 @@ val optionsImage = FileSelectOptions().apply { singleFileMaxSize = 5242880 singleFileMaxSizeTip = "图片最大不超过5M !" //The largest picture does not exceed 5M allFilesMaxSize = 10485760 - allFilesMaxSizeTip = - "总图片大小不超过10M !"//The total picture size does not exceed 10M 注:单选条件下无效,只做单个图片大小判断 + allFilesMaxSizeTip = "总图片大小不超过10M !"//The total picture size does not exceed 10M 注:单选条件下无效,只做单个图片大小判断 fileCondition = object : FileSelectCondition { override fun accept(fileType: IFileType, uri: Uri?): Boolean { - return (fileType == FileType.IMAGE && uri != null && !uri.path.isNullOrBlank() && !FileUtils.isGif( - uri - )) + return (fileType == FileType.IMAGE && uri != null && !uri.path.isNullOrBlank() && !FileUtils.isGif(uri)) } } } @@ -387,14 +378,8 @@ mFileSelector = FileSelector .setMinCount(1, "至少选择一个文件 !") //Choose at least one file .setMaxCount(10, "最多选择十个文件 !") //Choose up to ten files 注:单选条件下无效, 只做最少数量判断 .setOverLimitStrategy(OVER_LIMIT_EXCEPT_OVERFLOW) - .setSingleFileMaxSize( - 1048576, - "大小不能超过1M !" - ) //The size cannot exceed 1M 注:单选条件下无效, FileSelectOptions.singleFileMaxSize - .setAllFilesMaxSize( - 10485760, - "总大小不能超过10M !" - ) //The total size cannot exceed 10M 注:单选条件下无效,只做单个图片大小判断 setSingleFileMaxSize + .setSingleFileMaxSize(1048576,"大小不能超过1M !") //The size cannot exceed 1M 注:单选条件下无效, FileSelectOptions.singleFileMaxSize + .setAllFilesMaxSize(10485760,"总大小不能超过10M !") //The total size cannot exceed 10M 注:单选条件下无效,只做单个图片大小判断 setSingleFileMaxSize .setExtraMimeTypes("image/*") //默认不做文件类型约束为"*/*",不同类型系统提供的选择UI不一样 eg:"video/*","audio/*","image/*" .applyOptions(optionsImage) .filter(object : FileSelectCondition { @@ -437,32 +422,27 @@ mFileSelector = FileSelector.with(this) Multiple files (multi-select multiple types) -> 🌴适用于处理复杂文件选择情形, 如: 选取图片、音频文件、文本文件, 其中`图片`至少选择一张, 最多选择两张, 每张图片大小不超过5M, 全部图片大小不超过10M; +> 🌴适用于处理复杂文件选择情形, 如: 当需要同时选取图片、音频文件、文本文件, 其中`图片`至少选择一张, 最多选择两张, 每张图片大小不超过5M, 全部图片大小不超过10M; `音频文件`至少选择两个, 最多选择三个, 每个音频大小不超过20M, 全部音频大小不超过30M; `文本文件`至少选择一个, 最多选择两个, 每个文本文件大小不超过5M, 全部文本文件大小不超过10M -> 🌴It is suitable for processing complex file selection situations, such as: select pictures, audio -> files, text files, among which, select at least one picture and two at most. The size of each -> picture does not exceed 5M, and the size of all pictures does not exceed 10M; `audio File `Choose -> at -> least two and a maximum of three, each audio size does not exceed 20M, all audio size does not +> 🌴It is suitable for processing complex file selection situations, such as: When you need to select pictures, audio files, text files at the same time, among which, select at least one picture and two at most. The size of each picture does not exceed 5M, and the size of all pictures does not exceed 10M; `audio File `Choose +> at least two and a maximum of three, each audio size does not exceed 20M, all audio size does not > exceed 30M; `text file` select at least one, select at most two, each text file size does not -> exceed -> 5M, all The text file size does not exceed 10M +> exceed 5M, all The text file size does not exceed 10M -##### ✨注意 +##### ✨使用注意 [FileSelectCustomFileTypeActivity.kt](https://github.com/javakam/FileOperator/blob/master/app/src/main/java/com/ando/file/sample/ui/selector/FileSelectCustomFileTypeActivity.kt) ```kotlin -FileSelector 多选文件: -通过 applyOptions(optionsImage, optionsAudio, optionsTxt, optionsJsonFile) 指定四种类型可以选择, +使用FileSelector多选文件时推荐使用 OVER_LIMIT_EXCEPT_OVERFLOW 策略: +通过 applyOptions(optionsImage, optionsAudio, optionsTxt, optionsJsonFile) 方法指定四种类型可以选择, 其中的每一种类型包含多种 MimeType,例如: TXT(mutableListOf("txt", "conf", "iml", "ini", "log", "prop", "rc", "csv", "html", "htm", "htmls", "md")) -当在选择文件时候,分单选和多选两种情况: -1 单选:选择指定类型的任意文件都可以。即OVER_LIMIT_EXCEPT_ALL和OVER_LIMIT_EXCEPT_OVERFLOW都行。 -2 多选(setMultiSelect()):建议使用OVER_LIMIT_EXCEPT_OVERFLOW。 +1 单选文件:选择指定类型的任意文件都可以。即OVER_LIMIT_EXCEPT_ALL和OVER_LIMIT_EXCEPT_OVERFLOW都行。 +2 多选文件(setMultiSelect()):建议使用OVER_LIMIT_EXCEPT_OVERFLOW。 如果使用`OVER_LIMIT_EXCEPT_ALL`,每一种指定类型的文件都至少选取setMinCount(int)个, 比如只选择了一个xxx.txt文件会报错,因为其它类型文件也设置了最小数量限制却没有被选择, 进而被判定为选取失败抛出最小限定的异常。因此,多文件选择建议使用OVER_LIMIT_EXCEPT_OVERFLOW策略, @@ -470,7 +450,7 @@ TXT(mutableListOf("txt", "conf", "iml", "ini", "log", "prop", "rc", "csv", "html ``` ```kotlin -//图片 Image +//设定选择图片文件的规则 Set rules for selecting image files val optionsImage = FileSelectOptions().apply { fileType = FileType.IMAGE minCount = 1 @@ -483,13 +463,11 @@ val optionsImage = FileSelectOptions().apply { allFilesMaxSizeTip = "图片总大小不超过10M !" //The total size of the picture does not exceed 10M ! fileCondition = object : FileSelectCondition { override fun accept(fileType: IFileType, uri: Uri?): Boolean { - return (fileType == FileType.IMAGE && uri != null && !uri.path.isNullOrBlank() && !FileUtils.isGif( - uri - )) + return (fileType == FileType.IMAGE && uri != null && !uri.path.isNullOrBlank() && !FileUtils.isGif(uri)) } } } -//音频 Audio +//设定选择音频文件的规则 Sets the rules for selecting audio files val optionsAudio = FileSelectOptions().apply { fileType = FileType.AUDIO minCount = 2 @@ -506,7 +484,7 @@ val optionsAudio = FileSelectOptions().apply { } } } -//文本文件 txt +//设定选择文本文件文件的规则 Sets the rules for selecting text file files val optionsTxt = FileSelectOptions().apply { fileType = FileType.TXT minCount = 1 @@ -613,12 +591,10 @@ eg: 结果(result): TXT(mutableListOf("txt", "conf", "iml", "ini", "log", "prop", "rc", "gradle", "kt")) 移除(remove): FileType.TXT.remove("txt", "ini") -结果(result): TXT( - mutableListOf( - "conf", "iml", log", " prop ", " rc ")) +结果(result): TXT(mutableListOf("conf", "iml", "log", "prop", "rc")) - 替换 (replace): FileType. XML . replace ("xxx") - 调试 (debugging): FileType. TXT . dump () +替换 (replace): FileType.XML.replace("xxx") +调试 (debugging): FileType.TXT.dump() ``` ##### 2通过`IFileType`自定义文件类型 @@ -768,18 +744,15 @@ override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) ## Q&A -** -README_QA.md** https://github.com/javakam/FileOperator/blob/master/README_QA.md +**README_QA.md** https://github.com/javakam/FileOperator/blob/master/README_QA.md ## 更新日志 (Update log) -** -README_VERSIONS.md** https://github.com/javakam/FileOperator/blob/master/README_VERSIONS.md +**README_VERSIONS.md** https://github.com/javakam/FileOperator/blob/master/README_VERSIONS.md ## 感谢 (Thanks) -** -README_THANKS.md** https://github.com/javakam/FileOperator/blob/master/README_THANKS.md +**README_THANKS.md** https://github.com/javakam/FileOperator/blob/master/README_THANKS.md ## 许可(LICENSE) diff --git a/README_VERSIONS.md b/README_VERSIONS.md index 58f748c..4c1bf9f 100644 --- a/README_VERSIONS.md +++ b/README_VERSIONS.md @@ -1,5 +1,19 @@ # 更新日志(Update log) +## v3.9.8 +``` +主要改动了 requestCode 请求机制。 +FileSelector默认requestCode值为1 👉 val REQUEST_CODE_DEFAULT: Int = 1 + +FileSelector处理传入(mRequestCode)和接收(requestCode)的比较: +if (requestCode == -1 || requestCode != mRequestCode) return +改为 +if (requestCode != mRequestCode) { + mFileSelectCallBack?.onError(Throwable("请比较 setRequestCode() 和 obtainResult() 方法中的 requestCode 值是否一致!(Please compare whether the requestCode values in setRequestCode() and obtainResult() methods are consistent!)")) + return +} +``` + ## v3.9.0 & v3.8.0 ``` 优化媒体信息用例, 显示图片/音频/视频文件的全部信息 diff --git a/app/build.gradle b/app/build.gradle index 0a23cad..17641b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -122,7 +122,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" //权限;图片 - implementation 'com.permissionx.guolindev:permissionx:1.4.0' + implementation 'com.guolindev.permissionx:permissionx:1.7.1' implementation 'com.github.bumptech.glide:glide:4.16.0' //kapt 'com.github.bumptech.glide:compiler:4.16.0' //网络;gson diff --git a/app/src/main/java/com/ando/file/sample/ui/2024 b/app/src/main/java/com/ando/file/sample/ui/2024 new file mode 100644 index 0000000..06201f4 --- /dev/null +++ b/app/src/main/java/com/ando/file/sample/ui/2024 @@ -0,0 +1,8 @@ +### 11 +https://developer.android.com/about/versions/11/summary?hl=zh-cn +### 12 +https://developer.android.com/about/versions/12/summary?hl=zh-cn +https://developer.android.com/training/data-storage/shared/media?hl=zh-cn#well-defined-collections +### 13 +https://developer.android.com/about/versions/13/summary?hl=zh-cn +https://developer.android.com/about/versions/13/features/photopicker?hl=zh-cn \ No newline at end of file diff --git a/app/src/main/java/com/ando/file/sample/ui/selector/FileSelectSingleImageActivity.kt b/app/src/main/java/com/ando/file/sample/ui/selector/FileSelectSingleImageActivity.kt index ac2aa86..e88fd0b 100644 --- a/app/src/main/java/com/ando/file/sample/ui/selector/FileSelectSingleImageActivity.kt +++ b/app/src/main/java/com/ando/file/sample/ui/selector/FileSelectSingleImageActivity.kt @@ -82,7 +82,7 @@ class FileSelectSingleImageActivity : AppCompatActivity() { } } - //todo 2022年1月21日 17:43:34 批量删除 + //2022年1月21日 17:43:34 测试批量删除 //删除该文件 //用于测试 👉 https://github.com/javakam/FileOperator/issues/70 mBtDelete.visibility = View.VISIBLE @@ -113,6 +113,7 @@ class FileSelectSingleImageActivity : AppCompatActivity() { @Suppress("DEPRECATION") override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) + FileLogger.w("Back ok -> onActivityResult") //同下 } @@ -120,7 +121,7 @@ class FileSelectSingleImageActivity : AppCompatActivity() { private val mStartForResult: ActivityResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result: ActivityResult -> FileLogger.w("Back ok -> ActivityResultCallback") - handleResult(REQUEST_CHOOSE_FILE, result.resultCode, result.data) + handleResult(result.resultCode, result.data) } override fun onDestroy() { @@ -128,10 +129,10 @@ class FileSelectSingleImageActivity : AppCompatActivity() { super.onDestroy() } - private fun handleResult(requestCode: Int, resultCode: Int, data: Intent?) { - ResultUtils.resetUI(mTvError, mTvResult, mIvOrigin, mIvCompressed) + private fun handleResult(resultCode: Int, data: Intent?) { + // ResultUtils.resetUI(mTvError, mTvResult, mIvOrigin, mIvCompressed) //选择结果交给 FileSelector 处理, 可通过`requestCode -> REQUEST_CHOOSE_FILE`进行区分 - mFileSelector?.obtainResult(requestCode, resultCode, data) + mFileSelector?.obtainResult(REQUEST_CHOOSE_FILE, resultCode, data) } private fun chooseFile() { diff --git a/build.gradle b/build.gradle index fafa5f4..d4d8e30 100644 --- a/build.gradle +++ b/build.gradle @@ -9,9 +9,12 @@ buildscript { buildToolsVersion = '33.0.2' minSdkVersion = 21 targetSdkVersion = 33 + //2023年12月21日 + versionCode = 22 + versionName = "3.9.8" //2023年8月29日 09:47:46 - versionCode = 19 - versionName = "3.9.0" +// versionCode = 19 +// versionName = "3.9.0" //2023年8月22日 11:26:08 // versionCode = 18 // versionName = "3.8.0" diff --git a/library_selector/src/main/java/ando/file/selector/FileSelector.kt b/library_selector/src/main/java/ando/file/selector/FileSelector.kt index ed2c659..37e8242 100644 --- a/library_selector/src/main/java/ando/file/selector/FileSelector.kt +++ b/library_selector/src/main/java/ando/file/selector/FileSelector.kt @@ -28,6 +28,7 @@ import kotlin.math.min class FileSelector private constructor(builder: Builder) { companion object { + val REQUEST_CODE_DEFAULT: Int = 1 val TIP_SINGLE_FILE_TYPE_MISMATCH: String by lazy { getContext().getString(R.string.ando_str_single_file_type_mismatch) } val TIP_SINGLE_FILE_SIZE: String by lazy { getContext().getString(R.string.ando_str_single_file_size) } val TIP_ALL_FILE_SIZE: String by lazy { getContext().getString(R.string.ando_str_all_file_size) } @@ -44,7 +45,7 @@ class FileSelector private constructor(builder: Builder) { } private var mStartForResult: ActivityResultLauncher? = null - private var mRequestCode: Int = 0 + private var mRequestCode: Int = REQUEST_CODE_DEFAULT private var mExtraMimeTypes: Array? private var mIsMultiSelect: Boolean = false @@ -73,7 +74,7 @@ class FileSelector private constructor(builder: Builder) { private var isOptionsEmpty: Boolean = false //onActivityResult - var requestCode: Int? = -1 + var requestCode: Int? = REQUEST_CODE_DEFAULT var resultCode: Int? = 0 init { @@ -98,6 +99,7 @@ class FileSelector private constructor(builder: Builder) { fun choose(context: Any, mimeType: String?): FileSelector { checkParams() + FileLogger.e("requestCode = $mRequestCode") if (mStartForResult == null) { startActivityForResult(context, createChooseIntent(mimeType, mExtraMimeTypes, mIsMultiSelect), mRequestCode) return this @@ -106,9 +108,11 @@ class FileSelector private constructor(builder: Builder) { is ComponentActivity -> {// androidx.activity.ComponentActivity mStartForResult?.launch(createChooseIntent(mimeType, mExtraMimeTypes, mIsMultiSelect)) } + is Fragment -> { mStartForResult?.launch(createChooseIntent(mimeType, mExtraMimeTypes, mIsMultiSelect)) } + else -> { startActivityForResult(context, createChooseIntent(mimeType, mExtraMimeTypes, mIsMultiSelect), mRequestCode) } @@ -124,12 +128,15 @@ class FileSelector private constructor(builder: Builder) { } fun obtainResult(requestCode: Int, resultCode: Int, intent: Intent?) { + if (requestCode != mRequestCode) { + mFileSelectCallBack?.onError(Throwable("请比较 setRequestCode() 和 obtainResult() 方法中的 requestCode 值是否一致!(Please compare whether the requestCode values in setRequestCode() and obtainResult() methods are consistent!)")) + return + } + this.requestCode = requestCode this.resultCode = resultCode this.mFileTypeComposite.clear() - if (requestCode == -1 || requestCode != mRequestCode) return - //没有设定 FileSelectOptions 的情况(When FileSelectOptions is not set) isOptionsEmpty = mFileSelectOptions.isNullOrEmpty() if (mFileSelectOptions == null) mFileSelectOptions = mutableListOf() @@ -383,6 +390,7 @@ class FileSelector private constructor(builder: Builder) { OVER_LIMIT_EXCEPT_ALL -> { mFileSelectCallBack?.onError(Throwable(mAllFilesMaxSizeTip)) } + OVER_LIMIT_EXCEPT_OVERFLOW -> { if (resultList.isNotEmpty()) resultList.clear() relationMap.values.forEach { sr: SelectResult -> resultList.addAll(sr.uriList) } @@ -431,6 +439,7 @@ class FileSelector private constructor(builder: Builder) { } } } + OVER_LIMIT_EXCEPT_OVERFLOW -> { if (resultList.isNotEmpty()) resultList.clear() @@ -603,7 +612,7 @@ class FileSelector private constructor(builder: Builder) { class Builder internal constructor(private val context: Any, launcher: ActivityResultLauncher?) { var mStartForResult: ActivityResultLauncher? = launcher - var mRequestCode: Int = 0 + var mRequestCode: Int = REQUEST_CODE_DEFAULT var mExtraMimeTypes: Array? = null //eg: Intent.putExtra(Intent.EXTRA_MIME_TYPES, mExtraMimeTypes) var mIsMultiSelect: Boolean = false AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル
AltStyle によって変換されたページ (->オリジナル) / アドレス: モード: デフォルト 音声ブラウザ ルビ付き 配色反転 文字拡大 モバイル