This commit is contained in:
AriaLyy
2017-06-08 18:05:27 +08:00
parent 603a21fe43
commit 266c714535
25 changed files with 262 additions and 207 deletions

View File

@ -0,0 +1,11 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arialyy.aria">
<application
android:allowBackup="true"
android:label="@string/app_name"
android:supportsRtl="true">
</application>
</manifest>

View File

@ -0,0 +1,318 @@
/*
* 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;
import com.arialyy.aria.core.queue.DownloadTaskQueue;
import com.arialyy.aria.util.CommonUtil;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Properties;
/**
* Created by lyy on 2016/12/8.
* 信息配置
*/
class Configuration {
static final String DOWNLOAD_CONFIG_FILE = "/Aria/DownloadConfig.properties";
static final String UPLOAD_CONFIG_FILE = "/Aria/UploadConfig.properties";
static final String XML_FILE = "/Aria/aria_config.xml";
/**
* 通用配置
*/
public static class BaseConfig {
/**
* 旧任务数
*/
public static int oldMaxTaskNum = 2;
/**
* 是否发送任务广播true发送
*/
boolean isOpenBreadCast = false;
/**
* 任务队列最大任务数, 默认为2
*/
int maxTaskNum = 2;
/**
* 下载失败重试次数默认为10
*/
int reTryNum = 10;
/**
* 设置重试间隔单位为毫秒默认2000毫秒
*/
int reTryInterval = 2000;
/**
* 设置url连接超时时间单位为毫秒默认5000毫秒
*/
int connectTimeOut = 5000;
/**
* 是否需要转换速度单位转换完成后为1b/s、1k/s、1m/s、1g/s、1t/s如果不需要将返回byte长度
*/
boolean isConvertSpeed = false;
public boolean isOpenBreadCast() {
return isOpenBreadCast;
}
public BaseConfig setOpenBreadCast(boolean openBreadCast) {
isOpenBreadCast = openBreadCast;
saveKey("isOpenBreadCast", openBreadCast + "");
return this;
}
public int getMaxTaskNum() {
return maxTaskNum;
}
public BaseConfig setMaxTaskNum(int maxTaskNum) {
oldMaxTaskNum = this.maxTaskNum;
this.maxTaskNum = maxTaskNum;
saveKey("maxTaskNum", maxTaskNum + "");
DownloadTaskQueue.getInstance().setMaxTaskNum(maxTaskNum);
return this;
}
public int getReTryNum() {
return reTryNum;
}
public BaseConfig setReTryNum(int reTryNum) {
this.reTryNum = reTryNum;
saveKey("reTryNum", reTryNum + "");
return this;
}
public int getReTryInterval() {
return reTryInterval;
}
public BaseConfig setReTryInterval(int reTryInterval) {
this.reTryInterval = reTryInterval;
saveKey("reTryInterval", reTryInterval + "");
return this;
}
public boolean isConvertSpeed() {
return isConvertSpeed;
}
public BaseConfig setConvertSpeed(boolean convertSpeed) {
isConvertSpeed = convertSpeed;
saveKey("isConvertSpeed", isConvertSpeed + "");
return this;
}
public int getConnectTimeOut() {
return connectTimeOut;
}
public BaseConfig setConnectTimeOut(int connectTimeOut) {
this.connectTimeOut = connectTimeOut;
saveKey("connectTimeOut", connectTimeOut + "");
return this;
}
/**
* 保存key
*/
void saveKey(String key, String value) {
boolean isDownload = this instanceof DownloadConfig;
File file = new File(
AriaManager.APP.getFilesDir().getPath() + (isDownload ? DOWNLOAD_CONFIG_FILE
: UPLOAD_CONFIG_FILE));
if (file.exists()) {
Properties properties = CommonUtil.loadConfig(file);
properties.setProperty(key, value);
CommonUtil.saveConfig(file, properties);
}
}
/**
* 加载配置
*/
void loadConfig() {
boolean isDownload = this instanceof DownloadConfig;
File file = new File(
AriaManager.APP.getFilesDir().getPath() + (isDownload ? DOWNLOAD_CONFIG_FILE
: UPLOAD_CONFIG_FILE));
if (file.exists()) {
Properties properties = CommonUtil.loadConfig(file);
List<Field> fields = CommonUtil.getAllFields(getClass());
try {
for (Field field : fields) {
int m = field.getModifiers();
if (Modifier.isFinal(m) || Modifier.isStatic(m)) {
continue;
}
field.setAccessible(true);
String value = properties.getProperty(field.getName());
Class<?> type = field.getType();
if (type == String.class) {
field.set(this, value);
} else if (type == int.class || type == Integer.class) {
field.setInt(this, Integer.parseInt(value));
} else if (type == float.class || type == Float.class) {
field.setFloat(this, Float.parseFloat(value));
} else if (type == double.class || type == Double.class) {
field.setDouble(this, Double.parseDouble(value));
} else if (type == long.class || type == Long.class) {
field.setLong(this, Long.parseLong(value));
} else if (type == boolean.class || type == Boolean.class) {
field.setBoolean(this, Boolean.parseBoolean(value));
}
}
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 保存配置
*/
void saveAll() {
List<Field> fields = CommonUtil.getAllFields(getClass());
boolean isDownload = this instanceof DownloadConfig;
try {
File file = new File(
AriaManager.APP.getFilesDir().getPath() + (isDownload ? DOWNLOAD_CONFIG_FILE
: UPLOAD_CONFIG_FILE));
Properties properties = CommonUtil.loadConfig(file);
for (Field field : fields) {
int m = field.getModifiers();
if (Modifier.isFinal(m) || Modifier.isStatic(m)) {
continue;
}
field.setAccessible(true);
properties.setProperty(field.getName(), field.get(this) + "");
}
CommonUtil.saveConfig(file, properties);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
/**
* 下载配置
*/
public static class DownloadConfig extends BaseConfig {
/**
* 设置IO流读取时间单位为毫秒默认20000毫秒该时间不能少于10000毫秒
*/
int iOTimeOut = 20 * 1000;
/**
* 设置写文件buff大小该数值大小不能小于2048数值变小下载速度会变慢
*/
int buffSize = 8192;
/**
* 设置https ca 证书信息path 为assets目录下的CA证书完整路径
*/
String caPath;
/**
* name 为CA证书名
*/
String caName;
/**
* 下载线程数下载线程数不能小于1
*/
int threadNum = 3;
public int getIOTimeOut() {
return iOTimeOut;
}
public DownloadConfig setIOTimeOut(int iOTimeOut) {
this.iOTimeOut = iOTimeOut;
saveKey("iOTimeOut", iOTimeOut + "");
return this;
}
public int getBuffSize() {
return buffSize;
}
public DownloadConfig setBuffSize(int buffSize) {
this.buffSize = buffSize;
saveKey("buffSize", buffSize + "");
return this;
}
public String getCaPath() {
return caPath;
}
public DownloadConfig setCaPath(String caPath) {
this.caPath = caPath;
saveKey("caPath", caPath);
return this;
}
public String getCaName() {
return caName;
}
public DownloadConfig setCaName(String caName) {
this.caName = caName;
saveKey("caName", caName);
return this;
}
public int getThreadNum() {
return threadNum;
}
private DownloadConfig() {
loadConfig();
}
private static DownloadConfig INSTANCE = null;
static DownloadConfig getInstance() {
if (INSTANCE == null) {
synchronized (DownloadConfig.class) {
INSTANCE = new DownloadConfig();
}
}
return INSTANCE;
}
}
/**
* 上传配置
*/
public static class UploadConfig extends BaseConfig {
private UploadConfig() {
loadConfig();
}
private static UploadConfig INSTANCE = null;
static UploadConfig getInstance() {
if (INSTANCE == null) {
synchronized (DownloadConfig.class) {
INSTANCE = new UploadConfig();
}
}
return INSTANCE;
}
}
}

View File

@ -0,0 +1,67 @@
/*
* 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.scheduler;
import com.arialyy.aria.core.inf.ITask;
/**
* Created by Aria.Lao on 2017/6/7.
*/
public class AbsSchedulerListener<TASK extends ITask> implements ISchedulerListener<TASK> {
@Override public void onPre(TASK task) {
}
@Override public void onTaskPre(TASK task) {
}
@Override public void onTaskResume(TASK task) {
}
@Override public void onTaskStart(TASK task) {
}
@Override public void onTaskStop(TASK task) {
}
@Override public void onTaskCancel(TASK task) {
}
@Override public void onTaskFail(TASK task) {
}
@Override public void onTaskComplete(TASK task) {
}
@Override public void onTaskRunning(TASK task) {
}
public void onNoSupportBreakPoint(TASK task) {
}
public void setListener(Object obj) {
}
}

View File

@ -0,0 +1,249 @@
/*
* 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.upload;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.util.Log;
import com.arialyy.aria.core.Aria;
import com.arialyy.aria.core.AriaManager;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.inf.AbsTask;
import com.arialyy.aria.core.inf.IEntity;
import com.arialyy.aria.core.scheduler.DownloadSchedulers;
import com.arialyy.aria.core.scheduler.ISchedulers;
import com.arialyy.aria.util.CommonUtil;
import java.lang.ref.WeakReference;
/**
* Created by lyy on 2017/2/23.
* 上传任务
*/
public class UploadTask extends AbsTask<UploadTaskEntity, UploadEntity> {
private static final String TAG = "UploadTask";
private Handler mOutHandler;
private UploadUtil mUtil;
private UListener mListener;
private UploadTask(UploadTaskEntity taskEntity, Handler outHandler) {
mOutHandler = outHandler;
mEntity = taskEntity.uploadEntity;
mListener = new UListener(mOutHandler, this);
mUtil = new UploadUtil(taskEntity, mListener);
}
@Override public String getKey() {
return mEntity.getFilePath();
}
@Override public boolean isRunning() {
return mUtil.isRunning();
}
@Override public void start() {
if (mUtil.isRunning()) {
Log.d(TAG, "任务正在下载");
} else {
if (mListener == null) {
mListener = new UploadTask.UListener(mOutHandler, this);
}
mUtil.start();
}
}
@Override public void stop() {
}
@Override public void cancel() {
if (!mEntity.isComplete()) {
// 如果任务不是下载状态
mUtil.cancel();
mEntity.deleteData();
if (mOutHandler != null) {
mOutHandler.obtainMessage(DownloadSchedulers.CANCEL, this).sendToTarget();
}
//发送取消下载的广播
Intent intent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_CANCEL);
intent.putExtra(Aria.UPLOAD_ENTITY, mEntity);
AriaManager.APP.sendBroadcast(intent);
}
}
private static class UListener extends UploadListener {
WeakReference<Handler> outHandler;
WeakReference<UploadTask> task;
long lastLen = 0; //上一次发送长度
long lastTime = 0;
long INTERVAL_TIME = 1000; //1m更新周期
boolean isFirst = true;
UploadEntity uploadEntity;
Intent sendIntent;
boolean isOpenBroadCast = false;
boolean isConvertSpeed = false;
Context context;
UListener(Handler outHandle, UploadTask task) {
this.outHandler = new WeakReference<>(outHandle);
this.task = new WeakReference<>(task);
uploadEntity = this.task.get().getEntity();
sendIntent = CommonUtil.createIntent(AriaManager.APP.getPackageName(), Aria.ACTION_RUNNING);
sendIntent.putExtra(Aria.UPLOAD_ENTITY, uploadEntity);
context = AriaManager.APP;
final AriaManager manager = AriaManager.getInstance(context);
isOpenBroadCast = manager.getUploadConfig().isOpenBreadCast();
isConvertSpeed = manager.getUploadConfig().isConvertSpeed();
}
@Override public void onPre() {
uploadEntity.setState(IEntity.STATE_PRE);
sendIntent(Aria.ACTION_PRE, -1);
sendInState2Target(ISchedulers.PRE);
}
@Override public void onPostPre(long fileSize) {
super.onPostPre(fileSize);
uploadEntity.setFileSize(fileSize);
uploadEntity.setState(IEntity.STATE_POST_PRE);
sendIntent(Aria.ACTION_POST_PRE, 0);
sendInState2Target(ISchedulers.POST_PRE);
}
@Override public void onStart() {
uploadEntity.setState(IEntity.STATE_RUNNING);
sendIntent(Aria.ACTION_START, 0);
sendInState2Target(ISchedulers.START);
}
@Override public void onResume(long resumeLocation) {
uploadEntity.setState(DownloadEntity.STATE_RUNNING);
sendInState2Target(DownloadSchedulers.RESUME);
sendIntent(Aria.ACTION_RESUME, resumeLocation);
}
@Override public void onStop(long stopLocation) {
uploadEntity.setState(DownloadEntity.STATE_STOP);
handleSpeed(0);
sendInState2Target(DownloadSchedulers.STOP);
sendIntent(Aria.ACTION_STOP, stopLocation);
}
@Override public void onProgress(long currentLocation) {
if (System.currentTimeMillis() - lastTime > INTERVAL_TIME) {
long speed = currentLocation - lastLen;
sendIntent.putExtra(Aria.CURRENT_LOCATION, currentLocation);
sendIntent.putExtra(Aria.CURRENT_SPEED, speed);
lastTime = System.currentTimeMillis();
if (isFirst) {
speed = 0;
isFirst = false;
}
handleSpeed(speed);
uploadEntity.setCurrentProgress(currentLocation);
lastLen = currentLocation;
sendInState2Target(DownloadSchedulers.RUNNING);
AriaManager.APP.sendBroadcast(sendIntent);
}
}
@Override public void onCancel() {
uploadEntity.setState(DownloadEntity.STATE_CANCEL);
handleSpeed(0);
sendInState2Target(DownloadSchedulers.CANCEL);
sendIntent(Aria.ACTION_CANCEL, -1);
uploadEntity.deleteData();
}
@Override public void onComplete() {
uploadEntity.setState(DownloadEntity.STATE_COMPLETE);
uploadEntity.setComplete(true);
handleSpeed(0);
sendInState2Target(DownloadSchedulers.COMPLETE);
sendIntent(Aria.ACTION_COMPLETE, uploadEntity.getFileSize());
}
@Override public void onFail() {
uploadEntity.setFailNum(uploadEntity.getFailNum() + 1);
uploadEntity.setState(DownloadEntity.STATE_FAIL);
handleSpeed(0);
sendInState2Target(DownloadSchedulers.FAIL);
sendIntent(Aria.ACTION_FAIL, -1);
}
private void handleSpeed(long speed) {
if (isConvertSpeed) {
uploadEntity.setConvertSpeed(CommonUtil.formatFileSize(speed) + "/s");
} else {
uploadEntity.setSpeed(speed);
}
}
/**
* 将任务状态发送给下载器
*
* @param state {@link DownloadSchedulers#START}
*/
private void sendInState2Target(int state) {
if (outHandler.get() != null) {
outHandler.get().obtainMessage(state, task.get()).sendToTarget();
}
}
private void sendIntent(String action, long location) {
uploadEntity.setComplete(action.equals(Aria.ACTION_COMPLETE));
uploadEntity.setCurrentProgress(location);
uploadEntity.update();
if (!isOpenBroadCast) return;
Intent intent = CommonUtil.createIntent(context.getPackageName(), action);
intent.putExtra(Aria.UPLOAD_ENTITY, uploadEntity);
if (location != -1) {
intent.putExtra(Aria.CURRENT_LOCATION, location);
}
context.sendBroadcast(intent);
}
}
public static class Builder {
private Handler mOutHandler;
private UploadTaskEntity mTaskEntity;
private String mTargetName;
public void setOutHandler(ISchedulers outHandler) {
mOutHandler = new Handler(outHandler);
}
public void setUploadTaskEntity(UploadTaskEntity taskEntity) {
mTaskEntity = taskEntity;
}
public void setTargetName(String targetName) {
mTargetName = targetName;
}
public Builder() {
}
public UploadTask build() {
UploadTask task = new UploadTask(mTaskEntity, mOutHandler);
task.setTargetName(mTargetName);
return task;
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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.upload;
import com.arialyy.aria.core.inf.AbsTaskEntity;
import java.util.HashMap;
import java.util.Map;
/**
* Created by lyy on 2017/2/9.
* 上传任务实体
*/
public class UploadTaskEntity extends AbsTaskEntity {
public UploadEntity uploadEntity;
public String uploadUrl; //上传路径
public String attachment; //文件上传需要的key
public String contentType = "multipart/form-data"; //上传的文件类型
public String userAgent = "User-Agent";
public String charset = "utf-8";
/**
* 文件上传表单
*/
public Map<String, String> formFields = new HashMap<>();
public UploadTaskEntity(UploadEntity downloadEntity) {
this.uploadEntity = downloadEntity;
}
@Override public UploadEntity getEntity() {
return uploadEntity;
}
}

View File

@ -0,0 +1,28 @@
/*
* 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.exception;
/**
* Created by lyy on 2017/1/18.
* Aria 文件异常
*/
public class FileException extends NullPointerException {
private static final String ARIA_FILE_EXCEPTION = "Aria Exception:";
public FileException(String detailMessage) {
super(ARIA_FILE_EXCEPTION + detailMessage);
}
}