fix bug https://github.com/AriaLyy/Aria/issues/542 fix bug https://github.com/AriaLyy/Aria/issues/547 修复下载失败时,中断重试无效的问题 增加忽略权限检查的api,`ignoreCheckPermissions()`
This commit is contained in:
@@ -23,6 +23,8 @@ import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkRequest;
|
||||
import android.os.Build;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import com.arialyy.aria.core.config.AppConfig;
|
||||
import com.arialyy.aria.core.config.Configuration;
|
||||
import com.arialyy.aria.core.config.DGroupConfig;
|
||||
@@ -56,6 +58,7 @@ public class AriaConfig {
|
||||
* 是否已经联网,true 已经联网
|
||||
*/
|
||||
private static boolean isConnectedNet = true;
|
||||
private Handler mAriaHandler;
|
||||
|
||||
private AriaConfig(Context context) {
|
||||
APP = context.getApplicationContext();
|
||||
@@ -105,6 +108,13 @@ public class AriaConfig {
|
||||
return mDGConfig;
|
||||
}
|
||||
|
||||
public synchronized Handler getAriaHandler() {
|
||||
if (mAriaHandler == null) {
|
||||
mAriaHandler = new Handler(Looper.getMainLooper());
|
||||
}
|
||||
return mAriaHandler;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册网络监听,只有配置了检查网络{@link AppConfig#isNetCheck()}才会注册事件
|
||||
*/
|
||||
|
||||
@@ -1,55 +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.listener;
|
||||
|
||||
import com.arialyy.aria.exception.BaseException;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/23.
|
||||
*/
|
||||
class UploadListener implements IUploadListener {
|
||||
@Override public void onPre() {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onStart(long startLocation) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onResume(long resumeLocation) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onStop(long stopLocation) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onProgress(long currentLocation) {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onCancel() {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onComplete() {
|
||||
|
||||
}
|
||||
|
||||
@Override public void onFail(boolean needRetry, BaseException e) {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ public class ThreadStateManager implements IThreadState {
|
||||
mFailNum++;
|
||||
if (isFail()) {
|
||||
Bundle b = msg.getData();
|
||||
mListener.onFail(b.getBoolean(KEY_RETRY, true),
|
||||
mListener.onFail(b.getBoolean(KEY_RETRY, false),
|
||||
(BaseException) b.getSerializable(KEY_ERROR_INFO));
|
||||
quitLooper();
|
||||
}
|
||||
|
||||
@@ -353,7 +353,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
} else {
|
||||
ALog.e(TAG, String.format("任务【%s】执行失败", getFileName()));
|
||||
ErrorHelp.saveError(TAG, "", ALog.getExceptionString(ex));
|
||||
sendFailMsg(null);
|
||||
sendFailMsg(null, needRetry);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,7 +365,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
boolean isConnected = NetUtils.isConnected(AriaConfig.getInstance().getAPP());
|
||||
if (!isConnected && !isNotNetRetry) {
|
||||
ALog.w(TAG, String.format("ts切片【%s】重试失败,网络未连接", getFileName()));
|
||||
sendFailMsg(null);
|
||||
sendFailMsg(null, false);
|
||||
return;
|
||||
}
|
||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
||||
@@ -377,7 +377,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
FileUtil.createFile(mConfig.tempFile);
|
||||
ThreadTaskManager.getInstance().retryThread(this);
|
||||
} else {
|
||||
sendFailMsg(null);
|
||||
sendFailMsg(null, needRetry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
private void retryBlockTask(boolean needRetry) {
|
||||
if (!NetUtils.isConnected(AriaConfig.getInstance().getAPP()) && !isNotNetRetry) {
|
||||
ALog.w(TAG, String.format("分块【%s】重试失败,网络未连接", getFileName()));
|
||||
sendFailMsg(null);
|
||||
sendFailMsg(null, false);
|
||||
return;
|
||||
}
|
||||
if (mFailTimes < RETRY_NUM && needRetry && (NetUtils.isConnected(
|
||||
@@ -400,7 +400,7 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
handleBlockRecord();
|
||||
ThreadTaskManager.getInstance().retryThread(this);
|
||||
} else {
|
||||
sendFailMsg(null);
|
||||
sendFailMsg(null, needRetry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -448,13 +448,14 @@ public class ThreadTask implements IThreadTask, IThreadTaskObserver {
|
||||
/**
|
||||
* 发送失败信息
|
||||
*/
|
||||
private void sendFailMsg(@Nullable BaseException e) {
|
||||
private void sendFailMsg(@Nullable BaseException e,boolean needRetry) {
|
||||
Bundle b = new Bundle();
|
||||
b.putBoolean(IThreadState.KEY_RETRY, needRetry);
|
||||
if (e != null) {
|
||||
Bundle b = new Bundle();
|
||||
b.putSerializable(IThreadState.KEY_ERROR_INFO, e);
|
||||
updateState(IThreadState.STATE_FAIL, b);
|
||||
} else {
|
||||
updateState(IThreadState.STATE_FAIL, null);
|
||||
updateState(IThreadState.STATE_FAIL, b);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.Map;
|
||||
class DBConfig {
|
||||
/*adb pull /mnt/sdcard/Android/data/com.arialyy.simple/files/DB/AriaLyyDb d:/db*/
|
||||
static boolean DEBUG = false;
|
||||
static Map<String, Class> mapping = new LinkedHashMap<>();
|
||||
static Map<String, Class<? extends DbEntity>> mapping = new LinkedHashMap<>();
|
||||
static String DB_NAME;
|
||||
static int VERSION = 56;
|
||||
|
||||
@@ -51,8 +51,8 @@ class DBConfig {
|
||||
}
|
||||
|
||||
static {
|
||||
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
|
||||
mapping.put("DownloadEntity", DownloadEntity.class);
|
||||
mapping.put("DownloadGroupEntity", DownloadGroupEntity.class);
|
||||
mapping.put("UploadEntity", UploadEntity.class);
|
||||
mapping.put("ThreadRecord", ThreadRecord.class);
|
||||
mapping.put("TaskRecord", TaskRecord.class);
|
||||
|
||||
@@ -221,4 +221,22 @@ class DelegateCommon extends AbsDelegate {
|
||||
db.execSQL(str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过class 获取该class的表字段
|
||||
*
|
||||
* @return 表字段列表
|
||||
*/
|
||||
List<String> getColumns(Class<? extends DbEntity> clazz) {
|
||||
List<String> columns = new ArrayList<>();
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (SqlUtil.isIgnore(field)) {
|
||||
continue;
|
||||
}
|
||||
columns.add(field.getName());
|
||||
}
|
||||
return columns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,14 +100,14 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
} else if (oldVersion < 53) {
|
||||
handle366Update(db);
|
||||
} else {
|
||||
handleDbUpdate(db, null, null);
|
||||
handleDbUpdate(db, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
if (oldVersion > newVersion) {
|
||||
handleDbUpdate(db, null, null);
|
||||
handleDbUpdate(db, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,10 +145,8 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
*
|
||||
* @param modifyColumns 需要修改的表字段的映射,key为表名,
|
||||
* value{@code Map<String, String>}中的Map的key为老字段名称,value为该老字段对应的新字段名称
|
||||
* @param delColumns 需要删除的表字段,key为表名,value{@code List<String>}为需要删除的字段列表
|
||||
*/
|
||||
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns,
|
||||
Map<String, List<String>> delColumns) {
|
||||
private void handleDbUpdate(SQLiteDatabase db, Map<String, Map<String, String>> modifyColumns) {
|
||||
if (db == null) {
|
||||
ALog.e("SqlHelper", "db 为 null");
|
||||
return;
|
||||
@@ -161,7 +159,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
db.beginTransaction();
|
||||
Set<String> tables = DBConfig.mapping.keySet();
|
||||
for (String tableName : tables) {
|
||||
Class clazz = DBConfig.mapping.get(tableName);
|
||||
Class<? extends DbEntity> clazz = DBConfig.mapping.get(tableName);
|
||||
if (mDelegate.tableExists(db, clazz)) {
|
||||
//修改表名为中介表名
|
||||
String alertSql = String.format("ALTER TABLE %s RENAME TO %s_temp", tableName, tableName);
|
||||
@@ -178,46 +176,57 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
|
||||
// 复制数据
|
||||
if (count > 0) {
|
||||
// 获取旧表的所有字段名称
|
||||
Cursor columnC =
|
||||
db.rawQuery(String.format("PRAGMA table_info(%s_temp)", tableName), null);
|
||||
StringBuilder params = new StringBuilder();
|
||||
|
||||
// 获取新表的所有字段名称
|
||||
List<String> newTabColumns = mDelegate.getColumns(clazz);
|
||||
// 获取旧表的所有字段名称
|
||||
List<String> oldTabColumns = new ArrayList<>();
|
||||
|
||||
while (columnC.moveToNext()) {
|
||||
String columnName = columnC.getString(columnC.getColumnIndex("name"));
|
||||
if (delColumns != null && delColumns.get(tableName) != null) {
|
||||
List<String> delColumn = delColumns.get(tableName);
|
||||
if (delColumn != null && !delColumn.isEmpty()) {
|
||||
if (delColumn.contains(columnName)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
params.append(columnName).append(",");
|
||||
oldTabColumns.add(columnName);
|
||||
}
|
||||
columnC.close();
|
||||
|
||||
// 旧表需要删除的字段,删除旧表有而新表没的字段
|
||||
List<String> diffTab = getDiffColumn(newTabColumns, oldTabColumns);
|
||||
StringBuilder params = new StringBuilder();
|
||||
|
||||
// 需要修改的列名映射表
|
||||
Map<String, String> modifyMap = null;
|
||||
if (modifyColumns != null) {
|
||||
modifyMap = modifyColumns.get(tableName);
|
||||
}
|
||||
|
||||
for (String column : oldTabColumns) {
|
||||
if (!diffTab.isEmpty() && diffTab.contains(column)
|
||||
&& (modifyMap != null && !modifyMap.containsKey(column))) { // 如果旧表字段有修改,忽略这个删除
|
||||
continue;
|
||||
}
|
||||
params.append(column).append(",");
|
||||
}
|
||||
|
||||
String oldParamStr = params.toString();
|
||||
oldParamStr = oldParamStr.substring(0, oldParamStr.length() - 1);
|
||||
String newParamStr = oldParamStr;
|
||||
// 处理字段名称改变
|
||||
if (modifyColumns != null) {
|
||||
Map<String, String> columnMap = modifyColumns.get(tableName);
|
||||
if (columnMap != null && !columnMap.isEmpty()) {
|
||||
Set<String> keys = columnMap.keySet();
|
||||
for (String key : keys) {
|
||||
if (newParamStr.contains(key)) {
|
||||
newParamStr = newParamStr.replace(key, columnMap.get(key));
|
||||
}
|
||||
if (modifyMap != null && !modifyMap.isEmpty()) {
|
||||
Set<String> keys = modifyMap.keySet();
|
||||
for (String key : keys) {
|
||||
if (newParamStr.contains(key)) {
|
||||
newParamStr = newParamStr.replace(key, modifyMap.get(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//恢复数据
|
||||
String insertSql =
|
||||
String.format("INSERT INTO %s (%s) SELECT %s FROM %s_temp", tableName, newParamStr,
|
||||
oldParamStr, tableName);
|
||||
ALog.d(TAG, "insertSql = " + insertSql);
|
||||
|
||||
db.execSQL(insertSql);
|
||||
}
|
||||
//删除中介表
|
||||
@@ -234,6 +243,19 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 取新表差值(需要删除的字段):旧表有而新表没的字段
|
||||
*
|
||||
* @param newTab 新表字段
|
||||
* @param oldTab 旧表字段
|
||||
* @return 旧表有而新表没的字段
|
||||
*/
|
||||
private List<String> getDiffColumn(List<String> newTab, List<String> oldTab) {
|
||||
List<String> temp = new ArrayList<>(oldTab); // 拷贝旧表字段
|
||||
temp.removeAll(newTab);
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除重复的repeat数据
|
||||
*/
|
||||
@@ -256,7 +278,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||
|
||||
// 执行升级操作
|
||||
handleDbUpdate(db, modifyMap, null);
|
||||
handleDbUpdate(db, modifyMap);
|
||||
delRepeatThreadRecord(db);
|
||||
}
|
||||
|
||||
@@ -273,7 +295,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||
|
||||
// 执行升级操作
|
||||
handleDbUpdate(db, modifyMap, null);
|
||||
handleDbUpdate(db, modifyMap);
|
||||
delRepeatThreadRecord(db);
|
||||
}
|
||||
|
||||
@@ -307,7 +329,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
modifyMap.put("ThreadRecord", threadRecordModify);
|
||||
|
||||
// 执行升级操作
|
||||
handleDbUpdate(db, modifyMap, null);
|
||||
handleDbUpdate(db, modifyMap);
|
||||
delRepeatThreadRecord(db);
|
||||
}
|
||||
|
||||
@@ -360,15 +382,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
dGEntityModifyMap.put("groupName", "groupHash");
|
||||
modifyMap.put("DownloadGroupEntity", dGEntityModifyMap);
|
||||
|
||||
// 删除字段
|
||||
Map<String, List<String>> delColumnMap = new HashMap<>();
|
||||
List<String> dEntityDel = new ArrayList<>();
|
||||
dEntityDel.add("taskKey");
|
||||
delColumnMap.put("DownloadEntity", dEntityDel);
|
||||
List<String> dgEntityDel = new ArrayList<>();
|
||||
dgEntityDel.add("subtask");
|
||||
delColumnMap.put("DownloadGroupEntity", dgEntityDel);
|
||||
|
||||
handleDbUpdate(db, modifyMap, delColumnMap);
|
||||
handleDbUpdate(db, modifyMap);
|
||||
}
|
||||
}
|
||||
@@ -62,7 +62,7 @@ public class CheckUtil {
|
||||
public static boolean checkUploadPathConflicts(boolean isForceUpload, String filePath) {
|
||||
if (DbEntity.checkDataExist(UploadEntity.class, "filePath=?", filePath)) {
|
||||
if (!isForceUpload) {
|
||||
ALog.e(TAG, String.format("上传失败,文件路径【%s】已经被其它任务占用,请设置其它保存路径", filePath));
|
||||
ALog.e(TAG, String.format("上传失败,文件路径【%s】已经被其它任务占用,请设置其它文件路径", filePath));
|
||||
return false;
|
||||
} else {
|
||||
ALog.w(TAG, String.format("文件路径【%s】已经被其它任务占用,当前任务将覆盖该路径的文件", filePath));
|
||||
|
||||
@@ -38,6 +38,8 @@ import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.SequenceInputStream;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.Channels;
|
||||
import java.nio.channels.FileChannel;
|
||||
@@ -61,6 +63,21 @@ public class FileUtil {
|
||||
private static final String EXTERNAL_STORAGE_PATH =
|
||||
Environment.getExternalStorageDirectory().getPath();
|
||||
|
||||
/**
|
||||
* 获取m3u8 ts文件的缓存目录。
|
||||
* 缓存文件夹格式:父文件夹/.文件名_码率
|
||||
*
|
||||
* @param path m3u8 文件下载路径
|
||||
* @return m3u8 ts文件的缓存目录
|
||||
*/
|
||||
public static String getTsCacheDir(String path, int bandWidth) {
|
||||
if (TextUtils.isEmpty(path)) {
|
||||
throw new NullPointerException("m3u8文保存路径为空");
|
||||
}
|
||||
File file = new File(path);
|
||||
return String.format("%s/.%s_%s", file.getParent(), file.getName(), bandWidth);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建目录 当目录不存在的时候创建文件,否则返回false
|
||||
*/
|
||||
@@ -409,9 +426,19 @@ public class FileUtil {
|
||||
* 获取SD卡目录列表
|
||||
*/
|
||||
public static List<String> getSDPathList(Context context) {
|
||||
List<String> paths;
|
||||
List<String> paths = null;
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
|
||||
paths = getVolumeList(context);
|
||||
try {
|
||||
paths = getVolumeList(context);
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
List<String> mounts = readMountsFile();
|
||||
List<String> volds = readVoldFile();
|
||||
@@ -471,16 +498,26 @@ public class FileUtil {
|
||||
/**
|
||||
* getSDPathList
|
||||
*/
|
||||
private static List<String> getVolumeList(final Context context) {
|
||||
private static List<String> getVolumeList(final Context context)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException,
|
||||
IllegalAccessException {
|
||||
List<String> pathList = new ArrayList<>();
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
|
||||
StorageManager manager = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
|
||||
List<StorageVolume> volumes = manager.getStorageVolumes();
|
||||
|
||||
Class<?> volumeClass = StorageVolume.class;
|
||||
Method getPath = volumeClass.getDeclaredMethod("getPath");
|
||||
//Method isRemovable = volumeClass.getDeclaredMethod("isRemovable");
|
||||
getPath.setAccessible(true);
|
||||
//isRemovable.setAccessible(true);
|
||||
|
||||
for (StorageVolume volume : volumes) {
|
||||
String state = volume.getState();
|
||||
|
||||
if (state.equals(Environment.MEDIA_MOUNTED)) {
|
||||
pathList.add(volume.toString());
|
||||
pathList.add((String) getPath.invoke(volume));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user