修复,文件长度放在header中,Aria不识别的问题;修复单任务下载时有可能出现的进度条错误问题
This commit is contained in:
@ -16,9 +16,9 @@
|
||||
package com.arialyy.aria.core.download;
|
||||
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.AbsGroupTarget;
|
||||
import com.arialyy.aria.core.inf.AbsDownloadTarget;
|
||||
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import com.arialyy.aria.orm.DbUtil;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.io.File;
|
||||
@ -29,7 +29,7 @@ import java.util.List;
|
||||
* Created by AriaL on 2017/6/29.
|
||||
*/
|
||||
public class DownloadGroupTarget
|
||||
extends AbsGroupTarget<DownloadGroupTarget, DownloadGroupEntity, DownloadGroupTaskEntity> {
|
||||
extends AbsDownloadTarget<DownloadGroupTarget, DownloadGroupEntity, DownloadGroupTaskEntity> {
|
||||
private List<String> mUrls = new ArrayList<>();
|
||||
private final String TAG = "DownloadGroupTarget";
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ package com.arialyy.aria.core.download;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTarget;
|
||||
import com.arialyy.aria.core.inf.AbsDownloadTarget;
|
||||
import com.arialyy.aria.core.inf.IEntity;
|
||||
import com.arialyy.aria.core.queue.DownloadTaskQueue;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
@ -29,7 +29,7 @@ import java.io.File;
|
||||
* https://github.com/AriaLyy/Aria
|
||||
*/
|
||||
public class DownloadTarget
|
||||
extends AbsNormalTarget<DownloadTarget, DownloadEntity, DownloadTaskEntity> {
|
||||
extends AbsDownloadTarget<DownloadTarget, DownloadEntity, DownloadTaskEntity> {
|
||||
|
||||
DownloadTarget(DownloadEntity entity, String targetName) {
|
||||
this(entity.getDownloadUrl(), targetName);
|
||||
@ -87,13 +87,6 @@ public class DownloadTarget
|
||||
super.setHighestPriority();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向后,新url的key,默认为location
|
||||
*/
|
||||
public DownloadTarget setRedirectUrlKey(String redirectUrlKey) {
|
||||
super._setRedirectUrlKey(redirectUrlKey);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
|
@ -85,7 +85,10 @@ class FileInfoThread implements Runnable {
|
||||
}
|
||||
|
||||
private void handleConnect(HttpURLConnection conn) throws IOException {
|
||||
int len = conn.getContentLength();
|
||||
long len = conn.getContentLength();
|
||||
if (len < 0) {
|
||||
len = Long.parseLong(conn.getHeaderField(mTaskEntity.contentLength));
|
||||
}
|
||||
int code = conn.getResponseCode();
|
||||
boolean isComplete = false;
|
||||
if (TextUtils.isEmpty(mEntity.getMd5Code())) {
|
||||
@ -93,6 +96,7 @@ class FileInfoThread implements Runnable {
|
||||
mEntity.setMd5Code(md5Code);
|
||||
}
|
||||
String disposition = conn.getHeaderField(mTaskEntity.dispositionKey);
|
||||
//Map<String, List<String>> headers = conn.getHeaderFields();
|
||||
if (!TextUtils.isEmpty(disposition)) {
|
||||
mEntity.setDisposition(disposition);
|
||||
if (disposition.contains(mTaskEntity.dispositionFileKey)) {
|
||||
|
@ -98,7 +98,7 @@ public class SimpleDownloadUtil implements IDownloadUtil, Runnable {
|
||||
}
|
||||
})).start();
|
||||
} else {
|
||||
new Downloader(mListener, mTaskEntity).startDownload();
|
||||
mDT.startDownload();
|
||||
}
|
||||
}
|
||||
}
|
@ -109,23 +109,15 @@ final class SingleThreadTask implements Runnable {
|
||||
//当前子线程的下载位置
|
||||
mChildCurrentLocation = mConfigEntity.START_LOCATION;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
if (CONSTANCE.isCancel) {
|
||||
break;
|
||||
}
|
||||
if (CONSTANCE.isStop) {
|
||||
break;
|
||||
}
|
||||
Thread.sleep(mSleepTime);
|
||||
if (CONSTANCE.isCancel) break;
|
||||
if (CONSTANCE.isStop) break;
|
||||
if (mSleepTime > 0) Thread.sleep(mSleepTime);
|
||||
file.write(buffer, 0, len);
|
||||
progress(len);
|
||||
}
|
||||
if (CONSTANCE.isCancel) {
|
||||
return;
|
||||
}
|
||||
if (CONSTANCE.isCancel) return;
|
||||
//停止状态不需要删除记录文件
|
||||
if (CONSTANCE.isStop) {
|
||||
return;
|
||||
}
|
||||
if (CONSTANCE.isStop) return;
|
||||
//支持断点的处理
|
||||
if (mConfigEntity.IS_SUPPORT_BREAK_POINT) {
|
||||
Log.i(TAG, "任务【"
|
||||
|
@ -19,14 +19,54 @@ import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.core.command.normal.NormalCmdFactory;
|
||||
import com.arialyy.aria.core.download.DownloadEntity;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
|
||||
/**
|
||||
* Created by lyy on 2017/2/28.
|
||||
*/
|
||||
public abstract class AbsNormalTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
public abstract class AbsDownloadTarget<TARGET extends AbsTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> {
|
||||
|
||||
/**
|
||||
* 如果你的下载链接的header中含有md5码信息,那么你可以通过设置key,来获取从header获取该md5码信息。
|
||||
* key默认值为:Content-MD5
|
||||
* 获取md5信息:{@link DownloadEntity#getMd5Code()}
|
||||
*/
|
||||
public void setHeaderMd5Key(String md5Key) {
|
||||
if (TextUtils.isEmpty(md5Key)) return;
|
||||
mTaskEntity.md5Key = md5Key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果你的文件长度是放在header中,那么你需要配置key来让Aria知道正确的文件长度
|
||||
* key默认值为:Content-Length
|
||||
*/
|
||||
public void setHeaderContentLengthKey(String contentLength) {
|
||||
if (TextUtils.isEmpty(contentLength)) return;
|
||||
mTaskEntity.contentLength = contentLength;
|
||||
}
|
||||
|
||||
/**
|
||||
* 如果你的下载链接的header中含有文件描述信息,那么你可以通过设置key,来获取从header获取该文件描述信息。
|
||||
* key默认值为:Content-Disposition
|
||||
* 获取文件描述信息:{@link DownloadEntity#getDisposition()}
|
||||
*/
|
||||
public void setHeaderDispositionKey(String dispositionKey) {
|
||||
if (TextUtils.isEmpty(dispositionKey)) return;
|
||||
mTaskEntity.dispositionKey = dispositionKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从文件描述信息{@link #setHeaderDispositionKey(String)}中含有文件名信息,你可以通过设置key来获取header中的文件名
|
||||
* key默认值为:attachment;filename
|
||||
* 获取文件名信息:{@link DownloadEntity#getServerFileName()}
|
||||
*/
|
||||
public void setHeaderDispositionFileKey(String dispositionFileKey) {
|
||||
if (TextUtils.isEmpty(dispositionFileKey)) return;
|
||||
mTaskEntity.dispositionFileKey = dispositionFileKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将任务设置为最高优先级任务,最高优先级任务有以下特点:
|
||||
* 1、在下载队列中,有且只有一个最高优先级任务
|
||||
@ -46,21 +86,14 @@ public abstract class AbsNormalTarget<TARGET extends AbsTarget, ENTITY extends A
|
||||
/**
|
||||
* 重定向后,新url的key,默认为location
|
||||
*/
|
||||
protected void _setRedirectUrlKey(String redirectUrlKey) {
|
||||
public void setRedirectUrlKey(String redirectUrlKey) {
|
||||
if (TextUtils.isEmpty(redirectUrlKey)) {
|
||||
Log.w("AbsNormalTarget", "重定向后,新url的key不能为null");
|
||||
Log.w("AbsDownloadTarget", "重定向后,新url的key不能为null");
|
||||
return;
|
||||
}
|
||||
mTaskEntity.redirectUrlKey = redirectUrlKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*/
|
||||
public void removeRecord() {
|
||||
mEntity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务文件大小
|
||||
*
|
||||
@ -70,7 +103,6 @@ public abstract class AbsNormalTarget<TARGET extends AbsTarget, ENTITY extends A
|
||||
return getSize();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取单位转换后的文件大小
|
||||
*
|
||||
@ -80,13 +112,6 @@ public abstract class AbsNormalTarget<TARGET extends AbsTarget, ENTITY extends A
|
||||
return getConvertSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载任务是否存在
|
||||
*/
|
||||
public boolean taskExists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加任务
|
||||
*/
|
@ -34,6 +34,20 @@ public abstract class AbsTarget<TARGET extends AbsTarget, ENTITY extends AbsEnti
|
||||
protected TASK_ENTITY mTaskEntity;
|
||||
protected String mTargetName;
|
||||
|
||||
/**
|
||||
* 删除记录
|
||||
*/
|
||||
public void removeRecord() {
|
||||
mEntity.deleteData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 任务是否存在
|
||||
*/
|
||||
public boolean taskExists() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取任务进度,如果任务存在,则返回当前进度
|
||||
*
|
||||
|
@ -43,17 +43,17 @@ public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
|
||||
public RequestEnum requestEnum = RequestEnum.GET;
|
||||
|
||||
/**
|
||||
* 从链接中含有的文件md5码信息所需要的key
|
||||
* 从header中含有的文件md5码信息所需要的key
|
||||
*/
|
||||
public String md5Key = "Content-MD5";
|
||||
|
||||
/**
|
||||
* 从链接中获取文件描述信息所需要的key
|
||||
* 从header中获取文件描述信息所需要的key
|
||||
*/
|
||||
public String dispositionKey = "Content-Disposition";
|
||||
|
||||
/**
|
||||
* 重定向后,从链接中获取新url所需要的key
|
||||
* 重定向后,从header中获取新url所需要的key
|
||||
*/
|
||||
public String redirectUrlKey = "location";
|
||||
|
||||
@ -62,6 +62,11 @@ public abstract class AbsTaskEntity<ENTITY extends AbsEntity> extends DbEntity {
|
||||
*/
|
||||
public String dispositionFileKey = "attachment;filename";
|
||||
|
||||
/**
|
||||
* 从header中含有的文件长度信息所需要的key
|
||||
*/
|
||||
public String contentLength = "Content-Length";
|
||||
|
||||
/**
|
||||
* 重定向链接
|
||||
*/
|
||||
|
@ -19,7 +19,7 @@ package com.arialyy.aria.core.inf;
|
||||
* Created by AriaL on 2017/6/29.
|
||||
* 任务组超类
|
||||
*/
|
||||
public abstract class AbsGroupTarget<TARGET extends AbsGroupTarget, ENTITY extends AbsGroupEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
public abstract class AbsUploadTarget<TARGET extends AbsUploadTarget, ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity>
|
||||
extends AbsTarget<TARGET, ENTITY, TASK_ENTITY> {
|
||||
|
||||
|
@ -16,7 +16,8 @@
|
||||
package com.arialyy.aria.core.upload;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import com.arialyy.aria.core.inf.AbsNormalTarget;
|
||||
import com.arialyy.aria.core.inf.AbsDownloadTarget;
|
||||
import com.arialyy.aria.core.inf.AbsUploadTarget;
|
||||
import com.arialyy.aria.core.queue.UploadTaskQueue;
|
||||
import com.arialyy.aria.orm.DbEntity;
|
||||
import java.util.regex.Pattern;
|
||||
@ -24,7 +25,7 @@ import java.util.regex.Pattern;
|
||||
/**
|
||||
* Created by lyy on 2017/2/28.
|
||||
*/
|
||||
public class UploadTarget extends AbsNormalTarget<UploadTarget, UploadEntity, UploadTaskEntity> {
|
||||
public class UploadTarget extends AbsUploadTarget<UploadTarget, UploadEntity, UploadTaskEntity> {
|
||||
|
||||
UploadTarget(String filePath, String targetName) {
|
||||
this.mTargetName = targetName;
|
||||
|
@ -29,10 +29,10 @@ import java.util.Map;
|
||||
* Created by lyy on 2017/4/6.
|
||||
* 数据库配置信息
|
||||
*/
|
||||
public class DBConfig {
|
||||
class DBConfig {
|
||||
static Map<String, Class> mapping = new HashMap<>();
|
||||
static String DB_NAME;
|
||||
static int VERSION = 10;
|
||||
static int VERSION = 11;
|
||||
|
||||
static {
|
||||
if (TextUtils.isEmpty(DB_NAME)) {
|
||||
|
@ -170,21 +170,21 @@ public class DbEntity {
|
||||
List<String> values = new ArrayList<>();
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (SqlHelper.ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
where.add(field.getName());
|
||||
Type type = field.getType();
|
||||
if (SqlHelper.isOneToOne(field)) {
|
||||
values.add(SqlHelper.getOneToOneParams(field));
|
||||
if (SqlUtil.isOneToOne(field)) {
|
||||
values.add(SqlUtil.getOneToOneParams(field));
|
||||
} else if (type == List.class) {
|
||||
if (SqlHelper.isOneToMany(field)) {
|
||||
values.add(SqlHelper.getOneToManyElementParams(field));
|
||||
if (SqlUtil.isOneToMany(field)) {
|
||||
values.add(SqlUtil.getOneToManyElementParams(field));
|
||||
} else {
|
||||
values.add(SqlHelper.list2Str(this, field));
|
||||
values.add(SqlUtil.list2Str(this, field));
|
||||
}
|
||||
} else if (type == Map.class) {
|
||||
values.add(SqlHelper.map2Str((Map<String, String>) field.get(this)));
|
||||
values.add(SqlUtil.map2Str((Map<String, String>) field.get(this)));
|
||||
} else {
|
||||
values.add(field.get(this) + "");
|
||||
}
|
||||
|
@ -27,12 +27,9 @@ import com.arialyy.aria.core.AriaManager;
|
||||
import com.arialyy.aria.util.CheckUtil;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@ -57,7 +54,17 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
if (INSTANCE == null) {
|
||||
synchronized (AriaManager.LOCK) {
|
||||
INSTANCE = new SqlHelper(context.getApplicationContext());
|
||||
checkTable(INSTANCE.getWritableDatabase());
|
||||
SQLiteDatabase db = INSTANCE.getWritableDatabase();
|
||||
db = checkDb(db);
|
||||
Set<String> tables = DBConfig.mapping.keySet();
|
||||
for (String tableName : tables) {
|
||||
Class clazz = null;
|
||||
clazz = DBConfig.mapping.get(tableName);
|
||||
|
||||
if (!tableExists(db, clazz)) {
|
||||
createTable(db, clazz, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return INSTANCE;
|
||||
@ -86,8 +93,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
|
||||
/**
|
||||
* 处理数据库升级
|
||||
*
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
private void handleDbUpdate(SQLiteDatabase db) {
|
||||
if (db == null) {
|
||||
@ -148,7 +153,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
if (fields != null && fields.size() > 0) {
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
count++;
|
||||
@ -157,22 +162,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查数据库表,如果配置的表不存在,则创建新表
|
||||
*/
|
||||
static synchronized void checkTable(SQLiteDatabase db) {
|
||||
db = checkDb(db);
|
||||
Set<String> tables = DBConfig.mapping.keySet();
|
||||
for (String tableName : tables) {
|
||||
Class clazz = null;
|
||||
clazz = DBConfig.mapping.get(tableName);
|
||||
|
||||
if (!tableExists(db, clazz)) {
|
||||
createTable(db, clazz, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 条件查寻数据
|
||||
*/
|
||||
@ -286,7 +275,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
int i = 0;
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (SqlHelper.ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
@ -295,15 +284,15 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
sb.append(field.getName()).append("='");
|
||||
Type type = field.getType();
|
||||
if (type == Map.class) {
|
||||
value = map2Str((Map<String, String>) field.get(dbEntity));
|
||||
value = SqlUtil.map2Str((Map<String, String>) field.get(dbEntity));
|
||||
} else if (type == List.class) {
|
||||
if (isOneToMany(field)) {
|
||||
value = getOneToManyElementParams(field);
|
||||
if (SqlUtil.isOneToMany(field)) {
|
||||
value = SqlUtil.getOneToManyElementParams(field);
|
||||
} else {
|
||||
value = list2Str(dbEntity, field);
|
||||
value = SqlUtil.list2Str(dbEntity, field);
|
||||
}
|
||||
} else if (isOneToOne(field)) {
|
||||
value = getOneToOneParams(field);
|
||||
} else if (SqlUtil.isOneToOne(field)) {
|
||||
value = SqlUtil.getOneToOneParams(field);
|
||||
} else {
|
||||
Object obj = field.get(dbEntity);
|
||||
value = obj == null ? "" : obj.toString();
|
||||
@ -336,11 +325,10 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
int i = 0;
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
//sb.append(getFieldName(field.getType(), field));
|
||||
sb.append(field.getName());
|
||||
i++;
|
||||
}
|
||||
@ -349,22 +337,22 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
try {
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
sb.append(i > 0 ? ", " : "");
|
||||
sb.append("'");
|
||||
Type type = field.getType();
|
||||
if (type == Map.class) {
|
||||
sb.append(map2Str((Map<String, String>) field.get(dbEntity)));
|
||||
sb.append(SqlUtil.map2Str((Map<String, String>) field.get(dbEntity)));
|
||||
} else if (type == List.class) {
|
||||
if (isOneToMany(field)) {
|
||||
sb.append(getOneToManyElementParams(field));
|
||||
if (SqlUtil.isOneToMany(field)) {
|
||||
sb.append(SqlUtil.getOneToManyElementParams(field));
|
||||
} else {
|
||||
sb.append(list2Str(dbEntity, field));
|
||||
sb.append(SqlUtil.list2Str(dbEntity, field));
|
||||
}
|
||||
} else if (isOneToOne(field)) {
|
||||
sb.append(getOneToOneParams(field));
|
||||
} else if (SqlUtil.isOneToOne(field)) {
|
||||
sb.append(SqlUtil.getOneToOneParams(field));
|
||||
} else {
|
||||
sb.append(field.get(dbEntity));
|
||||
}
|
||||
@ -381,104 +369,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
close(db);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一对一参数
|
||||
*/
|
||||
static String getOneToOneParams(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
if (oneToOne == null) {
|
||||
throw new IllegalArgumentException("@OneToOne注解的对象必须要有@Primary注解的字段");
|
||||
}
|
||||
return oneToOne.table().getName() + "$$" + oneToOne.key();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取List一对多参数
|
||||
*
|
||||
* @param field list反射字段
|
||||
*/
|
||||
static String getOneToManyElementParams(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
if (oneToMany == null) {
|
||||
throw new IllegalArgumentException("一对多元素必须被@OneToMany注解");
|
||||
}
|
||||
//关联的表名
|
||||
String tableName = oneToMany.table().getName();
|
||||
//关联的字段
|
||||
String key = oneToMany.key();
|
||||
return tableName + "$$" + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表数据转字符串
|
||||
*
|
||||
* @param field list反射字段
|
||||
*/
|
||||
static String list2Str(DbEntity dbEntity, Field field) throws IllegalAccessException {
|
||||
NormalList normalList = field.getAnnotation(NormalList.class);
|
||||
if (normalList == null) {
|
||||
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
|
||||
}
|
||||
List list = (List) field.get(dbEntity);
|
||||
if (list == null || list.isEmpty()) return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object aList : list) {
|
||||
sb.append(aList).append("$$");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转列表
|
||||
*
|
||||
* @param str 数据库中的字段
|
||||
* @return 如果str为null,则返回null
|
||||
*/
|
||||
private static List str2List(String str, Field field) {
|
||||
NormalList normalList = field.getAnnotation(NormalList.class);
|
||||
if (normalList == null) {
|
||||
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
|
||||
}
|
||||
if (TextUtils.isEmpty(str)) return null;
|
||||
String[] datas = str.split("$$");
|
||||
List list = new ArrayList();
|
||||
String type = normalList.clazz().getName();
|
||||
for (String data : datas) {
|
||||
list.add(checkData(data, type));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
private static Object checkData(String type, String data) {
|
||||
switch (type) {
|
||||
case "String":
|
||||
return data;
|
||||
case "int":
|
||||
case "Integer":
|
||||
return Integer.parseInt(data);
|
||||
case "double":
|
||||
case "Double":
|
||||
return Double.parseDouble(data);
|
||||
case "float":
|
||||
case "Float":
|
||||
return Float.parseFloat(data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找class的主键字段
|
||||
*
|
||||
* @return 返回主键字段名
|
||||
*/
|
||||
private static String getPrimaryName(Class<? extends DbEntity> clazz) {
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
for (Field field : fields) {
|
||||
if (isPrimary(field)) return field.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找表是否存在
|
||||
*
|
||||
@ -526,7 +416,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
.append("(");
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
Class<?> type = field.getType();
|
||||
@ -534,7 +424,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
if (type == String.class
|
||||
|| type == Map.class
|
||||
|| type == List.class
|
||||
|| isOneToOne(field)
|
||||
|| SqlUtil.isOneToOne(field)
|
||||
|| type.isEnum()) {
|
||||
sb.append(" varchar");
|
||||
} else if (type == int.class || type == Integer.class) {
|
||||
@ -554,7 +444,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (isPrimary(field)) {
|
||||
if (SqlUtil.isPrimary(field)) {
|
||||
//sb.append(" PRIMARY KEY");
|
||||
sb.append(" NOT NULL");
|
||||
}
|
||||
@ -614,7 +504,7 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
T entity = clazz.newInstance();
|
||||
for (Field field : fields) {
|
||||
field.setAccessible(true);
|
||||
if (ignoreField(field)) {
|
||||
if (SqlUtil.ignoreField(field)) {
|
||||
continue;
|
||||
}
|
||||
Class<?> type = field.getType();
|
||||
@ -637,12 +527,12 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
} else if (type == byte[].class) {
|
||||
field.set(entity, cursor.getBlob(column));
|
||||
} else if (type == Map.class) {
|
||||
field.set(entity, str2Map(cursor.getString(column)));
|
||||
field.set(entity, SqlUtil.str2Map(cursor.getString(column)));
|
||||
} else if (type == List.class) {
|
||||
String value = cursor.getString(column);
|
||||
if (isOneToMany(field)) {
|
||||
if (SqlUtil.isOneToMany(field)) {
|
||||
//主键字段
|
||||
String primaryKey = getPrimaryName(clazz);
|
||||
String primaryKey = SqlUtil.getPrimaryName(clazz);
|
||||
if (TextUtils.isEmpty(primaryKey)) {
|
||||
throw new IllegalArgumentException("List中的元素对象必须需要@Primary注解的字段");
|
||||
}
|
||||
@ -654,10 +544,10 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
if (list == null) continue;
|
||||
field.set(entity, findForeignData(db, primaryData, value));
|
||||
} else {
|
||||
field.set(entity, str2List(value, field));
|
||||
field.set(entity, SqlUtil.str2List(value, field));
|
||||
}
|
||||
} else if (isOneToOne(field)) {
|
||||
String primaryKey = getPrimaryName(clazz);
|
||||
} else if (SqlUtil.isOneToOne(field)) {
|
||||
String primaryKey = SqlUtil.getPrimaryName(clazz);
|
||||
if (TextUtils.isEmpty(primaryKey)) {
|
||||
throw new IllegalArgumentException("@OneToOne的注解对象必须需要@Primary注解的字段");
|
||||
}
|
||||
@ -696,41 +586,6 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
return findData(db, params[0], params[1] + "=?", primary);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转Map,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
private static Map<String, String> str2Map(String str) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
return map;
|
||||
}
|
||||
String[] element = str.split(",");
|
||||
for (String data : element) {
|
||||
String[] s = data.split("\\$");
|
||||
map.put(s[0], s[1]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转字符串,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
static String map2Str(Map<String, String> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<String> keys = map.keySet();
|
||||
for (String key : keys) {
|
||||
sb.append(key).append("$").append(map.get(key)).append(",");
|
||||
}
|
||||
String str = sb.toString();
|
||||
return TextUtils.isEmpty(str) ? str : str.substring(0, str.length() - 1);
|
||||
}
|
||||
|
||||
private static void close(SQLiteDatabase db) {
|
||||
//if (db != null && db.isOpen()) db.close();
|
||||
}
|
||||
@ -741,42 +596,4 @@ final class SqlHelper extends SQLiteOpenHelper {
|
||||
}
|
||||
return db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true 忽略该字段
|
||||
*/
|
||||
static boolean ignoreField(Field field) {
|
||||
// field.isSynthetic(), 使用as热启动App时,AS会自动给你的class添加change字段
|
||||
Ignore ignore = field.getAnnotation(Ignore.class);
|
||||
int modifiers = field.getModifiers();
|
||||
return (ignore != null && ignore.value())
|
||||
|| field.getName().equals("rowID")
|
||||
|| field.isSynthetic()
|
||||
|| Modifier.isStatic(modifiers)
|
||||
|| Modifier.isFinal(modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否一对多注解
|
||||
*/
|
||||
static boolean isOneToMany(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
return oneToMany != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是一对一注解
|
||||
*/
|
||||
static boolean isOneToOne(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
return oneToOne != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是主键
|
||||
*/
|
||||
static boolean isPrimary(Field field) {
|
||||
Primary pk = field.getAnnotation(Primary.class);
|
||||
return pk != null;
|
||||
}
|
||||
}
|
208
Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java
Normal file
208
Aria/src/main/java/com/arialyy/aria/orm/SqlUtil.java
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
* 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.sqlite.SQLiteDatabase;
|
||||
import android.text.TextUtils;
|
||||
import com.arialyy.aria.util.CommonUtil;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Aria.Lao on 2017/7/24.
|
||||
* sql工具
|
||||
*/
|
||||
final class SqlUtil {
|
||||
|
||||
/**
|
||||
* 获取一对一参数
|
||||
*/
|
||||
static String getOneToOneParams(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
if (oneToOne == null) {
|
||||
throw new IllegalArgumentException("@OneToOne注解的对象必须要有@Primary注解的字段");
|
||||
}
|
||||
return oneToOne.table().getName() + "$$" + oneToOne.key();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取List一对多参数
|
||||
*
|
||||
* @param field list反射字段
|
||||
*/
|
||||
static String getOneToManyElementParams(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
if (oneToMany == null) {
|
||||
throw new IllegalArgumentException("一对多元素必须被@OneToMany注解");
|
||||
}
|
||||
//关联的表名
|
||||
String tableName = oneToMany.table().getName();
|
||||
//关联的字段
|
||||
String key = oneToMany.key();
|
||||
return tableName + "$$" + key;
|
||||
}
|
||||
|
||||
/**
|
||||
* 列表数据转字符串
|
||||
*
|
||||
* @param field list反射字段
|
||||
*/
|
||||
static String list2Str(DbEntity dbEntity, Field field) throws IllegalAccessException {
|
||||
NormalList normalList = field.getAnnotation(NormalList.class);
|
||||
if (normalList == null) {
|
||||
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
|
||||
}
|
||||
List list = (List) field.get(dbEntity);
|
||||
if (list == null || list.isEmpty()) return "";
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Object aList : list) {
|
||||
sb.append(aList).append("$$");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转列表
|
||||
*
|
||||
* @param str 数据库中的字段
|
||||
* @return 如果str为null,则返回null
|
||||
*/
|
||||
static List str2List(String str, Field field) {
|
||||
NormalList normalList = field.getAnnotation(NormalList.class);
|
||||
if (normalList == null) {
|
||||
throw new IllegalArgumentException("List中元素必须被@NormalList注解");
|
||||
}
|
||||
if (TextUtils.isEmpty(str)) return null;
|
||||
String[] datas = str.split("$$");
|
||||
List list = new ArrayList();
|
||||
String type = normalList.clazz().getName();
|
||||
for (String data : datas) {
|
||||
list.add(checkData(data, type));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转Map,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
static Map<String, String> str2Map(String str) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
if (TextUtils.isEmpty(str)) {
|
||||
return map;
|
||||
}
|
||||
String[] element = str.split(",");
|
||||
for (String data : element) {
|
||||
String[] s = data.split("\\$");
|
||||
map.put(s[0], s[1]);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map转字符串,只支持
|
||||
* <pre>
|
||||
* {@code Map<String, String>}
|
||||
* </pre>
|
||||
*/
|
||||
static String map2Str(Map<String, String> map) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
Set<String> keys = map.keySet();
|
||||
for (String key : keys) {
|
||||
sb.append(key).append("$").append(map.get(key)).append(",");
|
||||
}
|
||||
String str = sb.toString();
|
||||
return TextUtils.isEmpty(str) ? str : str.substring(0, str.length() - 1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @return true 忽略该字段
|
||||
*/
|
||||
static boolean ignoreField(Field field) {
|
||||
// field.isSynthetic(), 使用as热启动App时,AS会自动给你的class添加change字段
|
||||
Ignore ignore = field.getAnnotation(Ignore.class);
|
||||
int modifiers = field.getModifiers();
|
||||
return (ignore != null && ignore.value())
|
||||
|| field.getName().equals("rowID")
|
||||
|| field.isSynthetic()
|
||||
|| Modifier.isStatic(modifiers)
|
||||
|| Modifier.isFinal(modifiers);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否一对多注解
|
||||
*/
|
||||
static boolean isOneToMany(Field field) {
|
||||
OneToMany oneToMany = field.getAnnotation(OneToMany.class);
|
||||
return oneToMany != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是一对一注解
|
||||
*/
|
||||
static boolean isOneToOne(Field field) {
|
||||
OneToOne oneToOne = field.getAnnotation(OneToOne.class);
|
||||
return oneToOne != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断是否是主键
|
||||
*/
|
||||
static boolean isPrimary(Field field) {
|
||||
Primary pk = field.getAnnotation(Primary.class);
|
||||
return pk != null;
|
||||
}
|
||||
|
||||
private static Object checkData(String type, String data) {
|
||||
switch (type) {
|
||||
case "String":
|
||||
return data;
|
||||
case "int":
|
||||
case "Integer":
|
||||
return Integer.parseInt(data);
|
||||
case "double":
|
||||
case "Double":
|
||||
return Double.parseDouble(data);
|
||||
case "float":
|
||||
case "Float":
|
||||
return Float.parseFloat(data);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查找class的主键字段
|
||||
*
|
||||
* @return 返回主键字段名
|
||||
*/
|
||||
static String getPrimaryName(Class<? extends DbEntity> clazz) {
|
||||
List<Field> fields = CommonUtil.getAllFields(clazz);
|
||||
for (Field field : fields) {
|
||||
if (isPrimary(field)) return field.getName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
@ -41,7 +41,8 @@ public class SingleTaskActivity extends BaseActivity<ActivitySingleBinding> {
|
||||
private static final String DOWNLOAD_URL =
|
||||
//"http://kotlinlang.org/docs/kotlin-docs.pdf";
|
||||
//"https://atom-installer.github.com/v1.13.0/AtomSetup.exe?s=1484074138&ext=.exe";
|
||||
"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
|
||||
//"http://static.gaoshouyou.com/d/22/94/822260b849944492caadd2983f9bb624.apk";
|
||||
"https://d.pcs.baidu.com/file/7330524ec2affe80914cd306e16fd0ac?fid=3965548007-250528-918323254381453&time=1500859695&rt=sh&sign=FDTAERVY-DCb740ccc5511e5e8fedcff06b081203-7u09%2BsA23HuD53M3bCJpH1HVp3o%3D&expires=8h&chkv=1&chkbd=0&chkpc=et&dp-logid=4740488282618906999&dp-callid=0&r=714336419";
|
||||
//"http://down2.xiaoshuofuwuqi.com/d/file/filetxt/20170608/14/%BA%DA%CE%D7%CA%A6%E1%C8%C6%F0.txt";
|
||||
//"http://tinghuaapp.oss-cn-shanghai.aliyuncs.com/20170612201739607815";
|
||||
//"http://static.gaoshouyou.com/d/36/69/2d3699acfa69e9632262442c46516ad8.apk";
|
||||
|
Reference in New Issue
Block a user