修复一个表创建失败的问题 https://github.com/AriaLyy/Aria/issues/570
修复一个非分块模式下导致下载失败的问题 https://github.com/AriaLyy/Aria/issues/571 修复一个服务器端无法创建socket连接,却没有返回码导致客户端卡住的问题 https://github.com/AriaLyy/Aria/issues/569 修复文件删除后,组合任务没有重新下载的问题 https://github.com/AriaLyy/Aria/issues/574 优化缓存队列和执行队列pull/617/head
parent
27c889e171
commit
8dc16ce302
@ -1,242 +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.orm; |
||||
|
||||
import android.database.Cursor; |
||||
import android.database.sqlite.SQLiteDatabase; |
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.orm.annotation.Default; |
||||
import com.arialyy.aria.orm.annotation.Foreign; |
||||
import com.arialyy.aria.orm.annotation.Primary; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.lang.reflect.Field; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* Created by laoyuyu on 2018/3/22. |
||||
* 通用委托,创建表,检查字段 |
||||
*/ |
||||
class DelegateCommon extends AbsDelegate { |
||||
private DelegateCommon() { |
||||
} |
||||
|
||||
/** |
||||
* 删除指定的表 |
||||
*/ |
||||
void dropTable(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
String deleteSQL = String.format("DROP TABLE IF EXISTS %s", tableName); |
||||
//db.beginTransaction();
|
||||
db.execSQL(deleteSQL); |
||||
//db.setTransactionSuccessful();
|
||||
//db.endTransaction();
|
||||
} |
||||
|
||||
/** |
||||
* 清空表数据 |
||||
*/ |
||||
<T extends DbEntity> void clean(SQLiteDatabase db, Class<T> clazz) { |
||||
db = checkDb(db); |
||||
String tableName = CommonUtil.getClassName(clazz); |
||||
if (tableExists(db, clazz)) { |
||||
String sql = "DELETE FROM " + tableName; |
||||
db.execSQL(sql); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* 查找表是否存在 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
* @return true,该数据库实体对应的表存在;false,不存在 |
||||
*/ |
||||
boolean tableExists(SQLiteDatabase db, Class clazz) { |
||||
return tableExists(db, CommonUtil.getClassName(clazz)); |
||||
} |
||||
|
||||
/** |
||||
* 查找表是否存在 |
||||
* |
||||
* @param tableName 表名 |
||||
* @return true,该数据库实体对应的表存在;false,不存在 |
||||
*/ |
||||
boolean tableExists(SQLiteDatabase db, String tableName) { |
||||
db = checkDb(db); |
||||
Cursor cursor = null; |
||||
try { |
||||
String sql = |
||||
String.format("SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='%s'", |
||||
tableName); |
||||
cursor = db.rawQuery(sql, null); |
||||
if (cursor != null && cursor.moveToNext()) { |
||||
int count = cursor.getInt(0); |
||||
if (count > 0) { |
||||
return true; |
||||
} |
||||
} |
||||
} catch (Exception e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
closeCursor(cursor); |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
/** |
||||
* 检查某个字段的值是否存在 |
||||
* |
||||
* @param expression 字段和值"url=xxx" |
||||
* @return {@code true}该字段的对应的value已存在 |
||||
*/ |
||||
boolean checkDataExist(SQLiteDatabase db, Class clazz, String... expression) { |
||||
db = checkDb(db); |
||||
if (!CommonUtil.checkSqlExpression(expression)) { |
||||
return false; |
||||
} |
||||
String sql = String.format("SELECT rowid, * FROM %s WHERE %s ", CommonUtil.getClassName(clazz), |
||||
expression[0]); |
||||
sql = sql.replace("?", "%s"); |
||||
Object[] params = new String[expression.length - 1]; |
||||
for (int i = 0, len = params.length; i < len; i++) { |
||||
params[i] = String.format("'%s'", SqlUtil.encodeStr(expression[i + 1])); |
||||
} |
||||
sql = String.format(sql, params); |
||||
Cursor cursor = db.rawQuery(sql, null); |
||||
final boolean isExist = cursor.getCount() > 0; |
||||
closeCursor(cursor); |
||||
return isExist; |
||||
} |
||||
|
||||
/** |
||||
* 创建表 |
||||
* |
||||
* @param clazz 数据库实体 |
||||
*/ |
||||
void createTable(SQLiteDatabase db, Class clazz) { |
||||
db = checkDb(db); |
||||
List<Field> fields = CommonUtil.getAllFields(clazz); |
||||
if (fields != null && fields.size() > 0) { |
||||
//外键Map,在Sqlite3中foreign修饰的字段必须放在最后
|
||||
final List<Field> foreignArray = new ArrayList<>(); |
||||
StringBuilder sb = new StringBuilder(); |
||||
sb.append("CREATE TABLE IF NOT EXISTS ") |
||||
.append(CommonUtil.getClassName(clazz)) |
||||
.append(" ("); |
||||
for (Field field : fields) { |
||||
field.setAccessible(true); |
||||
if (SqlUtil.isIgnore(field)) { |
||||
continue; |
||||
} |
||||
Class<?> type = field.getType(); |
||||
sb.append(field.getName()); |
||||
if (type == String.class || type.isEnum()) { |
||||
sb.append(" VARCHAR"); |
||||
} else if (type == int.class || type == Integer.class) { |
||||
sb.append(" INTEGER"); |
||||
} else if (type == float.class || type == Float.class) { |
||||
sb.append(" FLOAT"); |
||||
} else if (type == double.class || type == Double.class) { |
||||
sb.append(" DOUBLE"); |
||||
} else if (type == long.class || type == Long.class) { |
||||
sb.append(" BIGINT"); |
||||
} else if (type == boolean.class || type == Boolean.class) { |
||||
sb.append(" BOOLEAN"); |
||||
} else if (type == java.util.Date.class || type == java.sql.Date.class) { |
||||
sb.append(" DATA"); |
||||
} else if (type == byte.class || type == Byte.class) { |
||||
sb.append(" BLOB"); |
||||
} else if (type == Map.class || type == List.class) { |
||||
sb.append(" TEXT"); |
||||
} else { |
||||
continue; |
||||
} |
||||
if (SqlUtil.isPrimary(field)) { |
||||
Primary pk = field.getAnnotation(Primary.class); |
||||
sb.append(" PRIMARY KEY"); |
||||
if (pk.autoincrement() && (type == int.class || type == Integer.class)) { |
||||
sb.append(" AUTOINCREMENT"); |
||||
} |
||||
} |
||||
|
||||
if (SqlUtil.isForeign(field)) { |
||||
foreignArray.add(field); |
||||
} |
||||
|
||||
if (SqlUtil.isNoNull(field)) { |
||||
sb.append(" NOT NULL"); |
||||
} |
||||
|
||||
if (SqlUtil.isDefault(field)) { |
||||
Default d = field.getAnnotation(Default.class); |
||||
if (!TextUtils.isEmpty(d.value())) { |
||||
sb.append(" ERROR ").append("'").append(d.value()).append("'"); |
||||
} |
||||
} |
||||
|
||||
if (SqlUtil.isUnique(field)) { |
||||
sb.append(" UNIQUE"); |
||||
} |
||||
|
||||
sb.append(","); |
||||
} |
||||
|
||||
for (Field field : foreignArray) { |
||||
Foreign foreign = field.getAnnotation(Foreign.class); |
||||
sb.append("FOREIGN KEY (") |
||||
.append(field.getName()) |
||||
.append(") REFERENCES ") |
||||
.append(CommonUtil.getClassName(foreign.parent())) |
||||
.append("(") |
||||
.append(foreign.column()) |
||||
.append(")"); |
||||
ActionPolicy update = foreign.onUpdate(); |
||||
ActionPolicy delete = foreign.onDelete(); |
||||
if (update != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON UPDATE ").append(update.function); |
||||
} |
||||
|
||||
if (delete != ActionPolicy.NO_ACTION) { |
||||
sb.append(" ON DELETE ").append(update.function); |
||||
} |
||||
sb.append(","); |
||||
} |
||||
|
||||
String str = sb.toString(); |
||||
str = str.substring(0, str.length() - 1) + ");"; |
||||
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; |
||||
} |
||||
} |
@ -1,161 +0,0 @@ |
||||
<?xml version="1.0" encoding="utf-8"?> |
||||
<aria> |
||||
<!--注意,修改该配置文件中的属性会覆盖代码中所设置的属性--> |
||||
|
||||
<!--Aria框架配置--> |
||||
<app> |
||||
<!--是否使用AriaCrashHandler来捕获异常,异常日志保存在:/mnt/sdcard/Android/data/{package_name}/files/log/--> |
||||
<useAriaCrashHandler value="true"/> |
||||
<!--设置Aria的日志级别,{@link ALog#LOG_LEVEL_VERBOSE}--> |
||||
<logLevel value="2"/> |
||||
<!-- 是否检查网络 true: 检查网络,false: 不检查网络--> |
||||
<netCheck value="true"/> |
||||
<!--除非无法使用注解,否则不建议使用广播来接受任务状态,true:使用广播接收任务状态,false:不适用广播接收状态 --> |
||||
<!-- http://aria.laoyuyu.me/aria_doc/api/use_broadcast.html --> |
||||
<useBroadcast value="true"/> |
||||
<!--断网的时候是否重试,true:断网也重试;false:断网不重试,直接走失败的回调--> |
||||
<notNetRetry value="false"/> |
||||
</app> |
||||
|
||||
|
||||
<!--普通下载任务--> |
||||
<download> |
||||
|
||||
<!--设置任务最大下载速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="0"/> |
||||
|
||||
<!-- |
||||
多线程下载是否使用块下载模式,{@code true}使用,{@code false}不使用 |
||||
注意: |
||||
1、使用分块模式,在I/O性能底下的手机上,合并文件需要的时间会更加长; |
||||
2、优点是使用多线程的块下载,初始化时,文件初始化时将不会预占用对应长度的空间; |
||||
3、只对新的多线程下载任务有效 |
||||
4、只对多线程的任务有效 |
||||
--> |
||||
<useBlock value="false"/> |
||||
|
||||
<!--设置下载线程数,下载线程数不能小于1 |
||||
注意: |
||||
1、线程下载数改变后,新的下载任务才会生效; |
||||
2、如果任务大小小于1m,该设置不会生效; |
||||
3、从3.4.1开始,如果线程数为1,文件初始化时将不再预占用对应长度的空间,下载多少byte,则占多大的空间; |
||||
对于3.4.1之前版本的未完成的老任务,依然采用原来的文件空间占用方式; |
||||
--> |
||||
<threadNum value="3"/> |
||||
|
||||
<!--设置下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="3"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="5"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--设置https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</download> |
||||
|
||||
<!--普通上传任务--> |
||||
<upload> |
||||
<!--设置任务最大上传速度,0表示不限速,单位为:kb--> |
||||
<maxSpeed value="0"/> |
||||
|
||||
<!--设置IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--设置写文件buff大小,该数值大小不能小于2048,数值变小,速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--设置上传队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="2"/> |
||||
|
||||
<!--设置上传失败,重试次数,默认为10--> |
||||
<reTryNum value="3"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒--> |
||||
<reTryInterval value="2000"/> |
||||
|
||||
<!--设置url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
</upload> |
||||
|
||||
<!-- 下载类组合任务 --> |
||||
<dGroup> |
||||
|
||||
<!--组合任务下载队列最大任务数, 默认为2--> |
||||
<maxTaskNum value="2"/> |
||||
|
||||
<!--设置下载失败,重试次数,默认为10--> |
||||
<reTryNum value="1"/> |
||||
|
||||
<!--设置重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<reTryInterval value="5000"/> |
||||
|
||||
<!--执行队列类型,见com.arialyy.aria.core.QueueMod,默认类型为wait--> |
||||
<queueMod value="wait"/> |
||||
|
||||
<!--进度更新更新间隔,默认1000毫秒--> |
||||
<updateInterval value="1000"/> |
||||
|
||||
|
||||
<!-- =============================以下为子任务的配置====================================--> |
||||
|
||||
<!--能同时下载的子任务最大任务数,默认3--> |
||||
<subMaxTaskNum value="5"/> |
||||
|
||||
<!--子任务下载失败时的重试次数,默认为5--> |
||||
<subReTryNum value="5"/> |
||||
|
||||
<!--子任务下载失败时的重试间隔,单位为毫秒,默认2000毫秒--> |
||||
<subReTryInterval value="5000"/> |
||||
|
||||
<!--子任务url连接超时时间,单位为毫秒,默认5000毫秒--> |
||||
<connectTimeOut value="5000"/> |
||||
|
||||
<!--子任务IO流读取时间,单位为毫秒,默认20000毫秒,该时间不能少于10000毫秒--> |
||||
<iOTimeOut value="10000"/> |
||||
|
||||
<!--子任务写文件buff大小,该数值大小不能小于2048,数值变小,下载速度会变慢--> |
||||
<buffSize value="8192"/> |
||||
|
||||
<!--子任务 https ca 证书信息;path 为assets目录下的CA证书完整路径,name 为CA证书名--> |
||||
<ca name="" path=""/> |
||||
|
||||
<!--子任务是否需要转换速度单位,转换完成后为:1b/s、1kb/s、1mb/s、1gb/s、1tb/s,如果不需要将返回byte长度--> |
||||
<convertSpeed value="true"/> |
||||
|
||||
<!--子任务的最大下载速度,0表示不限速,单位为:kb; --> |
||||
<maxSpeed value="0"/> |
||||
|
||||
</dGroup> |
||||
</aria> |
@ -0,0 +1,15 @@ |
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android" |
||||
android:width="128dp" |
||||
android:height="128dp" |
||||
android:viewportWidth="1024" |
||||
android:viewportHeight="1024"> |
||||
<path |
||||
android:pathData="M694.4,1.6L163.2,1.6C113.6,1.6 73.6,41.6 73.6,91.2v843.2c0,49.6 40,89.6 89.6,89.6h475.2c-20.8,-14.4 -33.6,-36.8 -33.6,-64L604.8,758.4c0,-41.6 32,-84.8 75.2,-84.8h209.6l1.6,-475.2L694.4,1.6zM307.2,545.6c-6.4,9.6 -14.4,16 -25.6,20.8 -11.2,4.8 -24,8 -38.4,8 -24,0 -41.6,-4.8 -54.4,-14.4 -12.8,-9.6 -20.8,-24 -24,-43.2l30.4,-4.8c1.6,12.8 8,20.8 16,27.2 8,6.4 19.2,9.6 33.6,9.6 14.4,0 22.4,-3.2 28.8,-9.6s9.6,-11.2 9.6,-17.6c0,-6.4 -3.2,-12.8 -9.6,-16 -4.8,-3.2 -14.4,-4.8 -30.4,-9.6 -22.4,-6.4 -38.4,-11.2 -46.4,-14.4 -8,-4.8 -16,-9.6 -19.2,-17.6 -4.8,-8 -6.4,-16 -6.4,-24s1.6,-16 4.8,-22.4c3.2,-6.4 8,-12.8 14.4,-17.6 4.8,-3.2 14.4,-9.6 22.4,-12.8 8,-3.2 17.6,-3.2 27.2,-3.2 14.4,0 22.4,1.6 33.6,6.4 6.4,3.2 19.2,12.8 24,20.8 4.8,6.4 8,16 11.2,27.2l-30.4,4.8c-1.6,-9.6 -4.8,-16 -11.2,-22.4 -6.4,-4.8 -16,-8 -27.2,-8 -14.4,0 -22.4,1.6 -27.2,4.8 -6.4,4.8 -11.2,11.2 -11.2,17.6 0,3.2 0,8 1.6,11.2 3.2,3.2 6.4,6.4 11.2,8 3.2,1.6 12.8,3.2 27.2,8 22.4,6.4 36.8,11.2 44.8,14.4 8,3.2 16,9.6 20.8,17.6 4.8,6.4 8,16 8,25.6 0,8 -3.2,17.6 -8,25.6zM465.6,417.6h-91.2v44.8h78.4v32h-78.4v80L336,574.4L336,385.6h129.6v32zM633.6,417.6h-56v156.8h-38.4v-156.8h-56v-32h150.4v32zM790.4,473.6c-4.8,8 -9.6,14.4 -16,19.2 -6.4,4.8 -12.8,8 -19.2,9.6 -9.6,1.6 -22.4,3.2 -40,3.2h-25.6v72h-38.4v-192h60.8c22.4,0 38.4,1.6 44.8,3.2 11.2,3.2 19.2,9.6 27.2,19.2s11.2,22.4 11.2,36.8c0,11.2 -1.6,20.8 -4.8,28.8zM694.4,196.8L694.4,51.2l145.6,145.6h-145.6z" |
||||
android:fillColor="@color/icon_color"/> |
||||
<path |
||||
android:pathData="M736,419.2c-4.8,-1.6 -14.4,-1.6 -27.2,-1.6h-19.2v52.8h20.8c14.4,0 25.6,-1.6 30.4,-3.2 4.8,-1.6 9.6,-4.8 11.2,-9.6 3.2,-4.8 4.8,-9.6 4.8,-14.4 0,-6.4 -1.6,-12.8 -6.4,-17.6 -3.2,-3.2 -9.6,-4.8 -14.4,-6.4zM795.2,867.2c-11.2,0 -22.4,9.6 -22.4,22.4 0,9.6 6.4,17.6 14.4,20.8v30.4h14.4v-30.4c8,-3.2 14.4,-11.2 14.4,-20.8 1.6,-12.8 -8,-22.4 -20.8,-22.4zM795.2,764.8c-16,0 -28.8,12.8 -28.8,28.8v28.8h57.6v-28.8c1.6,-16 -12.8,-28.8 -28.8,-28.8z" |
||||
android:fillColor="@color/icon_color"/> |
||||
<path |
||||
android:pathData="M892.8,705.6L699.2,705.6c-32,0 -57.6,25.6 -57.6,56L641.6,960c0,30.4 25.6,56 57.6,56h195.2c32,0 57.6,-25.6 57.6,-56L952,761.6c-1.6,-30.4 -27.2,-56 -59.2,-56zM883.2,955.2c0,8 -6.4,14.4 -14.4,14.4h-144c-8,0 -14.4,-6.4 -14.4,-14.4L710.4,832c0,-8 6.4,-14.4 14.4,-14.4h22.4v-28.8c0,-27.2 22.4,-51.2 51.2,-51.2 27.2,0 51.2,22.4 51.2,51.2v28.8h22.4c8,0 14.4,6.4 14.4,14.4v123.2z" |
||||
android:fillColor="@color/icon_color"/> |
||||
</vector> |
Loading…
Reference in new issue