增加获取执行中的任务api

增加获取剩余时间的api
修复重构loader导致的m3u8问题
This commit is contained in:
laoyuyu
2020-01-07 21:56:35 +08:00
parent b1a2f232fa
commit 432ae1c145
37 changed files with 495 additions and 128 deletions

View File

@@ -0,0 +1,99 @@
/*
* 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.m3u8.live;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.m3u8.M3U8TaskOption;
import com.arialyy.aria.util.RecordUtil;
import java.util.ArrayList;
/**
* 直播m3u8文件处理器
*/
final class LiveRecordHandler extends RecordHandler {
private M3U8TaskOption mOption;
LiveRecordHandler(AbsTaskWrapper wrapper) {
super(wrapper);
}
public void setOption(M3U8TaskOption option) {
mOption = option;
}
@Override public void onPre() {
super.onPre();
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_DOWNLOAD);
}
/**
* @deprecated 直播文件不需要处理任务记录
*/
@Deprecated
@Override public void handlerTaskRecord(TaskRecord record) {
if (record.threadRecords == null) {
record.threadRecords = new ArrayList<>();
}
}
/**
* @deprecated 交由{@link #createThreadRecord(TaskRecord, String, int)} 处理
*/
@Override
@Deprecated
public ThreadRecord createThreadRecord(TaskRecord record, int threadId, long startL, long endL) {
return null;
}
/**
* 创建线程记录
*
* @param taskRecord 任务记录
* @param tsUrl ts下载地址
* @param threadId 线程id
*/
ThreadRecord createThreadRecord(TaskRecord taskRecord, String tsUrl, int threadId) {
ThreadRecord tr = new ThreadRecord();
tr.taskKey = taskRecord.filePath;
tr.isComplete = false;
tr.tsUrl = tsUrl;
tr.threadType = getEntity().getTaskType();
tr.threadId = threadId;
tr.startLocation = 0;
taskRecord.threadRecords.add(tr);
return tr;
}
@Override public TaskRecord createTaskRecord(int threadNum) {
TaskRecord record = new TaskRecord();
record.fileName = getEntity().getFileName();
record.filePath = getEntity().getFilePath();
record.threadRecords = new ArrayList<>();
record.threadNum = threadNum;
record.isBlock = true;
record.taskType = getEntity().getTaskType();
record.bandWidth = mOption.getBandWidth();
return record;
}
@Override public int initTaskThreadNum() {
return 1;
}
}

View File

@@ -15,6 +15,7 @@
*/
package com.arialyy.aria.m3u8.live;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -80,7 +81,11 @@ final class LiveStateManager implements IThreadStateManager {
msg.getData().getString(ISchedulers.DATA_M3U8_PEER_PATH), peerIndex);
break;
case STATE_RUNNING:
mProgress += (long) msg.obj;
Bundle b = msg.getData();
if (b != null) {
long len = b.getLong(IThreadStateManager.DATA_ADD_LEN, 0);
mProgress += len;
}
break;
case STATE_FAIL:
mLoader.notifyLock(false, peerIndex);

View File

@@ -68,11 +68,9 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
private Condition mCondition = LOCK.newCondition();
private LinkedBlockingQueue<ExtInfo> mPeerQueue = new LinkedBlockingQueue<>();
private ExtInfo mCurExtInfo;
private LiveStateManager mManager;
private M3U8InfoTask mInfoTask;
private ScheduledThreadPoolExecutor mTimer;
private List<String> mPeerUrls = new ArrayList<>();
private Looper mLooper;
M3U8LiveLoader(DTaskWrapper wrapper, M3U8Listener listener) {
super(wrapper, listener);
@@ -94,8 +92,22 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
if (isBreak()) {
return;
}
mLooper = looper;
// 处理记录
getRecordHandler().setOption(mM3U8Option);
mRecord = getRecordHandler().getRecord(0);
// 初始化状态管理器
getStateManager().setLooper(mRecord, looper);
getStateManager().setLoader(this);
mStateHandler = new Handler(looper, getStateManager().getHandlerCallback());
// 循环获取直播文件列表
startLoaderLiveInfo();
// 启动定时器
startTimer();
new Thread(new Runnable() {
@Override public void run() {
String cacheDir = getCacheDir();
@@ -127,6 +139,14 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
}).start();
}
@Override protected LiveStateManager getStateManager() {
return (LiveStateManager) super.getStateManager();
}
private LiveRecordHandler getRecordHandler() {
return (LiveRecordHandler) mRecordHandler;
}
@Override public long getFileSize() {
return mTempFile.length();
}
@@ -165,20 +185,14 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
* 配置config
*/
private ThreadTask createThreadTask(String cacheDir, int indexId, String tsUrl) {
ThreadRecord record = new ThreadRecord();
record.taskKey = mRecord.filePath;
record.isComplete = false;
record.tsUrl = tsUrl;
record.threadType = getEntity().getTaskType();
record.threadId = indexId;
mRecord.threadRecords.add(record);
ThreadRecord tr = getRecordHandler().createThreadRecord(mRecord, tsUrl, indexId);
SubThreadConfig config = new SubThreadConfig();
config.url = tsUrl;
config.tempFile = new File(getTsFilePath(cacheDir, indexId));
config.isBlock = mRecord.isBlock;
config.taskWrapper = mTaskWrapper;
config.record = record;
config.record = tr;
config.stateHandler = mStateHandler;
config.peerIndex = indexId;
config.threadType = SubThreadConfig.getThreadType(ITaskWrapper.M3U8_LIVE);
@@ -219,15 +233,10 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
if (isSuccess) {
// 合并成功,删除缓存文件
for (String pp : partPath) {
File f = new File(pp);
if (f.exists()) {
f.delete();
}
FileUtil.deleteFile(pp);
}
File cDir = new File(cacheDir);
if (cDir.exists()) {
cDir.delete();
}
FileUtil.deleteDir(cDir);
return true;
} else {
ALog.e(TAG, "合并失败");
@@ -323,10 +332,7 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
* 需要在{@link #addComponent(IRecordHandler)} 后调用
*/
@Override public void addComponent(IThreadStateManager threadState) {
mManager = (LiveStateManager) threadState;
mManager.setLooper(mRecordHandler.getRecord(0), mLooper);
mManager.setLoader(this);
mStateHandler = new Handler(mLooper, mManager.getHandlerCallback());
mStateManager = threadState;
}
/**
@@ -344,7 +350,7 @@ final class M3U8LiveLoader extends BaseM3U8Loader {
if (mInfoTask == null) {
throw new NullPointerException(("文件信息组件为空"));
}
if (mManager == null) {
if (mStateManager == null) {
throw new NullPointerException("任务状态管理组件为空");
}
}

View File

@@ -23,9 +23,7 @@ import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpTaskOption;
import com.arialyy.aria.m3u8.M3U8InfoTask;
import com.arialyy.aria.m3u8.M3U8Listener;
import com.arialyy.aria.m3u8.M3U8RecordHandler;
import com.arialyy.aria.m3u8.M3U8TaskOption;
import com.arialyy.aria.util.CommonUtil;
/**
* M3U8直播文件下载工具对于直播来说需要定时更新m3u8文件
@@ -37,7 +35,6 @@ import com.arialyy.aria.util.CommonUtil;
* 5、不处理直播切片下载失败的状态
*/
public class M3U8LiveUtil extends AbsNormalLoaderUtil {
private final String TAG = CommonUtil.getClassName(getClass());
public M3U8LiveUtil(AbsTaskWrapper wrapper, IEventListener listener) {
super(wrapper, listener);
@@ -57,7 +54,7 @@ public class M3U8LiveUtil extends AbsNormalLoaderUtil {
@Override public LoaderStructure BuildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new M3U8RecordHandler(getTaskWrapper()))
structure.addComponent(new LiveRecordHandler(getTaskWrapper()))
.addComponent(new M3U8InfoTask(getTaskWrapper()))
.addComponent(new LiveStateManager(getTaskWrapper(), getListener()));
structure.accept(getLoader());

View File

@@ -73,7 +73,6 @@ final class M3U8VodLoader extends BaseM3U8Loader {
private Condition mJumpCondition = JUMP_LOCK.newCondition();
private SparseArray<ThreadRecord> mBeforePeer = new SparseArray<>();
private SparseArray<ThreadRecord> mAfterPeer = new SparseArray<>();
private VodStateManager mManager;
private PeerIndexEvent mCurrentEvent;
private String mCacheDir;
private int aIndex = 0, bIndex = 0;
@@ -136,11 +135,6 @@ final class M3U8VodLoader extends BaseM3U8Loader {
}
}
@Override protected void onPostPre() {
super.onPostPre();
initData();
}
@Override public boolean isBreak() {
return super.isBreak() || isDestroy;
}
@@ -154,6 +148,22 @@ final class M3U8VodLoader extends BaseM3U8Loader {
}
private void startThreadTask() {
// 处理任务记录
((VodRecordHandler) mRecordHandler).setOption(mM3U8Option);
mRecord = mRecordHandler.getRecord(0);
// 处理任务管理器
mStateHandler = new Handler(mLooper, getStateManager().getHandlerCallback());
getStateManager().setVodLoader(this);
getStateManager().setLooper(mRecord, mLooper);
// 初始化ts数据
initData();
// 启动定时器
startTimer();
// 启动线程开始下载ts切片
Thread th = new Thread(new Runnable() {
@Override public void run() {
while (!isBreak()) {
@@ -258,7 +268,7 @@ final class M3U8VodLoader extends BaseM3U8Loader {
mCompleteNum++;
}
}
mManager.updateStateCount();
getStateManager().updateStateCount();
if (mCompleteNum <= 0) {
getListener().onStart(0);
} else {
@@ -416,7 +426,7 @@ final class M3U8VodLoader extends BaseM3U8Loader {
String.format("beforeSize = %s, afterSize = %s, mCompleteNum = %s", mBeforePeer.size(),
mAfterPeer.size(), mCompleteNum));
ALog.i(TAG, String.format("完成处理数据的操作,将优先下载【%s】之后的切片", mCurrentEvent.peerIndex));
mManager.updateStateCount();
getStateManager().updateStateCount();
try {
JUMP_LOCK.lock();
@@ -487,7 +497,6 @@ final class M3U8VodLoader extends BaseM3U8Loader {
@Override public void addComponent(IRecordHandler recordHandler) {
mRecordHandler = recordHandler;
mRecord = mRecordHandler.getRecord(0);
}
@Override public void addComponent(IInfoTask infoTask) {
@@ -543,10 +552,7 @@ final class M3U8VodLoader extends BaseM3U8Loader {
* 需要在 {@link #addComponent(IRecordHandler)}后调用
*/
@Override public void addComponent(IThreadStateManager threadState) {
mManager = (VodStateManager) threadState;
mStateHandler = new Handler(mLooper, mManager.getHandlerCallback());
mManager.setVodLoader(this);
mManager.setLooper(mRecord, mLooper);
mStateManager = threadState;
}
/**
@@ -557,6 +563,11 @@ final class M3U8VodLoader extends BaseM3U8Loader {
}
@Override
protected VodStateManager getStateManager() {
return (VodStateManager) mStateManager;
}
@Override protected void checkComponent() {
if (mRecordHandler == null) {
throw new NullPointerException("任务记录组件为空");
@@ -564,7 +575,7 @@ final class M3U8VodLoader extends BaseM3U8Loader {
if (mInfoTask == null) {
throw new NullPointerException(("文件信息组件为空"));
}
if (mManager == null) {
if (getStateManager() == null) {
throw new NullPointerException("任务状态管理组件为空");
}
}

View File

@@ -24,7 +24,6 @@ import com.arialyy.aria.core.wrapper.AbsTaskWrapper;
import com.arialyy.aria.http.HttpTaskOption;
import com.arialyy.aria.m3u8.M3U8InfoTask;
import com.arialyy.aria.m3u8.M3U8Listener;
import com.arialyy.aria.m3u8.M3U8RecordHandler;
import com.arialyy.aria.m3u8.M3U8TaskOption;
/**
@@ -54,7 +53,7 @@ public final class M3U8VodUtil extends AbsNormalLoaderUtil {
@Override public LoaderStructure BuildLoaderStructure() {
LoaderStructure structure = new LoaderStructure();
structure.addComponent(new M3U8RecordHandler(getTaskWrapper()))
structure.addComponent(new VodRecordHandler(getTaskWrapper()))
.addComponent(new M3U8InfoTask(getTaskWrapper()))
.addComponent(new VodStateManager(getTaskWrapper(), (M3U8Listener) getListener()));
structure.accept(getLoader());

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arialyy.aria.m3u8;
package com.arialyy.aria.m3u8.vod;
import com.arialyy.aria.core.TaskRecord;
import com.arialyy.aria.core.ThreadRecord;
@@ -21,11 +21,12 @@ import com.arialyy.aria.core.common.RecordHandler;
import com.arialyy.aria.core.download.DTaskWrapper;
import com.arialyy.aria.core.download.DownloadEntity;
import com.arialyy.aria.core.download.M3U8Entity;
import com.arialyy.aria.core.loader.IRecordHandler;
import com.arialyy.aria.core.wrapper.ITaskWrapper;
import com.arialyy.aria.m3u8.BaseM3U8Loader;
import com.arialyy.aria.m3u8.M3U8InfoTask;
import com.arialyy.aria.m3u8.M3U8TaskOption;
import com.arialyy.aria.util.ALog;
import com.arialyy.aria.util.FileUtil;
import com.arialyy.aria.util.RecordUtil;
import java.io.File;
import java.util.ArrayList;
@@ -33,19 +34,15 @@ import java.util.ArrayList;
* @Author lyy
* @Date 2019-09-24
*/
public final class M3U8RecordHandler extends RecordHandler {
final class VodRecordHandler extends RecordHandler {
private M3U8TaskOption mOption;
public M3U8RecordHandler(DTaskWrapper wrapper) {
VodRecordHandler(DTaskWrapper wrapper) {
super(wrapper);
mOption = (M3U8TaskOption) wrapper.getM3u8Option();
}
@Override public void onPre() {
super.onPre();
if (getWrapper().getRequestType() == ITaskWrapper.M3U8_LIVE) {
RecordUtil.delTaskRecord(getEntity().getFilePath(), IRecordHandler.TYPE_DOWNLOAD);
}
public void setOption(M3U8TaskOption option) {
mOption = option;
}
/**

View File

@@ -52,7 +52,6 @@ public final class VodStateManager implements IThreadStateManager {
private int cancelNum = 0; // 已经取消的线程的数
private int stopNum = 0; // 已经停止的线程数
private int failNum = 0; // 失败的线程数
private long percent; //当前总进度,百分比进度
private long progress;
private TaskRecord taskRecord; // 任务记录
private Looper looper;
@@ -164,7 +163,11 @@ public final class VodStateManager implements IThreadStateManager {
}
break;
case STATE_RUNNING:
progress += (long) msg.obj;
Bundle b = msg.getData();
if (b != null) {
long len = b.getLong(IThreadStateManager.DATA_ADD_LEN, 0);
progress += len;
}
break;
}
return true;
@@ -226,7 +229,6 @@ public final class VodStateManager implements IThreadStateManager {
int percent = completeNum * 100 / taskRecord.threadRecords.size();
getEntity().setPercent(percent);
getEntity().update();
this.percent = percent;
}
@Override public boolean isFail() {