diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java b/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java index 09301f2d..f9913e80 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/FtpOption.java @@ -21,7 +21,7 @@ import com.arialyy.aria.core.IdEntity; import com.arialyy.aria.core.ProtocolType; import com.arialyy.aria.core.processor.IFtpUploadInterceptor; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import java.text.DateFormatSymbols; import java.util.Collection; import java.util.Locale; @@ -158,7 +158,7 @@ public class FtpOption extends BaseOption { if (uploadInterceptor == null) { throw new NullPointerException("ftp拦截器为空"); } - CheckUtil.checkMemberClass(uploadInterceptor.getClass()); + FileUtils.checkMemberClass(uploadInterceptor.getClass()); this.uploadInterceptor = uploadInterceptor; return this; } @@ -212,7 +212,7 @@ public class FtpOption extends BaseOption { ALog.e(TAG, "ip为空"); return this; } - if (!CheckUtil.checkIp(ip)) { + if (!FileUtils.checkIp(ip)) { ALog.e(TAG, "ip地址错误:" + ip); return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java b/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java index a431f301..34eef965 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/common/HttpOption.java @@ -19,7 +19,7 @@ import android.text.TextUtils; import com.arialyy.aria.core.processor.IHttpFileLenAdapter; import com.arialyy.aria.core.processor.IHttpFileNameAdapter; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import java.net.Proxy; import java.util.HashMap; import java.util.Map; @@ -166,7 +166,7 @@ public class HttpOption extends BaseOption { if (fileLenAdapter == null) { throw new IllegalArgumentException("adapter为空"); } - CheckUtil.checkMemberClass(fileLenAdapter.getClass()); + FileUtils.checkMemberClass(fileLenAdapter.getClass()); this.fileLenAdapter = fileLenAdapter; return this; } @@ -174,7 +174,7 @@ public class HttpOption extends BaseOption { if (fileNameAdapter == null) { throw new IllegalArgumentException("adapter为空"); } - CheckUtil.checkMemberClass(fileNameAdapter.getClass()); + FileUtils.checkMemberClass(fileNameAdapter.getClass()); this.fileNameAdapter = fileNameAdapter; return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java index e5cd7bdb..cdb2bcb5 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDEntityUtil.java @@ -23,7 +23,7 @@ import com.arialyy.aria.core.inf.ITargetHandler; import com.arialyy.aria.core.wrapper.ITaskWrapper; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.RecordUtil; @@ -154,7 +154,7 @@ public class CheckDEntityUtil implements ICheckEntityUtil { //设置文件保存路径,如果新文件路径和旧文件路径不同,则修改路径 if (!filePath.equals(mEntity.getFilePath())) { // 检查路径冲突 - if (!CheckUtil.checkDPathConflicts(mWrapper.isIgnoreFilePathOccupy(), filePath, + if (!FileUtils.checkDPathConflicts(mWrapper.isIgnoreFilePathOccupy(), filePath, mWrapper.getRequestType())) { return false; } @@ -189,7 +189,7 @@ public class CheckDEntityUtil implements ICheckEntityUtil { if (TextUtils.isEmpty(url)) { ALog.e(TAG, "下载失败,url为null"); return false; - } else if (!CheckUtil.checkUrl(url)) { + } else if (!FileUtils.checkUrl(url)) { ALog.e(TAG, "下载失败,url【" + url + "】错误"); return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java index 67c6e0a2..41a6c872 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckDGEntityUtil.java @@ -22,7 +22,7 @@ import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.RecordUtil; import java.io.File; @@ -85,7 +85,7 @@ public class CheckDGEntityUtil implements ICheckEntityUtil { } // 检查路径冲突 - if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), + if (mWrapper.isNewTask() && !FileUtils.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), dirPath)) { return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java index 9e479fea..fd04f769 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/CheckFtpDirEntityUtil.java @@ -20,7 +20,7 @@ import com.arialyy.aria.core.FtpUrlEntity; import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.core.inf.IOptionConstant; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import java.io.File; public class CheckFtpDirEntityUtil implements ICheckEntityUtil { @@ -61,7 +61,7 @@ public class CheckFtpDirEntityUtil implements ICheckEntityUtil { } // 检查路径冲突 - if (mWrapper.isNewTask() && !CheckUtil.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), + if (mWrapper.isNewTask() && !FileUtils.checkDGPathConflicts(mWrapper.isIgnoreFilePathOccupy(), dirPath)) { return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java index 7766da1d..2ea352ae 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadReceiver.java @@ -45,7 +45,7 @@ import com.arialyy.aria.core.scheduler.TaskSchedulers; import com.arialyy.aria.core.task.ITask; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.ComponentUtil; import com.arialyy.aria.util.DbDataHelper; @@ -270,7 +270,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果url错误或查找不到数据,则返回null */ public DownloadEntity getFirstDownloadEntity(String downloadUrl) { - if (!CheckUtil.checkUrl(downloadUrl)) { + if (!FileUtils.checkUrl(downloadUrl)) { return null; } return DbEntity.findFirst(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl); @@ -282,7 +282,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果url错误或查找不到数据,则返回null */ public List getDownloadEntity(String downloadUrl) { - if (!CheckUtil.checkUrl(downloadUrl)) { + if (!FileUtils.checkUrl(downloadUrl)) { return null; } return DbEntity.findDatas(DownloadEntity.class, "url=? and isGroupChild='false'", downloadUrl); @@ -308,7 +308,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果实体不存在,返回null */ public DownloadGroupEntity getGroupEntity(List urls) { - if (CheckUtil.checkDownloadUrlsIsEmpty(urls)) { + if (FileUtils.checkDownloadUrlsIsEmpty(urls)) { return null; } return DbDataHelper.getDGEntityByHash(CommonUtil.getMd5Code(urls)); @@ -321,7 +321,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果实体不存在,返回null */ public DownloadGroupEntity getFtpDirEntity(String url) { - if (!CheckUtil.checkUrl(url)) { + if (!FileUtils.checkUrl(url)) { return null; } return DbDataHelper.getDGEntityByHash(url); @@ -387,7 +387,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getTaskList(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(DownloadEntity.class, page, num, "isGroupChild=? and downloadPath!=''", "false"); } @@ -408,7 +408,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getAllNotCompleteTask(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(DownloadEntity.class, page, num, "isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); } @@ -429,7 +429,7 @@ public class DownloadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getAllCompleteTask(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(DownloadEntity.class, "isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveOption.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveOption.java index c8a3b8f3..d3dcda56 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8LiveOption.java @@ -17,7 +17,7 @@ package com.arialyy.aria.core.download.m3u8; import com.arialyy.aria.core.processor.ILiveTsUrlConverter; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; /** * m3u8直播参数设置 @@ -38,7 +38,7 @@ public class M3U8LiveOption extends M3U8Option { * @param liveTsUrlConverter {@link ILiveTsUrlConverter} */ public M3U8LiveOption setLiveTsUrlConvert(ILiveTsUrlConverter liveTsUrlConverter) { - CheckUtil.checkMemberClass(liveTsUrlConverter.getClass()); + FileUtils.checkMemberClass(liveTsUrlConverter.getClass()); this.liveTsUrlConverter = liveTsUrlConverter; return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Option.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Option.java index 7bc57a10..c4eaefb9 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Option.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8Option.java @@ -21,7 +21,7 @@ import com.arialyy.aria.core.processor.IBandWidthUrlConverter; import com.arialyy.aria.core.processor.IKeyUrlConverter; import com.arialyy.aria.core.processor.ITsMergeHandler; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.ComponentUtil; /** @@ -101,7 +101,7 @@ public class M3U8Option extends BaseOption { * 需要注意的是:只有{@link #merge(boolean)}设置合并ts文件,该方法才会生效 */ public OP setMergeHandler(ITsMergeHandler mergeHandler) { - CheckUtil.checkMemberClass(mergeHandler.getClass()); + FileUtils.checkMemberClass(mergeHandler.getClass()); this.mergeHandler = mergeHandler; return (OP) this; } @@ -123,7 +123,7 @@ public class M3U8Option extends BaseOption { * @param bandWidthUrlConverter {@link IBandWidthUrlConverter} */ public OP setBandWidthUrlConverter(IBandWidthUrlConverter bandWidthUrlConverter) { - CheckUtil.checkMemberClass(bandWidthUrlConverter.getClass()); + FileUtils.checkMemberClass(bandWidthUrlConverter.getClass()); this.bandWidthUrlConverter = bandWidthUrlConverter; return (OP) this; } @@ -134,7 +134,7 @@ public class M3U8Option extends BaseOption { * @param keyUrlConverter {@link IKeyUrlConverter} */ public OP setKeyUrlConverter(IKeyUrlConverter keyUrlConverter) { - CheckUtil.checkMemberClass(keyUrlConverter.getClass()); + FileUtils.checkMemberClass(keyUrlConverter.getClass()); this.keyUrlConverter = keyUrlConverter; return (OP) this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodOption.java b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodOption.java index 563224c7..9d7a2313 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodOption.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/m3u8/M3U8VodOption.java @@ -17,7 +17,7 @@ package com.arialyy.aria.core.download.m3u8; import com.arialyy.aria.core.processor.IVodTsUrlConverter; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; /** * m3u8点播文件参数设置 @@ -39,7 +39,7 @@ public class M3U8VodOption extends M3U8Option { * @param vodUrlConverter {@link IVodTsUrlConverter} */ public M3U8VodOption setVodTsUrlConvert(IVodTsUrlConverter vodUrlConverter) { - CheckUtil.checkMemberClass(vodUrlConverter.getClass()); + FileUtils.checkMemberClass(vodUrlConverter.getClass()); this.vodUrlConverter = vodUrlConverter; return this; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/CheckUEntityUtil.java b/Aria/src/main/java/com/arialyy/aria/core/upload/CheckUEntityUtil.java index ea6c81f2..25a315e8 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/CheckUEntityUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/CheckUEntityUtil.java @@ -18,7 +18,7 @@ package com.arialyy.aria.core.upload; import android.text.TextUtils; import com.arialyy.aria.core.inf.ICheckEntityUtil; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import java.io.File; public class CheckUEntityUtil implements ICheckEntityUtil { @@ -62,7 +62,7 @@ public class CheckUEntityUtil implements ICheckEntityUtil { } // 任务是新任务,并且路径冲突就不会继续执行 if (mWrapper.isNewTask() - && !CheckUtil.checkUPathConflicts(mWrapper.isIgnoreFilePathOccupy(), filePath, + && !FileUtils.checkUPathConflicts(mWrapper.isIgnoreFilePathOccupy(), filePath, mWrapper.getRequestType())) { return false; } @@ -86,7 +86,7 @@ public class CheckUEntityUtil implements ICheckEntityUtil { if (TextUtils.isEmpty(url)) { ALog.e(TAG, "上传失败,url为null"); return false; - } else if (!CheckUtil.checkUrl(url)) { + } else if (!FileUtils.checkUrl(url)) { ALog.e(TAG, "上传失败,url【" + url + "】错误"); return false; } diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java index cb299fb7..10ddf065 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java @@ -39,7 +39,7 @@ import com.arialyy.aria.core.upload.target.HttpNormalTarget; import com.arialyy.aria.core.upload.target.UTargetFactory; import com.arialyy.aria.orm.DbEntity; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.ComponentUtil; import java.util.List; import java.util.Set; @@ -73,7 +73,7 @@ public class UploadReceiver extends AbsReceiver { public HttpBuilderTarget load(String filePath) { ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_HTTP); - CheckUtil.checkUploadPathIsEmpty(filePath); + FileUtils.checkUploadPathIsEmpty(filePath); return UTargetFactory.getInstance() .generateBuilderTarget(HttpBuilderTarget.class, filePath); } @@ -99,7 +99,7 @@ public class UploadReceiver extends AbsReceiver { public FtpBuilderTarget loadFtp(String filePath) { ComponentUtil.getInstance().checkComponentExist(ComponentUtil.COMPONENT_TYPE_FTP); - CheckUtil.checkUploadPathIsEmpty(filePath); + FileUtils.checkUploadPathIsEmpty(filePath); return UTargetFactory.getInstance() .generateBuilderTarget(FtpBuilderTarget.class, filePath); } @@ -178,7 +178,7 @@ public class UploadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getTaskList(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(UploadEntity.class, page, num, "isGroupChild=? and downloadPath!=''", "false"); } @@ -199,7 +199,7 @@ public class UploadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getAllNotCompleteTask(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(UploadEntity.class, page, num, "isGroupChild=? and downloadPath!='' and isComplete=?", "false", "false"); } @@ -220,7 +220,7 @@ public class UploadReceiver extends AbsReceiver { * @return 如果页数大于总页数,返回null */ public List getAllCompleteTask(int page, int num) { - CheckUtil.checkPageParams(page, num); + FileUtils.checkPageParams(page, num); return DbEntity.findDatas(UploadEntity.class, "isGroupChild=? and downloadPath!='' and isComplete=?", "false", "true"); } diff --git a/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java b/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java index 35af8b43..33c1c95b 100644 --- a/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java +++ b/FtpComponent/src/main/java/com/arialyy/aria/ftp/AbsFtpInfoTask.java @@ -34,7 +34,7 @@ import com.arialyy.aria.core.loader.ILoaderVisitor; import com.arialyy.aria.core.wrapper.AbsTaskWrapper; import com.arialyy.aria.exception.AriaFTPException; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.SSLContextUtil; import java.io.IOException; @@ -140,7 +140,7 @@ public abstract class AbsFtpInfoTask() + for (br in taskRecord.blockList) { + val blockF = File(br.blockPath) + if (blockF.exists()) { + if (br.curProgress == blockF.length() && !br.isComplete) { + br.isComplete = true + needUpdateBlockRecord.add(br) + } + if (br.curProgress != blockF.length()) { + br.curProgress = blockF.length() + needUpdateBlockRecord.add(br) + blockManager.putUnfinishedBlock(br) + } + // update task progress + handler.obtainMessage(IBlockManager.STATE_UPDATE_PROGRESS, br.curProgress) + } + } + handler.removeCallbacksAndMessages(null) + + // update block record + val dao = DuaContext.getServiceManager().getDbService().getDuaDb().getRecordDao() + withContext(Dispatchers.IO) { + dao.updateBlockList(needUpdateBlockRecord.toMutableList()) } + return TaskResp.CODE_SUCCESS } } \ No newline at end of file diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDFileInfoTask.java b/Http/src/main/java/com/arialyy/aria/http/download/HttpDFileInfoTask.java index 135d5c65..2f166f99 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDFileInfoTask.java +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDFileInfoTask.java @@ -31,7 +31,7 @@ import com.arialyy.aria.exception.AriaHTTPException; import com.arialyy.aria.http.ConnectionHelp; import com.arialyy.aria.http.HttpTaskOption; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.RecordUtil; @@ -262,7 +262,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable { } else { failDownload(new AriaHTTPException( String.format("任务下载失败,errorCode:%s, errorMsg: %s, url: %s", code, - conn.getResponseMessage(), mEntity.getUrl())), !CheckUtil.httpIsBadRequest(code)); + conn.getResponseMessage(), mEntity.getUrl())), !FileUtils.httpIsBadRequest(code)); } if (end) { doNext(code, isChunked); @@ -324,7 +324,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable { ALog.d(TAG, String.format("文件重命名为:%s", newName)); File oldFile = new File(mEntity.getFilePath()); String newPath = oldFile.getParent() + "/" + newName; - if (!CheckUtil.checkDPathConflicts(false, newPath, mTaskWrapper.getRequestType())) { + if (!FileUtils.checkDPathConflicts(false, newPath, mTaskWrapper.getRequestType())) { ALog.e(TAG, "文件重命名失败"); return; } @@ -353,7 +353,7 @@ final class HttpDFileInfoTask implements IInfoTask, Runnable { newUrl = uri.getHost() + newUrl; } - if (!CheckUtil.checkUrl(newUrl)) { + if (!FileUtils.checkUrl(newUrl)) { failDownload(new AriaHTTPException("下载失败,重定向url错误"), false); return; } diff --git a/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt b/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt index e9dcfba3..66f9c214 100644 --- a/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt +++ b/Http/src/main/java/com/arialyy/aria/http/download/HttpDHeaderInterceptor.kt @@ -28,7 +28,7 @@ import com.arialyy.aria.core.task.TaskChain import com.arialyy.aria.core.task.TaskResp import com.arialyy.aria.http.HttpUtil import com.arialyy.aria.http.request.IRequest -import com.arialyy.aria.util.CheckUtil +import com.arialyy.aria.util.FileUtils import timber.log.Timber import java.io.BufferedReader import java.io.IOException @@ -169,7 +169,7 @@ internal class HttpDHeaderInterceptor : ITaskInterceptor { val uri = Uri.parse(taskOption.sourUrl!!) tempUrl = uri.host + newUrl } - if (!CheckUtil.checkUrl(tempUrl)) { + if (!FileUtils.checkUrl(tempUrl)) { Timber.e("get redirect url fail, $tempUrl") return -1 } diff --git a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8InfoTask.java b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8InfoTask.java index 1970009f..b31d4ca7 100644 --- a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8InfoTask.java +++ b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8InfoTask.java @@ -34,7 +34,7 @@ import com.arialyy.aria.exception.AriaM3U8Exception; import com.arialyy.aria.http.ConnectionHelp; import com.arialyy.aria.http.HttpTaskOption; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import com.arialyy.aria.util.FileUtil; import com.arialyy.aria.util.Regular; @@ -327,7 +327,7 @@ final public class M3U8InfoTask implements IInfoTask { newUrl = uri.getHost() + newUrl; } - if (!CheckUtil.checkUrl(newUrl)) { + if (!FileUtils.checkUrl(newUrl)) { failDownload("下载失败,重定向url错误", false); return; } diff --git a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8ThreadTaskAdapter.java b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8ThreadTaskAdapter.java index 6e30ab2b..ffbc358f 100644 --- a/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8ThreadTaskAdapter.java +++ b/M3U8Component/src/main/java/com/arialyy/aria/m3u8/M3U8ThreadTaskAdapter.java @@ -25,7 +25,7 @@ import com.arialyy.aria.exception.AriaM3U8Exception; import com.arialyy.aria.http.ConnectionHelp; import com.arialyy.aria.http.HttpTaskOption; import com.arialyy.aria.util.ALog; -import com.arialyy.aria.util.CheckUtil; +import com.arialyy.aria.util.FileUtils; import com.arialyy.aria.util.CommonUtil; import java.io.BufferedInputStream; import java.io.FileOutputStream; @@ -159,7 +159,7 @@ public final class M3U8ThreadTaskAdapter extends AbsThreadTaskAdapter { newUrl = uri.getHost() + newUrl; } - if (!CheckUtil.checkUrl(newUrl)) { + if (!FileUtils.checkUrl(newUrl)) { fail(new AriaM3U8Exception("下载失败,重定向url错误"), false); return; } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IBlockManager.java b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IBlockManager.java index 2254cdc6..44882bb7 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IBlockManager.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/inf/IBlockManager.java @@ -18,6 +18,7 @@ package com.arialyy.aria.core.inf; import android.os.Handler; import android.os.Looper; import androidx.annotation.NonNull; +import com.arialyy.aria.orm.entity.BlockRecord; /** * 线程任务状态 @@ -41,6 +42,10 @@ public interface IBlockManager { void setBlockNum(int blockNum); + void putUnfinishedBlock(BlockRecord record); + + BlockRecord getUnfinishedBlock(); + /** * 是否有失败的快 * diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockState.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockState.kt deleted file mode 100644 index b91125d5..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockState.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.core.task - -import com.arialyy.aria.orm.entity.BlockRecord - -class BlockState(val blockState: BlockRecord, val blockPath: String) { - - companion object { - /** - * dir/.fileName.blockId - */ - const val BLOCK_PATH = "%s/.%s.%d" - - const val BLOCK_SIZE = 1024 * 1024 * 5L - } - - var curProgress: Long = 0 -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockUtil.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockUtil.kt index d4fa1145..010f6bff 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockUtil.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockUtil.kt @@ -1,9 +1,11 @@ package com.arialyy.aria.core.task -import android.bluetooth.BluetoothClass +import android.net.Uri import com.arialyy.aria.orm.entity.BlockRecord import com.arialyy.aria.orm.entity.TaskRecord +import com.arialyy.aria.util.FileUri import com.arialyy.aria.util.FileUtil +import com.arialyy.aria.util.FileUtils import timber.log.Timber import java.io.File @@ -24,22 +26,35 @@ import java.io.File */ object BlockUtil { + fun getBlockPathFormUri(fileSaveUri: Uri, blockId: Int): String { + val filePath = FileUri.getPathByUri(fileSaveUri) ?: "/" + val fileName = FileUtils.getFileNameFromPath(filePath) + val dirPath = FileUtils.getFilePathFromFullPath(filePath) + + return BlockRecord.BLOCK_PATH.format(dirPath, fileName, blockId) + } + /** * create block record */ - fun createBlockRecord(fileSize: Long): List { + fun createBlockRecord(fileSaveUri: Uri, fileSize: Long): List { + val filePath = FileUri.getPathByUri(fileSaveUri) ?: "/" + val fileName = FileUtils.getFileNameFromPath(filePath) + val dirPath = FileUtils.getFilePathFromFullPath(filePath) + val blockNumInfo = getBlockNum(fileSize) val lastIndex = blockNumInfo.first - 1 val brList = mutableListOf() for (bi in 0 until blockNumInfo.first) { - val sl = bi * BlockState.BLOCK_SIZE - val blockSize = if (bi == lastIndex) blockNumInfo.second else BlockState.BLOCK_SIZE + val sl = bi * BlockRecord.BLOCK_SIZE + val blockSize = if (bi == lastIndex) blockNumInfo.second else BlockRecord.BLOCK_SIZE val el = sl + blockSize val blockRecord = BlockRecord( bId = bi, - startLocation = bi * BlockState.BLOCK_SIZE, + startLocation = bi * BlockRecord.BLOCK_SIZE, endLocation = el, blockSize = blockSize, + blockPath = BlockRecord.BLOCK_PATH.format(dirPath, fileName, bi) ) brList.add(blockRecord) } @@ -51,11 +66,11 @@ object BlockUtil { * @return pair */ fun getBlockNum(fileLen: Long): Pair { - if (fileLen <= BlockState.BLOCK_SIZE) { + if (fileLen <= BlockRecord.BLOCK_SIZE) { return Pair(1, 0) } - val blockNum = (fileLen / BlockState.BLOCK_SIZE).toInt() - val lastBlockSize = fileLen % BlockState.BLOCK_SIZE + val blockNum = (fileLen / BlockRecord.BLOCK_SIZE).toInt() + val lastBlockSize = fileLen % BlockRecord.BLOCK_SIZE return Pair(if (lastBlockSize != 0L) blockNum + 1 else blockNum, lastBlockSize) } @@ -68,16 +83,16 @@ object BlockUtil { val fileName = targetF.name if (record.blockNum == 1) { // if this task not support blocks or fileSize < 5m, just need rename - return File(BlockState.BLOCK_PATH.format(dir, fileName, 0)).renameTo(targetF) + return File(BlockRecord.BLOCK_PATH.format(dir, fileName, 0)).renameTo(targetF) } val blockList = mutableListOf() for (i in 0 until record.blockNum) { - val subF = File(BlockState.BLOCK_PATH.format(dir, fileName, i)) + val subF = File(BlockRecord.BLOCK_PATH.format(dir, fileName, i)) if (!subF.exists()) { Timber.e("this block: $i not exists") return false } - if (subF.length() != BlockState.BLOCK_SIZE.toLong()) { + if (subF.length() != BlockRecord.BLOCK_SIZE.toLong()) { Timber.e("this block: $i size abnormal, size: ${subF.length()}") return false } @@ -85,5 +100,4 @@ object BlockUtil { } return FileUtil.mergeFile(record.filePath, blockList) } - } \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockManager.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/task/DBlockManager.kt similarity index 91% rename from PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockManager.kt rename to PublicComponent/src/main/java/com/arialyy/aria/core/task/DBlockManager.kt index e3975990..0b0a5617 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/BlockManager.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/task/DBlockManager.kt @@ -20,11 +20,13 @@ import android.os.Looper import com.arialyy.aria.core.inf.IBlockManager import com.arialyy.aria.core.listener.IEventListener import com.arialyy.aria.exception.AriaException +import com.arialyy.aria.orm.entity.BlockRecord import timber.log.Timber +import java.util.concurrent.LinkedBlockingDeque import java.util.concurrent.atomic.AtomicInteger class BlockManager(private val eventListener: IEventListener) : IBlockManager { - private val blockList = mutableListOf() + private val unfinishedBlockQueue = LinkedBlockingDeque() private val canceledNum = AtomicInteger(0) // 已经取消的线程的数 private val stoppedNum = AtomicInteger(0) // 已经停止的线程数 private val failedNum = AtomicInteger(0) // 失败的线程数 @@ -88,12 +90,12 @@ class BlockManager(private val eventListener: IEventListener) : IBlockManager { looper.quit() } - fun addBlockState(state: BlockState) { - blockList.add(state) + override fun putUnfinishedBlock(record: BlockRecord) { + unfinishedBlockQueue.offer(record) } - fun getBlockState(): BlockState { - return blockList.removeFirst() + override fun getUnfinishedBlock(): BlockRecord { + return unfinishedBlockQueue.remove() } override fun setLopper(looper: Looper) { @@ -138,5 +140,4 @@ class BlockManager(private val eventListener: IEventListener) : IBlockManager { override fun getHandlerCallback(): Callback { return callback } - } \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt b/PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt index 10113883..f104cb63 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/core/task/TaskResp.kt @@ -7,9 +7,10 @@ package com.arialyy.aria.core.task **/ class TaskResp(val code: Int = CODE_DEF) { companion object { - const val CODE_COMPLETE = 1 + const val CODE_SUCCESS = 1 const val CODE_INTERRUPT = 999 const val CODE_DEF = 0 + const val CODE_SAVE_URI_NULL = 3 const val CODE_GET_FILE_INFO_FAIL = 2 } diff --git a/PublicComponent/src/main/java/com/arialyy/aria/orm/dao/RecordDao.kt b/PublicComponent/src/main/java/com/arialyy/aria/orm/dao/RecordDao.kt index bda296ae..49edd022 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/orm/dao/RecordDao.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/orm/dao/RecordDao.kt @@ -53,6 +53,10 @@ interface RecordDao { @Update suspend fun update(record: TaskRecord) + @Transaction + @Update + suspend fun updateBlockList(blockList: List) + @Delete suspend fun deleteTaskRecord(record: TaskRecord) diff --git a/PublicComponent/src/main/java/com/arialyy/aria/orm/entity/BlockRecord.kt b/PublicComponent/src/main/java/com/arialyy/aria/orm/entity/BlockRecord.kt index fa651a93..ec39a7dc 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/orm/entity/BlockRecord.kt +++ b/PublicComponent/src/main/java/com/arialyy/aria/orm/entity/BlockRecord.kt @@ -18,7 +18,7 @@ package com.arialyy.aria.orm.entity import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.ForeignKey.Companion.CASCADE -import androidx.room.PrimaryKey +import androidx.room.Ignore /** * @Author laoyuyu @@ -49,5 +49,22 @@ data class BlockRecord( val blockSize: Long = 0, - val isComplete: Boolean = false -) \ No newline at end of file + /** + * block path + */ + val blockPath: String, + + var isComplete: Boolean = false +) { + companion object { + /** + * dir/.fileName.blockId + */ + const val BLOCK_PATH = "%s/.%s.%d" + + const val BLOCK_SIZE = 1024 * 1024 * 5L + } + + @Ignore + var curProgress = 0L +} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.kt b/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.kt deleted file mode 100644 index 30b8fc1a..00000000 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/CheckUtil.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.arialyy.aria.util - -import android.database.Cursor -import android.net.Uri -import com.arialyy.aria.core.DuaContext -import timber.log.Timber -import java.io.InputStream - -object CheckUtil { - - val HTTP_REGEX = - Regex( - "(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]", - RegexOption.IGNORE_CASE - ) - - /** - * check if url is correct - */ - fun checkUrl(url: String) = HTTP_REGEX.matches(url) - - /** - * 1. Check if Uri is correct - * 2. Whether the file corresponding to Uri exists (may be deleted, or the system db has Uri related records, but the file is invalid or damaged) - * - * https://stackoverflow.com/questions/7645951/how-to-check-if-resource-pointed-by-uri-is-available - */ - fun checkUri(uri: Uri?): Boolean { - if (uri == null) return false - val resolver = DuaContext.context.contentResolver - - //1. Check Uri - var cursor: Cursor? = null - val isUriExist: Boolean = try { - cursor = resolver.query(uri, null, null, null, null) - //cursor null: content Uri was invalid or some other error occurred - //cursor.moveToFirst() false: Uri was ok but no entry found. - (cursor != null && cursor.moveToFirst()) - } catch (t: Throwable) { - Timber.e("1.Check Uri Error: ${t.message}") - false - } finally { - try { - cursor?.close() - } catch (t: Throwable) { - } - } - - //2. Check File Exist - //如果系统 db 存有 Uri 相关记录, 但是文件失效或者损坏 (If the system db has Uri related records, but the file is invalid or damaged) - var ins: InputStream? = null - val isFileExist: Boolean = try { - ins = resolver.openInputStream(uri) - // file exists - true - } catch (t: Throwable) { - // File was not found eg: open failed: ENOENT (No such file or directory) - Timber.e("2. Check File Exist Error: ${t.message}") - false - } finally { - try { - ins?.close() - } catch (t: Throwable) { - } - } - return isUriExist && isFileExist - } -} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/Ext.kt b/PublicComponent/src/main/java/com/arialyy/aria/util/Ext.kt new file mode 100644 index 00000000..57d32357 --- /dev/null +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/Ext.kt @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.util + +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import com.arialyy.aria.core.DuaContext +import timber.log.Timber + +internal const val AUTHORITY = ".andoFileProvider" + +/** + * @return 传入的Uri是否已具备访问权限 (Whether the incoming Uri has access permission) + */ +fun giveUriPermission(uri: Uri?): Boolean { + return uri?.run { + when (DuaContext.context.checkUriPermission( + this, + android.os.Process.myPid(), + android.os.Process.myUid(), + Intent.FLAG_GRANT_READ_URI_PERMISSION + )) { + PackageManager.PERMISSION_GRANTED -> true + PackageManager.PERMISSION_DENIED -> { + DuaContext.context.grantUriPermission( + DuaContext.context.packageName, this, Intent.FLAG_GRANT_READ_URI_PERMISSION + ) + false + } + else -> false + } + } ?: false +} + +fun revokeUriPermission(uri: Uri?) { + DuaContext.context.revokeUriPermission(uri, Intent.FLAG_GRANT_READ_URI_PERMISSION) +} + +inline fun Uri.use(block: Uri.() -> R): R { + var isAlreadyHavePermission = false + try { + isAlreadyHavePermission = giveUriPermission(this) + return block() + } catch (t: Throwable) { + Timber.e("giveUriPermission Error ${t.message}") + } finally { + if (!isAlreadyHavePermission) { + try { + revokeUriPermission(this) + } catch (t: Throwable) { + Timber.e("revokeUriPermission Error ${t.message}") + } + } + } + return block() +} \ No newline at end of file diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtil.java b/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtil.java index 953f6af3..b4c7ca0e 100644 --- a/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtil.java +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtil.java @@ -56,6 +56,7 @@ import timber.log.Timber; /** * 文件操作工具类 */ +@Deprecated public class FileUtil { private static final String TAG = "FileUtil"; private static final Pattern DIR_SEPORATOR = Pattern.compile("/"); diff --git a/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtils.kt b/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtils.kt new file mode 100644 index 00000000..97cd2cc4 --- /dev/null +++ b/PublicComponent/src/main/java/com/arialyy/aria/util/FileUtils.kt @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2016 AriaLyy(https://github.com/AriaLyy/Aria) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.arialyy.aria.util + +import android.content.ContentResolver +import android.database.Cursor +import android.net.Uri +import android.provider.OpenableColumns +import com.arialyy.aria.core.DuaContext +import timber.log.Timber +import java.io.InputStream +import java.util.Locale + +object FileUtils { + + val HTTP_REGEX = + Regex( + "(https?)://[-A-Za-z0-9+&@#/%?=~_|!:,.;]+[-A-Za-z0-9+&@#/%=~_|]", + RegexOption.IGNORE_CASE + ) + + /** + * check if url is correct + */ + fun checkUrl(url: String) = HTTP_REGEX.matches(url) + + /** + * https://github.com/javakam/FileOperator/blob/master/library_core/src/main/java/ando/file/core/FileUtils.kt + * + * 1. Check if Uri is correct + * 2. Whether the file corresponding to Uri exists (may be deleted, or the system db has Uri related records, but the file is invalid or damaged) + * + * https://stackoverflow.com/questions/7645951/how-to-check-if-resource-pointed-by-uri-is-available + */ + fun uriEffective(uri: Uri?): Boolean { + if (uri == null) return false + val resolver = DuaContext.context.contentResolver + + //1. Check Uri + var cursor: Cursor? = null + val isUriExist: Boolean = try { + cursor = resolver.query(uri, null, null, null, null) + //cursor null: content Uri was invalid or some other error occurred + //cursor.moveToFirst() false: Uri was ok but no entry found. + (cursor != null && cursor.moveToFirst()) + } catch (t: Throwable) { + Timber.e("1.Check Uri Error: ${t.message}") + false + } finally { + try { + cursor?.close() + } catch (t: Throwable) { + } + } + + //2. Check File Exist + //如果系统 db 存有 Uri 相关记录, 但是文件失效或者损坏 (If the system db has Uri related records, but the file is invalid or damaged) + + return isUriExist && checkFileExistByUri(uri, resolver) + } + + /** + * check file exist + * @return true exist + */ + fun checkFileExistByUri(uri: Uri, resolver: ContentResolver): Boolean { + var ins: InputStream? = null + val isFileExist: Boolean = try { + ins = resolver.openInputStream(uri) + // file exists + true + } catch (t: Throwable) { + // File was not found eg: open failed: ENOENT (No such file or directory) + Timber.e("2. Check File Exist Error: ${t.message}") + false + } finally { + try { + ins?.close() + } catch (t: Throwable) { + } + } + return isFileExist + } + + /** + * ### 路径分割 + * + * ``` + * eg: + * srcPath=/storage/emulated/0/Movies/myVideo.mp4 path=/storage/emulated/0/Movies name=myVideo suffix=mp4 nameSuffix=myVideo.mp4 + * + * /xxx/xxx/note.txt -> path: /xxx/xxx name: note suffix: txt + * ///note.txt -> path: /// name: note suffix: txt + * /note.txt -> path: "" name: note suffix: txt + * note.txt -> path: "" name: note suffix: txt + * ``` + */ + fun splitFilePath( + srcPath: String?, + nameSplit: Char = '/', + suffixSplit: Char = '.', + block: ((path: String, name: String, suffix: String, nameSuffix: String) -> Unit)? = null, + ) { + if (srcPath.isNullOrBlank()) return + val cut = srcPath.lastIndexOf(nameSplit) + // /xxx/xxx/note.txt +0: /xxx/xxx +1: /xxx/xxx/ + val path = if (cut == -1) "" else srcPath.substring(0, cut) + val nameSuffix = if (cut == -1) srcPath else srcPath.substring(cut + 1) + + val dot = nameSuffix.lastIndexOf(suffixSplit) + if (dot != -1) { + val suffix = nameSuffix.substring((dot + 1)).lowercase(Locale.getDefault()) + val name = nameSuffix.substring(0, dot) + Timber.d("splitFilePath srcPath=$srcPath path=$path name=$name suffix=$suffix nameSuffix=$nameSuffix") + block?.invoke(path, name, suffix, nameSuffix) + } + } + + /** + * abc.jpg -> jpg + */ + fun getFileNameSuffix(path: String): String { + var nameSuffix = path + splitFilePath(srcPath = path) { _: String, _: String, suffix: String, _: String -> + nameSuffix = suffix + } + return nameSuffix + } + + /** + * /storage/emulated/0/Movies/myVideo.mp4 -> /storage/emulated/0/Movies + */ + fun getFilePathFromFullPath(path: String?, split: Char = '/'): String? { + if (path.isNullOrBlank()) return null + val cut = path.lastIndexOf(split) + // (cut+1): /storage/emulated/0/Movies/ + if (cut != -1) return path.substring(0, cut) + return path + } + + /** + * /storage/emulated/0/Movies/myVideo.mp4 -> myVideo.mp4 + */ + fun getFileNameFromPath(path: String?, split: Char = '/'): String? { + if (path.isNullOrBlank()) return null + val cut = path.lastIndexOf(split) + if (cut != -1) return path.substring(cut + 1) + return path + } + + /** + * /storage/emulated/0/Movies/myVideo.mp4 -> myVideo.mp4 + */ + fun getFileNameFromUri(uri: Uri?): String? = + uri?.use { + var filename: String? = null + val resolver = DuaContext.context.contentResolver + val mimeType = resolver.getType(uri) + + if (mimeType == null) { + filename = getFileNameFromPath(FileUri.getPathByUri(uri)) + } else { + resolver.query(uri, null, null, null, null)?.use { c: Cursor -> + val nameIndex = c.getColumnIndex(OpenableColumns.DISPLAY_NAME) + if (c.moveToFirst()) filename = c.getString(nameIndex) + } + } + filename + } +} \ No newline at end of file