commit
5c6770bf5b
@ -0,0 +1,104 @@ |
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one |
||||
* or more contributor license agreements. See the NOTICE file |
||||
* distributed with this work for additional information |
||||
* regarding copyright ownership. The ASF licenses this file |
||||
* to you 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.common; |
||||
|
||||
/** |
||||
* 速度限制 |
||||
*/ |
||||
public class BandwidthLimiter { |
||||
public static int maxBandWith = 2 * 1024; //KB
|
||||
|
||||
/* KB */ |
||||
private static Long KB = 1024L; |
||||
/* The smallest count chunk length in bytes */ |
||||
private static Long CHUNK_LENGTH = 1024L; |
||||
/* How many bytes will be sent or receive */ |
||||
private int bytesWillBeSentOrReceive = 0; |
||||
/* When the last piece was sent or receive */ |
||||
private long lastPieceSentOrReceiveTick = System.nanoTime(); |
||||
/* Default rate is 1024KB/s */ |
||||
private int maxRate = 1024; |
||||
/* Time cost for sending CHUNK_LENGTH bytes in nanoseconds */ |
||||
private long timeCostPerChunk = (1000000000L * CHUNK_LENGTH) |
||||
/ (this.maxRate * KB); |
||||
|
||||
/** |
||||
* Initialize a BandwidthLimiter object with a certain rate. |
||||
* |
||||
* @param maxRate the download or upload speed in KBytes |
||||
*/ |
||||
public BandwidthLimiter(int maxRate, int threadNum) { |
||||
if (threadNum > 1) { |
||||
maxRate = maxRate / threadNum; |
||||
} |
||||
this.setMaxRate(maxRate); |
||||
} |
||||
|
||||
/** |
||||
* Set the max upload or download rate in KB/s. maxRate must be grater than |
||||
* 0. If maxRate is zero, it means there is no bandwidth limit. |
||||
* |
||||
* @param maxRate If maxRate is zero, it means there is no bandwidth limit. |
||||
* @throws IllegalArgumentException |
||||
*/ |
||||
public synchronized void setMaxRate(int maxRate) |
||||
throws IllegalArgumentException { |
||||
if (maxRate < 0) { |
||||
throw new IllegalArgumentException("maxRate can not less than 0"); |
||||
} |
||||
this.maxRate = maxRate; |
||||
if (maxRate == 0) { |
||||
this.timeCostPerChunk = 0; |
||||
} else { |
||||
this.timeCostPerChunk = (1000000000L * CHUNK_LENGTH) |
||||
/ (this.maxRate * KB); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Next 1 byte should do bandwidth limit. |
||||
*/ |
||||
public synchronized void limitNextBytes() { |
||||
this.limitNextBytes(1); |
||||
} |
||||
|
||||
/** |
||||
* Next len bytes should do bandwidth limit |
||||
*/ |
||||
public synchronized void limitNextBytes(int len) { |
||||
this.bytesWillBeSentOrReceive += len; |
||||
|
||||
/* We have sent CHUNK_LENGTH bytes */ |
||||
while (!Thread.currentThread().isInterrupted() && this.bytesWillBeSentOrReceive > CHUNK_LENGTH) { |
||||
long nowTick = System.nanoTime(); |
||||
long missedTime = this.timeCostPerChunk |
||||
- (nowTick - this.lastPieceSentOrReceiveTick); |
||||
if (missedTime > 0) { |
||||
try { |
||||
Thread.currentThread().sleep(missedTime / 1000000, |
||||
(int) (missedTime % 1000000)); |
||||
} catch (InterruptedException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
} |
||||
this.bytesWillBeSentOrReceive -= CHUNK_LENGTH; |
||||
this.lastPieceSentOrReceiveTick = nowTick |
||||
+ (missedTime > 0 ? missedTime : 0); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,145 @@ |
||||
/* |
||||
* 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.common; |
||||
|
||||
import android.os.Handler; |
||||
import com.arialyy.aria.core.AriaManager; |
||||
import com.arialyy.aria.core.inf.AbsEntity; |
||||
import com.arialyy.aria.core.inf.AbsTask; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.core.inf.IEntity; |
||||
import com.arialyy.aria.core.inf.IEventListener; |
||||
import com.arialyy.aria.core.inf.TaskSchedulerType; |
||||
import com.arialyy.aria.core.scheduler.ISchedulers; |
||||
import com.arialyy.aria.exception.BaseException; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import com.arialyy.aria.util.ErrorHelp; |
||||
import java.lang.ref.WeakReference; |
||||
|
||||
public abstract class BaseListener<ENTITY extends AbsEntity, TASK_ENTITY extends AbsTaskEntity<ENTITY>, TASK extends AbsTask<ENTITY, TASK_ENTITY>> |
||||
implements IEventListener { |
||||
private static final String TAG = "BaseListener"; |
||||
protected WeakReference<Handler> outHandler; |
||||
private int RUN_SAVE_INTERVAL = 5 * 1000; //5s保存一次下载中的进度
|
||||
private long mLastLen; //上一次发送长度
|
||||
private boolean isFirst = true; |
||||
private TASK mTask; |
||||
private long mLastSaveTime; |
||||
protected ENTITY mEntity; |
||||
protected TASK_ENTITY mTaskEntity; |
||||
protected boolean isConvertSpeed; |
||||
protected long mUpdateInterval; |
||||
protected AriaManager manager; |
||||
|
||||
protected BaseListener(TASK task, Handler outHandler) { |
||||
this.outHandler = new WeakReference<>(outHandler); |
||||
this.mTask = new WeakReference<>(task).get(); |
||||
this.mEntity = mTask.getTaskEntity().getEntity(); |
||||
this.mTaskEntity = mTask.getTaskEntity(); |
||||
manager = AriaManager.getInstance(AriaManager.APP); |
||||
mLastLen = mEntity.getCurrentProgress(); |
||||
mLastSaveTime = System.currentTimeMillis(); |
||||
} |
||||
|
||||
@Override public void onPre() { |
||||
saveData(IEntity.STATE_PRE, -1); |
||||
sendInState2Target(ISchedulers.PRE); |
||||
} |
||||
|
||||
@Override public void onStart(long startLocation) { |
||||
saveData(IEntity.STATE_RUNNING, startLocation); |
||||
sendInState2Target(ISchedulers.START); |
||||
} |
||||
|
||||
@Override public void onResume(long resumeLocation) { |
||||
saveData(IEntity.STATE_RUNNING, resumeLocation); |
||||
sendInState2Target(ISchedulers.RESUME); |
||||
} |
||||
|
||||
@Override public void onProgress(long currentLocation) { |
||||
mEntity.setCurrentProgress(currentLocation); |
||||
long speed = currentLocation - mLastLen; |
||||
if (isFirst) { |
||||
speed = 0; |
||||
isFirst = false; |
||||
} |
||||
handleSpeed(speed); |
||||
sendInState2Target(ISchedulers.RUNNING); |
||||
if (System.currentTimeMillis() - mLastSaveTime >= RUN_SAVE_INTERVAL) { |
||||
saveData(IEntity.STATE_RUNNING, currentLocation); |
||||
mLastSaveTime = System.currentTimeMillis(); |
||||
} |
||||
|
||||
mLastLen = currentLocation; |
||||
} |
||||
|
||||
@Override public void onStop(long stopLocation) { |
||||
saveData(mTask.getSchedulerType() == TaskSchedulerType.TYPE_STOP_AND_WAIT ? IEntity.STATE_WAIT |
||||
: IEntity.STATE_STOP, stopLocation); |
||||
handleSpeed(0); |
||||
sendInState2Target(ISchedulers.STOP); |
||||
} |
||||
|
||||
@Override public void onComplete() { |
||||
saveData(IEntity.STATE_COMPLETE, mEntity.getFileSize()); |
||||
handleSpeed(0); |
||||
sendInState2Target(ISchedulers.COMPLETE); |
||||
} |
||||
|
||||
@Override public void onCancel() { |
||||
saveData(IEntity.STATE_CANCEL, -1); |
||||
handleSpeed(0); |
||||
sendInState2Target(ISchedulers.CANCEL); |
||||
} |
||||
|
||||
@Override public void onFail(boolean needRetry, BaseException e) { |
||||
mEntity.setFailNum(mEntity.getFailNum() + 1); |
||||
saveData(IEntity.STATE_FAIL, mEntity.getCurrentProgress()); |
||||
handleSpeed(0); |
||||
mTask.needRetry = needRetry; |
||||
mTask.putExpand(AbsTask.ERROR_INFO_KEY, e); |
||||
sendInState2Target(ISchedulers.FAIL); |
||||
e.printStackTrace(); |
||||
ErrorHelp.saveError(e.getTag(), "", ALog.getExceptionString(e)); |
||||
} |
||||
|
||||
private void handleSpeed(long speed) { |
||||
if (mUpdateInterval != 1000) { |
||||
speed = speed * 1000 / mUpdateInterval; |
||||
} |
||||
if (isConvertSpeed) { |
||||
mEntity.setConvertSpeed(CommonUtil.formatFileSize(speed < 0 ? 0 : speed) + "/s"); |
||||
} |
||||
mEntity.setSpeed(speed < 0 ? 0 : speed); |
||||
|
||||
mEntity.setPercent((int) (mEntity.getFileSize() <= 0 ? 0 |
||||
: mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); |
||||
} |
||||
|
||||
/** |
||||
* 将任务状态发送给下载器 |
||||
* |
||||
* @param state {@link ISchedulers#START} |
||||
*/ |
||||
protected void sendInState2Target(int state) { |
||||
if (outHandler.get() != null) { |
||||
outHandler.get().obtainMessage(state, mTask).sendToTarget(); |
||||
} |
||||
} |
||||
|
||||
protected abstract void saveData(int state, long location); |
||||
} |
@ -0,0 +1,39 @@ |
||||
/* |
||||
* 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.common; |
||||
|
||||
import android.support.annotation.StringDef; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
|
||||
@StringDef({ |
||||
ProtocolType.Default, |
||||
ProtocolType.SSL, |
||||
ProtocolType.SSLv3, |
||||
ProtocolType.TLS, |
||||
ProtocolType.TLSv1, |
||||
ProtocolType.TLSv1_1, |
||||
ProtocolType.TLSv1_2 |
||||
}) |
||||
@Retention(RetentionPolicy.SOURCE) public @interface ProtocolType { |
||||
String Default = "TLS"; |
||||
String SSL = "SSL"; |
||||
String SSLv3 = "SSLv3"; |
||||
String TLS = "TLS"; |
||||
String TLSv1 = "TLSv1"; |
||||
String TLSv1_1 = "TLSv1.1"; |
||||
String TLSv1_2 = "TLSv1.2"; |
||||
} |
@ -1,78 +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.common; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.Iterator; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.ConcurrentHashMap; |
||||
|
||||
/** |
||||
* 线程任务管理器 |
||||
*/ |
||||
class ThreadTaskManager { |
||||
private static volatile ThreadTaskManager INSTANCE = null; |
||||
private Map<String, List<AbsThreadTask>> mThreadTasks = new ConcurrentHashMap<>(); |
||||
|
||||
private ThreadTaskManager() { |
||||
|
||||
} |
||||
|
||||
public static ThreadTaskManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (ThreadTaskManager.class) { |
||||
INSTANCE = new ThreadTaskManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
/** |
||||
* 添加单条线程记录 |
||||
* |
||||
* @param key 任务对应的key |
||||
* @param threadTask 线程任务 |
||||
*/ |
||||
public void addTask(String key, AbsThreadTask threadTask) { |
||||
if (mThreadTasks.get(key) == null) { |
||||
mThreadTasks.put(key, new ArrayList<AbsThreadTask>()); |
||||
} |
||||
mThreadTasks.get(key).add(threadTask); |
||||
} |
||||
|
||||
/** |
||||
* 删除对应的任务的线程记录 |
||||
* |
||||
* @param key 任务对应的key |
||||
*/ |
||||
public void removeTask(String key) { |
||||
for (Iterator<Map.Entry<String, List<AbsThreadTask>>> iter = mThreadTasks.entrySet().iterator(); |
||||
iter.hasNext(); ) { |
||||
Map.Entry<String, List<AbsThreadTask>> entry = iter.next(); |
||||
if (key.equals(entry.getKey())) { |
||||
List<AbsThreadTask> list = mThreadTasks.get(key); |
||||
if (list != null && !list.isEmpty()) { |
||||
list.clear(); |
||||
} |
||||
iter.remove(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
|
||||
} |
@ -0,0 +1,104 @@ |
||||
/* |
||||
* 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.common.ftp; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.FtpUrlEntity; |
||||
import com.arialyy.aria.core.common.ProtocolType; |
||||
import com.arialyy.aria.core.inf.AbsTarget; |
||||
import com.arialyy.aria.core.inf.ITarget; |
||||
|
||||
/** |
||||
* FTP SSL/TSL配置 |
||||
*/ |
||||
public class FTPSConfig<TARGET extends AbsTarget> implements ITarget { |
||||
private final String TAG = "FTPSConfig"; |
||||
private TARGET mTarget; |
||||
private FtpUrlEntity mUrlEntity; |
||||
|
||||
public FTPSConfig(TARGET target) { |
||||
mTarget = target; |
||||
mUrlEntity = mTarget.getTaskEntity().getUrlEntity(); |
||||
} |
||||
|
||||
/** |
||||
* 设置协议类型 |
||||
* |
||||
* @param protocol {@link ProtocolType} |
||||
*/ |
||||
public FTPSConfig setProtocol(@ProtocolType String protocol) { |
||||
if (TextUtils.isEmpty(protocol)) { |
||||
throw new NullPointerException("协议为空"); |
||||
} |
||||
mUrlEntity.protocol = protocol; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置证书别名 |
||||
* |
||||
* @param keyAlias 别名 |
||||
*/ |
||||
public FTPSConfig setAlias(String keyAlias) { |
||||
if (TextUtils.isEmpty(keyAlias)) { |
||||
throw new NullPointerException("别名为空"); |
||||
} |
||||
mUrlEntity.keyAlias = keyAlias; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置证书密码 |
||||
* |
||||
* @param storePass 私钥密码 |
||||
*/ |
||||
public FTPSConfig setStorePass(String storePass) { |
||||
if (TextUtils.isEmpty(storePass)) { |
||||
throw new NullPointerException("证书密码为空"); |
||||
} |
||||
mUrlEntity.storePass = storePass; |
||||
return this; |
||||
} |
||||
|
||||
/** |
||||
* 设置证书路径 |
||||
* |
||||
* @param storePath 证书路径 |
||||
*/ |
||||
public FTPSConfig setStorePath(String storePath) { |
||||
if (TextUtils.isEmpty(storePath)) { |
||||
throw new NullPointerException("证书路径为空"); |
||||
} |
||||
mUrlEntity.storePath = storePath; |
||||
return this; |
||||
} |
||||
|
||||
@Override public void start() { |
||||
mTarget.start(); |
||||
} |
||||
|
||||
@Override public void stop() { |
||||
mTarget.stop(); |
||||
} |
||||
|
||||
@Override public void resume() { |
||||
mTarget.resume(); |
||||
} |
||||
|
||||
@Override public void cancel() { |
||||
mTarget.cancel(); |
||||
} |
||||
} |
@ -0,0 +1,52 @@ |
||||
package com.arialyy.aria.core.common.ftp; |
||||
|
||||
import aria.apache.commons.net.ftp.FTPSClient; |
||||
import java.io.IOException; |
||||
import java.lang.reflect.Field; |
||||
import java.lang.reflect.Method; |
||||
import java.net.Socket; |
||||
import java.util.Locale; |
||||
import javax.net.ssl.SSLContext; |
||||
import javax.net.ssl.SSLSession; |
||||
import javax.net.ssl.SSLSessionContext; |
||||
import javax.net.ssl.SSLSocket; |
||||
|
||||
public class SSLSessionReuseFTPSClient extends FTPSClient { |
||||
|
||||
SSLSessionReuseFTPSClient(boolean b, SSLContext context) { |
||||
super(b, context); |
||||
} |
||||
|
||||
// adapted from:
|
||||
// https://trac.cyberduck.io/browser/trunk/ftp/src/main/java/ch/cyberduck/core/ftp/FTPClient.java
|
||||
@Override |
||||
protected void _prepareDataSocket_(final Socket socket) throws IOException { |
||||
if (socket instanceof SSLSocket) { |
||||
// Control socket is SSL
|
||||
final SSLSession session = ((SSLSocket) _socket_).getSession(); |
||||
if (session.isValid()) { |
||||
final SSLSessionContext context = session.getSessionContext(); |
||||
try { |
||||
//final Field sessionHostPortCache = context.getClass().getDeclaredField("sessionHostPortCache");
|
||||
final Field sessionHostPortCache = |
||||
context.getClass().getDeclaredField("sessionsByHostAndPort"); |
||||
sessionHostPortCache.setAccessible(true); |
||||
final Object cache = sessionHostPortCache.get(context); |
||||
final Method method = |
||||
cache.getClass().getDeclaredMethod("put", Object.class, Object.class); |
||||
method.setAccessible(true); |
||||
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostName(), |
||||
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||
method.invoke(cache, String.format("%s:%s", socket.getInetAddress().getHostAddress(), |
||||
String.valueOf(socket.getPort())).toLowerCase(Locale.ROOT), session); |
||||
} catch (NoSuchFieldException e) { |
||||
throw new IOException(e); |
||||
} catch (Exception e) { |
||||
throw new IOException(e); |
||||
} |
||||
} else { |
||||
throw new IOException("Invalid SSL Session"); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,86 @@ |
||||
/* |
||||
* 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.common.http; |
||||
|
||||
import android.text.TextUtils; |
||||
import com.arialyy.aria.core.common.RequestEnum; |
||||
import com.arialyy.aria.core.download.DownloadGroupTarget; |
||||
import com.arialyy.aria.core.download.DownloadGroupTaskEntity; |
||||
import com.arialyy.aria.core.download.DownloadTaskEntity; |
||||
import com.arialyy.aria.core.inf.AbsTarget; |
||||
import com.arialyy.aria.core.inf.IPostDelegate; |
||||
import com.arialyy.aria.core.inf.ITarget; |
||||
import com.arialyy.aria.util.ALog; |
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* post处理委托类 |
||||
*/ |
||||
public class PostDelegate<TARGET extends AbsTarget> implements IPostDelegate<TARGET>, ITarget { |
||||
private static final String TAG = "PostDelegate"; |
||||
private TARGET mTarget; |
||||
|
||||
public PostDelegate(TARGET target) { |
||||
mTarget = target; |
||||
mTarget.getTaskEntity().setRequestEnum(RequestEnum.POST); |
||||
} |
||||
|
||||
@Override public TARGET setParams(Map<String, String> params) { |
||||
mTarget.getTaskEntity().setParams(params); |
||||
if (mTarget instanceof DownloadGroupTarget) { |
||||
for (DownloadTaskEntity subTask : ((DownloadGroupTaskEntity) mTarget.getTaskEntity()).getSubTaskEntities()) { |
||||
subTask.setParams(params); |
||||
} |
||||
} |
||||
return mTarget; |
||||
} |
||||
|
||||
@Override public TARGET setParam(String key, String value) { |
||||
if (TextUtils.isEmpty(key) || TextUtils.isEmpty(value)) { |
||||
ALog.d(TAG, "key 或value 为空"); |
||||
return mTarget; |
||||
} |
||||
Map<String, String> params = mTarget.getTaskEntity().getParams(); |
||||
if (params == null) { |
||||
params = new HashMap<>(); |
||||
mTarget.getTaskEntity().setParams(params); |
||||
} |
||||
params.put(key, value); |
||||
if (mTarget instanceof DownloadGroupTarget) { |
||||
for (DownloadTaskEntity subTask : ((DownloadGroupTaskEntity) mTarget.getTaskEntity()).getSubTaskEntities()) { |
||||
subTask.setParams(params); |
||||
} |
||||
} |
||||
return mTarget; |
||||
} |
||||
|
||||
@Override public void start() { |
||||
mTarget.start(); |
||||
} |
||||
|
||||
@Override public void stop() { |
||||
mTarget.stop(); |
||||
} |
||||
|
||||
@Override public void resume() { |
||||
mTarget.resume(); |
||||
} |
||||
|
||||
@Override public void cancel() { |
||||
mTarget.cancel(); |
||||
} |
||||
} |
@ -0,0 +1,31 @@ |
||||
/* |
||||
* 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.inf; |
||||
|
||||
import java.util.Map; |
||||
|
||||
/** |
||||
* post 通用处理接口 |
||||
*/ |
||||
public interface IPostDelegate<TARGET extends ITarget> { |
||||
|
||||
/** |
||||
* 设置Post请求参数 |
||||
*/ |
||||
TARGET setParams(Map<String, String> params); |
||||
|
||||
TARGET setParam(String key, String value); |
||||
} |
@ -0,0 +1,22 @@ |
||||
package com.arialyy.aria.core.inf; |
||||
|
||||
import android.support.annotation.IntDef; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
|
||||
@IntDef({ |
||||
TaskSchedulerType.TYPE_DEFAULT, |
||||
TaskSchedulerType.TYPE_STOP_NOT_NEXT, |
||||
TaskSchedulerType.TYPE_STOP_AND_WAIT |
||||
}) |
||||
@Retention(RetentionPolicy.SOURCE) public @interface TaskSchedulerType { |
||||
int TYPE_DEFAULT = 1; |
||||
/** |
||||
* 停止当前任务并且不自动启动下一任务 |
||||
*/ |
||||
int TYPE_STOP_NOT_NEXT = 2; |
||||
/** |
||||
* 停止任务并让当前任务处于等待状态 |
||||
*/ |
||||
int TYPE_STOP_AND_WAIT = 3; |
||||
} |
@ -0,0 +1,135 @@ |
||||
/* |
||||
* 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.manager; |
||||
|
||||
import com.arialyy.aria.core.common.AbsThreadTask; |
||||
import com.arialyy.aria.core.inf.AbsTaskEntity; |
||||
import com.arialyy.aria.util.ALog; |
||||
import com.arialyy.aria.util.CommonUtil; |
||||
import java.util.HashMap; |
||||
import java.util.HashSet; |
||||
import java.util.Map; |
||||
import java.util.Set; |
||||
import java.util.concurrent.ExecutorService; |
||||
import java.util.concurrent.Executors; |
||||
import java.util.concurrent.Future; |
||||
|
||||
/** |
||||
* 线程管理器 |
||||
*/ |
||||
public class ThreadTaskManager { |
||||
private static volatile ThreadTaskManager INSTANCE = null; |
||||
private static final Object LOCK = new Object(); |
||||
private final String TAG = "ThreadTaskManager"; |
||||
private ExecutorService mExePool; |
||||
private Map<String, Set<Future>> mThreadTasks = new HashMap<>(); |
||||
|
||||
public static ThreadTaskManager getInstance() { |
||||
if (INSTANCE == null) { |
||||
synchronized (LOCK) { |
||||
INSTANCE = new ThreadTaskManager(); |
||||
} |
||||
} |
||||
return INSTANCE; |
||||
} |
||||
|
||||
private ThreadTaskManager() { |
||||
mExePool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); |
||||
} |
||||
|
||||
/** |
||||
* 启动线程任务 |
||||
* |
||||
* @param key 任务对应的key{@link AbsTaskEntity#getKey()} |
||||
* @param threadTask 线程任务{@link AbsThreadTask} |
||||
*/ |
||||
public synchronized void startThread(String key, AbsThreadTask threadTask) { |
||||
if (mExePool.isShutdown()) { |
||||
ALog.e(TAG, "线程池已经关闭"); |
||||
return; |
||||
} |
||||
key = getKey(key); |
||||
Set<Future> temp = mThreadTasks.get(key); |
||||
if (temp == null) { |
||||
temp = new HashSet<>(); |
||||
mThreadTasks.put(key, temp); |
||||
} |
||||
temp.add(mExePool.submit(threadTask)); |
||||
} |
||||
|
||||
/** |
||||
* 停止任务的所有线程 |
||||
* |
||||
* @param key 任务对应的key{@link AbsTaskEntity#getKey()} |
||||
*/ |
||||
public synchronized void stopTaskThread(String key) { |
||||
if (mExePool.isShutdown()) { |
||||
ALog.e(TAG, "线程池已经关闭"); |
||||
return; |
||||
} |
||||
key = getKey(key); |
||||
Set<Future> temp = mThreadTasks.get(key); |
||||
if (temp != null && temp.size() > 0) { |
||||
try { |
||||
for (Future future : temp) { |
||||
if (future.isDone() || future.isCancelled()) { |
||||
continue; |
||||
} |
||||
AbsThreadTask task = (AbsThreadTask) future.get(); |
||||
task.setInterrupted(true); |
||||
future.cancel(true); |
||||
} |
||||
} catch (Exception e) { |
||||
ALog.e(TAG, e); |
||||
} |
||||
temp.clear(); |
||||
} |
||||
mThreadTasks.remove(key); |
||||
} |
||||
|
||||
/** |
||||
* 重试线程任务 |
||||
* |
||||
* @param task 线程任务 |
||||
*/ |
||||
public synchronized void retryThread(AbsThreadTask task) { |
||||
if (mExePool.isShutdown()) { |
||||
ALog.e(TAG, "线程池已经关闭"); |
||||
return; |
||||
} |
||||
try { |
||||
if (task == null || task.isInterrupted()) { |
||||
ALog.e(TAG, "线程为空或线程已经中断"); |
||||
return; |
||||
} |
||||
} catch (Exception e) { |
||||
ALog.e(TAG, e); |
||||
return; |
||||
} |
||||
mExePool.submit(task); |
||||
} |
||||
|
||||
/** |
||||
* map中的key |
||||
* |
||||
* @param key 任务的key{@link AbsTaskEntity#getKey()} |
||||
* @return 转换后的map中的key |
||||
*/ |
||||
private String getKey(String key) { |
||||
return CommonUtil.getStrMd5(key); |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue