values = new ArrayList<>(entry.getValue());
74 | serialMap.put(key, values);
75 | }
76 |
77 | return serialMap;
78 | }
79 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/exception/FileDownloadNetworkPolicyException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.exception;
18 |
19 | import com.liulishuo.filedownloader.BaseDownloadTask;
20 |
21 | /**
22 | * Throw this exception, If you have set {@code true} to {@link BaseDownloadTask#setWifiRequired}
23 | * when starting downloading with the network type isn't wifi or in downloading state the network
24 | * type change to non-Wifi type.
25 | */
26 |
27 | public class FileDownloadNetworkPolicyException extends FileDownloadGiveUpRetryException {
28 | public FileDownloadNetworkPolicyException() {
29 | super("Only allows downloading this task on the wifi network type");
30 | }
31 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/exception/FileDownloadOutOfSpaceException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.liulishuo.filedownloader.exception;
17 |
18 | import android.annotation.TargetApi;
19 | import android.os.Build;
20 |
21 | import com.liulishuo.filedownloader.download.DownloadStatusCallback;
22 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
23 |
24 | import java.io.IOException;
25 |
26 | /**
27 | * Throw this exception, when the downloading file is too large to store, in other words,
28 | * the free space is less than the length of the downloading file.
29 | *
30 | * When the resource is non-Chunked(normally), we will check the space and handle this problem
31 | * before fetch data from the input stream:
32 | * {@link FileDownloadUtils#createOutputStream(String)}
33 | * When the resource is chunked, we will handle this problem when the free space is not enough to
34 | * store the following chunk:
35 | * {@link DownloadStatusCallback#exFiltrate(Exception)}
36 | */
37 | @SuppressWarnings("SameParameterValue")
38 | public class FileDownloadOutOfSpaceException extends IOException {
39 |
40 | private long freeSpaceBytes, requiredSpaceBytes, breakpointBytes;
41 |
42 | @TargetApi(Build.VERSION_CODES.GINGERBREAD)
43 | public FileDownloadOutOfSpaceException(long freeSpaceBytes, long requiredSpaceBytes,
44 | long breakpointBytes, Throwable cause) {
45 | super(FileDownloadUtils.formatString("The file is too large to store, breakpoint in bytes: "
46 | + " %d, required space in bytes: %d, but free space in bytes: "
47 | + "%d", breakpointBytes, requiredSpaceBytes, freeSpaceBytes), cause);
48 |
49 | init(freeSpaceBytes, requiredSpaceBytes, breakpointBytes);
50 | }
51 |
52 | public FileDownloadOutOfSpaceException(long freeSpaceBytes, long requiredSpaceBytes,
53 | long breakpointBytes) {
54 | super(FileDownloadUtils.formatString("The file is too large to store, breakpoint in bytes: "
55 | + " %d, required space in bytes: %d, but free space in bytes: "
56 | + "%d", breakpointBytes, requiredSpaceBytes, freeSpaceBytes));
57 |
58 | init(freeSpaceBytes, requiredSpaceBytes, breakpointBytes);
59 |
60 | }
61 |
62 | private void init(long freeSpaceBytes, long requiredSpaceBytes, long breakpointBytes) {
63 | this.freeSpaceBytes = freeSpaceBytes;
64 | this.requiredSpaceBytes = requiredSpaceBytes;
65 | this.breakpointBytes = breakpointBytes;
66 | }
67 |
68 | /**
69 | * @return The free space in bytes.
70 | */
71 | public long getFreeSpaceBytes() {
72 | return freeSpaceBytes;
73 | }
74 |
75 | /**
76 | * @return The required space in bytes use to store the datum will be fetched.
77 | */
78 | public long getRequiredSpaceBytes() {
79 | return requiredSpaceBytes;
80 | }
81 |
82 | /**
83 | * @return In normal Case: The value of breakpoint, which has already downloaded by past, if the
84 | * value is more than 0, it must be resuming from breakpoint.
85 | * For Chunked Resource(Streaming media):
86 | * The value would be the filled size.
87 | */
88 | public long getBreakpointBytes() {
89 | return breakpointBytes;
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/exception/FileDownloadSecurityException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.exception;
18 |
19 | /**
20 | * Throwing this exception, when there are some security issues found on FileDownloader.
21 | */
22 | public class FileDownloadSecurityException extends Exception {
23 | public FileDownloadSecurityException(String msg) {
24 | super(msg);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/exception/PathConflictException.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.exception;
18 |
19 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
20 |
21 | /**
22 | * Throw this exception, when there is an another running task with the same path with the current
23 | * task, so if the current task is started, the path of the file is sure to be written by multiple
24 | * tasks, it is wrong, then we through this exception to avoid such conflict.
25 | */
26 |
27 | public class PathConflictException extends IllegalAccessException {
28 |
29 | private final String mDownloadingConflictPath;
30 | private final String mTargetFilePath;
31 | private final int mAnotherSamePathTaskId;
32 |
33 | public PathConflictException(final int anotherSamePathTaskId, final String conflictPath,
34 | final String targetFilePath) {
35 | super(FileDownloadUtils.formatString("There is an another running task(%d) with the"
36 | + " same downloading path(%s), because of they are with the same "
37 | + "target-file-path(%s), so if the current task is started, the path of the"
38 | + " file is sure to be written by multiple tasks, it is wrong, then you "
39 | + "receive this exception to avoid such conflict.",
40 | anotherSamePathTaskId, conflictPath, targetFilePath));
41 |
42 | mAnotherSamePathTaskId = anotherSamePathTaskId;
43 | mDownloadingConflictPath = conflictPath;
44 | mTargetFilePath = targetFilePath;
45 | }
46 |
47 | /**
48 | * Get the conflict downloading file path, normally, this path is used for store the downloading
49 | * file relate with the {@link #mTargetFilePath}, and it would be generated from
50 | * {@link FileDownloadUtils#getTempPath(String)}.
51 | *
52 | * @return the conflict downloading file path.
53 | */
54 | public String getDownloadingConflictPath() {
55 | return mDownloadingConflictPath;
56 | }
57 |
58 | /**
59 | * Get the target file path, which downloading file path is conflict when downloading the task.
60 | *
61 | * @return the target file path, which downloading file path is conflict when downloading the
62 | * task.
63 | */
64 | public String getTargetFilePath() {
65 | return mTargetFilePath;
66 | }
67 |
68 | /**
69 | * Get the identify of another task which has the same path with the current task and its target
70 | * file path is the same to the current task too.
71 | *
72 | * @return the identify of another task which has the same path with the current task and its
73 | * target file path is the same to the current task too.
74 | */
75 | public int getAnotherSamePathTaskId() {
76 | return mAnotherSamePathTaskId;
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/message/BlockCompleteMessage.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.message;
18 |
19 | import com.liulishuo.filedownloader.model.FileDownloadStatus;
20 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
21 |
22 | /**
23 | * The interface of block complete message.
24 | *
25 | * @see SmallMessageSnapshot
26 | * @see LargeMessageSnapshot
27 | */
28 |
29 | public interface BlockCompleteMessage {
30 |
31 | MessageSnapshot transmitToCompleted();
32 |
33 | class BlockCompleteMessageImpl extends MessageSnapshot implements BlockCompleteMessage {
34 | private final MessageSnapshot mCompletedSnapshot;
35 |
36 | public BlockCompleteMessageImpl(MessageSnapshot snapshot) {
37 | super(snapshot.getId());
38 | if (snapshot.getStatus() != FileDownloadStatus.completed) {
39 | throw new IllegalArgumentException(FileDownloadUtils.formatString(
40 | "can't create the block complete message for id[%d], status[%d]",
41 | snapshot.getId(), snapshot.getStatus()));
42 | }
43 | this.mCompletedSnapshot = snapshot;
44 | }
45 |
46 | @Override
47 | public MessageSnapshot transmitToCompleted() {
48 | return this.mCompletedSnapshot;
49 | }
50 |
51 | @Override
52 | public byte getStatus() {
53 | return FileDownloadStatus.blockComplete;
54 | }
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/message/IFlowDirectly.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.message;
18 |
19 | /**
20 | * If the snapshot implement this interface, it will be flowed directly, it means that it would be
21 | * callback to the message station synchronize, not through the keep-flow-thread-pool.
22 | */
23 | public interface IFlowDirectly {
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/message/IMessageSnapshot.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.message;
18 |
19 | /**
20 | * The snapshot interface.
21 | */
22 | interface IMessageSnapshot {
23 | /**
24 | * @return The download identify.
25 | */
26 | int getId();
27 |
28 | /**
29 | * @return The current downloading status.
30 | * @see com.liulishuo.filedownloader.model.FileDownloadStatus
31 | */
32 | byte getStatus();
33 |
34 | /**
35 | * @return The error cause.
36 | */
37 | Throwable getThrowable();
38 |
39 | /**
40 | * @return The currently retrying times.
41 | */
42 | int getRetryingTimes();
43 |
44 | /**
45 | * @return {@code true} if the downloading is resuming from the breakpoint, otherwise the
46 | * downloading is from the beginning.
47 | */
48 | boolean isResuming();
49 |
50 | /**
51 | * @return the Etag from the response's header.
52 | */
53 | String getEtag();
54 |
55 | /**
56 | * This method will be used when the downloading file is a large file.
57 | *
58 | * @return The so far downloaded bytes.
59 | * @see #isLargeFile()
60 | */
61 | long getLargeSofarBytes();
62 |
63 | /**
64 | * This method will be used when the downloading file is a large file.
65 | *
66 | * @return The total bytes of the downloading file.
67 | * @see #isLargeFile()
68 | */
69 | long getLargeTotalBytes();
70 |
71 | /**
72 | * This method will be used when the downloading file isn't a large file.
73 | *
74 | * @return The so far downloaded bytes.
75 | * @see #isLargeFile()
76 | */
77 | int getSmallSofarBytes();
78 |
79 | /**
80 | * This method will be used when the downloading file isn't a large file.
81 | *
82 | * @return The total bytes of the downloading file.
83 | * @see #isLargeFile()
84 | */
85 | int getSmallTotalBytes();
86 |
87 | /**
88 | * @return {@code true} if the task isn't real started, and we find the target file is already
89 | * exist, so the task will receive the completed callback directly, {@code false} otherwise.
90 | */
91 | boolean isReusedDownloadedFile();
92 |
93 | /**
94 | * @return {@code true} if the length of the file is more than 1.99G, {@code false} otherwise.
95 | */
96 | boolean isLargeFile();
97 |
98 | /**
99 | * @return The filename.
100 | */
101 | String getFileName();
102 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshotFlow.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.message;
18 |
19 | /**
20 | * The internal message snapshot station.
21 | *
22 | * Making message snapshots keep flowing in order.
23 | */
24 | public class MessageSnapshotFlow {
25 |
26 | private volatile MessageSnapshotThreadPool flowThreadPool;
27 | private volatile MessageReceiver receiver;
28 |
29 | public static final class HolderClass {
30 | private static final MessageSnapshotFlow INSTANCE = new MessageSnapshotFlow();
31 | }
32 |
33 | public static MessageSnapshotFlow getImpl() {
34 | return HolderClass.INSTANCE;
35 | }
36 |
37 | public void setReceiver(MessageReceiver receiver) {
38 | this.receiver = receiver;
39 | if (receiver == null) {
40 | this.flowThreadPool = null;
41 | } else {
42 | this.flowThreadPool = new MessageSnapshotThreadPool(5, receiver);
43 | }
44 | }
45 |
46 | public void inflow(final MessageSnapshot snapshot) {
47 | if (snapshot instanceof IFlowDirectly) {
48 | if (receiver != null) {
49 | receiver.receive(snapshot);
50 | }
51 | } else {
52 | if (flowThreadPool != null) {
53 | flowThreadPool.execute(snapshot);
54 | }
55 | }
56 |
57 | }
58 |
59 |
60 | public interface MessageReceiver {
61 | void receive(MessageSnapshot snapshot);
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/message/MessageSnapshotThreadPool.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.liulishuo.filedownloader.message;
17 |
18 | import com.liulishuo.filedownloader.util.FileDownloadExecutors;
19 |
20 | import java.util.ArrayList;
21 | import java.util.List;
22 | import java.util.concurrent.Executor;
23 |
24 | /**
25 | * For guaranteeing only one-thread-pool for one-task, the task will be identified by its ID, make
26 | * sure the same task will be invoked in FIFO.
27 | */
28 | public class MessageSnapshotThreadPool {
29 |
30 | private final List executorList;
31 |
32 | private final MessageSnapshotFlow.MessageReceiver receiver;
33 |
34 | MessageSnapshotThreadPool(@SuppressWarnings("SameParameterValue") final int poolCount,
35 | MessageSnapshotFlow.MessageReceiver receiver) {
36 | this.receiver = receiver;
37 | executorList = new ArrayList<>();
38 | for (int i = 0; i < poolCount; i++) {
39 | executorList.add(new FlowSingleExecutor(i));
40 | }
41 | }
42 |
43 | public void execute(final MessageSnapshot snapshot) {
44 | FlowSingleExecutor targetPool = null;
45 | try {
46 | synchronized (executorList) {
47 | final int id = snapshot.getId();
48 | // Case 1. already had same task in executorList, so execute this event after
49 | // before-one.
50 | for (FlowSingleExecutor executor : executorList) {
51 | if (executor.enQueueTaskIdList.contains(id)) {
52 | targetPool = executor;
53 | break;
54 | }
55 | }
56 |
57 | // Case 2. no same task in executorList, so execute in executor which has the count
58 | // of active task is least.
59 | if (targetPool == null) {
60 | int leastTaskCount = 0;
61 | for (FlowSingleExecutor executor : executorList) {
62 | if (executor.enQueueTaskIdList.size() <= 0) {
63 | targetPool = executor;
64 | break;
65 | }
66 |
67 | if (leastTaskCount == 0
68 | || executor.enQueueTaskIdList.size() < leastTaskCount) {
69 | leastTaskCount = executor.enQueueTaskIdList.size();
70 | targetPool = executor;
71 | }
72 | }
73 | }
74 |
75 | //noinspection ConstantConditions
76 | targetPool.enqueue(id);
77 | }
78 | } finally {
79 | //noinspection ConstantConditions
80 | targetPool.execute(snapshot);
81 | }
82 | }
83 |
84 | public class FlowSingleExecutor {
85 | private final List enQueueTaskIdList = new ArrayList<>();
86 | private final Executor mExecutor;
87 |
88 | public FlowSingleExecutor(int index) {
89 | mExecutor = FileDownloadExecutors.newDefaultThreadPool(1, "Flow-" + index);
90 | }
91 |
92 | public void enqueue(final int id) {
93 | enQueueTaskIdList.add(id);
94 | }
95 |
96 | public void execute(final MessageSnapshot snapshot) {
97 | mExecutor.execute(new Runnable() {
98 | @Override
99 | public void run() {
100 | receiver.receive(snapshot);
101 | enQueueTaskIdList.remove((Integer) snapshot.getId());
102 | }
103 | });
104 | }
105 |
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/model/ConnectionModel.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.model;
18 |
19 | import android.content.ContentValues;
20 |
21 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
22 |
23 | import java.util.List;
24 |
25 | /**
26 | * The connection model used for record each connections on multiple connections case.
27 | */
28 |
29 | public class ConnectionModel {
30 | public static final String ID = "id";
31 | private int id;
32 |
33 | public static final String INDEX = "connectionIndex";
34 | private int index;
35 |
36 | public static final String START_OFFSET = "startOffset";
37 | private long startOffset;
38 |
39 | public static final String CURRENT_OFFSET = "currentOffset";
40 | private long currentOffset;
41 |
42 | public static final String END_OFFSET = "endOffset";
43 | private long endOffset;
44 |
45 | public int getId() {
46 | return id;
47 | }
48 |
49 | public void setId(int id) {
50 | this.id = id;
51 | }
52 |
53 | public int getIndex() {
54 | return index;
55 | }
56 |
57 | public void setIndex(int index) {
58 | this.index = index;
59 | }
60 |
61 | public long getStartOffset() {
62 | return startOffset;
63 | }
64 |
65 | public void setStartOffset(long startOffset) {
66 | this.startOffset = startOffset;
67 | }
68 |
69 | public long getCurrentOffset() {
70 | return currentOffset;
71 | }
72 |
73 | public void setCurrentOffset(long currentOffset) {
74 | this.currentOffset = currentOffset;
75 | }
76 |
77 | public long getEndOffset() {
78 | return endOffset;
79 | }
80 |
81 | public void setEndOffset(long endOffset) {
82 | this.endOffset = endOffset;
83 | }
84 |
85 | public ContentValues toContentValues() {
86 | final ContentValues values = new ContentValues();
87 | values.put(ConnectionModel.ID, id);
88 | values.put(ConnectionModel.INDEX, index);
89 | values.put(ConnectionModel.START_OFFSET, startOffset);
90 | values.put(ConnectionModel.CURRENT_OFFSET, currentOffset);
91 | values.put(ConnectionModel.END_OFFSET, endOffset);
92 | return values;
93 | }
94 |
95 | public static long getTotalOffset(List modelList) {
96 | long totalOffset = 0;
97 | for (ConnectionModel model : modelList) {
98 | totalOffset += (model.getCurrentOffset() - model.getStartOffset());
99 | }
100 | return totalOffset;
101 | }
102 |
103 | @Override
104 | public String toString() {
105 | return FileDownloadUtils.formatString("id[%d] index[%d] range[%d, %d) current offset(%d)",
106 | id, index, startOffset, endOffset, currentOffset);
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/model/FileDownloadHeader.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.model;
18 |
19 | import android.os.Parcel;
20 | import android.os.Parcelable;
21 |
22 | import java.util.ArrayList;
23 | import java.util.HashMap;
24 | import java.util.List;
25 |
26 | /**
27 | * We have already handled Etag internal for guaranteeing tasks resuming from the breakpoint, in
28 | * other words, if the task has downloaded and got Etag, we will add the 'If-Match' and the 'Range'
29 | * K-V to its request header automatically.
30 | */
31 | public class FileDownloadHeader implements Parcelable {
32 |
33 | private HashMap> mHeaderMap;
34 |
35 | /**
36 | * We have already handled etag, and will add 'If-Match' & 'Range' value if it works.
37 | *
38 | * @see com.liulishuo.filedownloader.download.ConnectTask#addUserRequiredHeader
39 | */
40 | public void add(String name, String value) {
41 | if (name == null) throw new NullPointerException("name == null");
42 | if (name.isEmpty()) throw new IllegalArgumentException("name is empty");
43 | if (value == null) throw new NullPointerException("value == null");
44 |
45 | if (mHeaderMap == null) {
46 | mHeaderMap = new HashMap<>();
47 | }
48 |
49 | List values = mHeaderMap.get(name);
50 | if (values == null) {
51 | values = new ArrayList<>();
52 | mHeaderMap.put(name, values);
53 | }
54 |
55 | if (!values.contains(value)) {
56 | values.add(value);
57 | }
58 | }
59 |
60 | /**
61 | * We have already handled etag, and will add 'If-Match' & 'Range' value if it works.
62 | *
63 | * @see com.liulishuo.filedownloader.download.ConnectTask#addUserRequiredHeader
64 | */
65 | public void add(String line) {
66 | String[] parsed = line.split(":");
67 | final String name = parsed[0].trim();
68 | final String value = parsed[1].trim();
69 |
70 | add(name, value);
71 | }
72 |
73 | /**
74 | * Remove all files with the name.
75 | */
76 | public void removeAll(String name) {
77 | if (mHeaderMap == null) {
78 | return;
79 | }
80 |
81 | mHeaderMap.remove(name);
82 | }
83 |
84 | @Override
85 | public int describeContents() {
86 | return 0;
87 | }
88 |
89 | @Override
90 | public void writeToParcel(Parcel dest, int flags) {
91 | dest.writeMap(mHeaderMap);
92 | }
93 |
94 | public HashMap> getHeaders() {
95 | return mHeaderMap;
96 | }
97 |
98 | public FileDownloadHeader() {
99 | }
100 |
101 | protected FileDownloadHeader(Parcel in) {
102 | //noinspection unchecked
103 | this.mHeaderMap = in.readHashMap(String.class.getClassLoader());
104 | }
105 |
106 | public static final Creator CREATOR = new Creator() {
107 | public FileDownloadHeader createFromParcel(Parcel source) {
108 | return new FileDownloadHeader(source);
109 | }
110 |
111 | public FileDownloadHeader[] newArray(int size) {
112 | return new FileDownloadHeader[size];
113 | }
114 | };
115 |
116 | @Override
117 | public String toString() {
118 | return mHeaderMap.toString();
119 | }
120 | }
121 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/model/FileDownloadTaskAtom.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.liulishuo.filedownloader.model;
17 |
18 | import android.os.Parcel;
19 | import android.os.Parcelable;
20 |
21 | import com.liulishuo.filedownloader.FileDownloader;
22 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
23 |
24 | /**
25 | * The Minimal unit for a task.
26 | *
27 | * Used for telling the FileDownloader Engine that a task was downloaded by the other ways.
28 | *
29 | * @see com.liulishuo.filedownloader.FileDownloader#setTaskCompleted
30 | * @deprecated No used. {@link FileDownloader#setTaskCompleted(String, String, long)}
31 | */
32 | @SuppressWarnings({"WeakerAccess", "deprecation", "DeprecatedIsStillUsed"})
33 | public class FileDownloadTaskAtom implements Parcelable {
34 | private String url;
35 | private String path;
36 | private long totalBytes;
37 |
38 | public FileDownloadTaskAtom(String url, String path, long totalBytes) {
39 | setUrl(url);
40 | setPath(path);
41 | setTotalBytes(totalBytes);
42 | }
43 |
44 | private int id;
45 |
46 | public int getId() {
47 | if (id != 0) {
48 | return id;
49 | }
50 |
51 | return id = FileDownloadUtils.generateId(getUrl(), getPath());
52 | }
53 |
54 | public String getUrl() {
55 | return url;
56 | }
57 |
58 | public void setUrl(String url) {
59 | this.url = url;
60 | }
61 |
62 | public String getPath() {
63 | return path;
64 | }
65 |
66 | public void setPath(String path) {
67 | this.path = path;
68 | }
69 |
70 | public long getTotalBytes() {
71 | return totalBytes;
72 | }
73 |
74 | public void setTotalBytes(long totalBytes) {
75 | this.totalBytes = totalBytes;
76 | }
77 |
78 | @Override
79 | public int describeContents() {
80 | return 0;
81 | }
82 |
83 | @Override
84 | public void writeToParcel(Parcel dest, int flags) {
85 | dest.writeString(this.url);
86 | dest.writeString(this.path);
87 | dest.writeLong(this.totalBytes);
88 | }
89 |
90 | protected FileDownloadTaskAtom(Parcel in) {
91 | this.url = in.readString();
92 | this.path = in.readString();
93 | this.totalBytes = in.readLong();
94 | }
95 |
96 | public static final Parcelable.Creator CREATOR =
97 | new Parcelable.Creator() {
98 | @Override
99 | public FileDownloadTaskAtom createFromParcel(Parcel source) {
100 | return new FileDownloadTaskAtom(source);
101 | }
102 |
103 | @Override
104 | public FileDownloadTaskAtom[] newArray(int size) {
105 | return new FileDownloadTaskAtom[size];
106 | }
107 | };
108 | }
109 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/notification/BaseNotificationItem.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.notification;
18 |
19 | import android.app.NotificationManager;
20 | import android.content.Context;
21 |
22 | import com.liulishuo.filedownloader.model.FileDownloadStatus;
23 | import com.liulishuo.filedownloader.util.FileDownloadHelper;
24 |
25 | /**
26 | * An atom notification item which identify with a downloading task, they have the same downloading
27 | * Id.
28 | *
29 | * @see FileDownloadNotificationHelper
30 | * @see FileDownloadNotificationListener
31 | */
32 | @SuppressWarnings("WeakerAccess")
33 | public abstract class BaseNotificationItem {
34 |
35 | private int id, sofar, total;
36 | private String title, desc;
37 |
38 | private int status = FileDownloadStatus.INVALID_STATUS;
39 | private int lastStatus = FileDownloadStatus.INVALID_STATUS;
40 |
41 | public BaseNotificationItem(final int id, final String title, final String desc) {
42 | this.id = id;
43 |
44 | this.title = title;
45 | this.desc = desc;
46 | }
47 |
48 | public void show(boolean isShowProgress) {
49 | show(isChanged(), getStatus(), isShowProgress);
50 | }
51 |
52 | /**
53 | * @param isShowProgress Whether there is a need to show the progress schedule changes
54 | */
55 | public abstract void show(boolean statusChanged, int status, boolean isShowProgress);
56 |
57 | public void update(final int sofar, final int total) {
58 | this.sofar = sofar;
59 | this.total = total;
60 | show(true);
61 | }
62 |
63 | public void updateStatus(final int status) {
64 | this.status = status;
65 | }
66 |
67 | public void cancel() {
68 | getManager().cancel(id);
69 | }
70 |
71 | private NotificationManager manager;
72 |
73 | protected NotificationManager getManager() {
74 | if (manager == null) {
75 | manager = (NotificationManager) FileDownloadHelper.getAppContext().
76 | getSystemService(Context.NOTIFICATION_SERVICE);
77 | }
78 | return manager;
79 | }
80 |
81 | public int getId() {
82 | return this.id;
83 | }
84 |
85 | public void setId(int id) {
86 | this.id = id;
87 | }
88 |
89 | public int getSofar() {
90 | return sofar;
91 | }
92 |
93 | public void setSofar(int sofar) {
94 | this.sofar = sofar;
95 | }
96 |
97 | public int getTotal() {
98 | return total;
99 | }
100 |
101 | public void setTotal(int total) {
102 | this.total = total;
103 | }
104 |
105 | public String getTitle() {
106 | return title;
107 | }
108 |
109 | public void setTitle(String title) {
110 | this.title = title;
111 | }
112 |
113 | public String getDesc() {
114 | return desc;
115 | }
116 |
117 | public void setDesc(String desc) {
118 | this.desc = desc;
119 | }
120 |
121 | public int getStatus() {
122 | this.lastStatus = status;
123 | return status;
124 | }
125 |
126 | public void setStatus(int status) {
127 | this.status = status;
128 | }
129 |
130 | public int getLastStatus() {
131 | return lastStatus;
132 | }
133 |
134 | public boolean isChanged() {
135 | return this.lastStatus != status;
136 | }
137 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/notification/FileDownloadNotificationHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.notification;
18 |
19 | import android.util.SparseArray;
20 |
21 | import com.liulishuo.filedownloader.model.FileDownloadStatus;
22 |
23 | /**
24 | * The helper for notifications with downloading tasks. You also can think this is the notifications
25 | * manager.
26 | *
27 | * @see BaseNotificationItem
28 | * @see FileDownloadNotificationListener
29 | */
30 | @SuppressWarnings("WeakerAccess")
31 | public class FileDownloadNotificationHelper {
32 |
33 | private final SparseArray notificationArray = new SparseArray<>();
34 |
35 | /**
36 | * Get {@link BaseNotificationItem} by the download id.
37 | *
38 | * @param id The download id.
39 | */
40 | public T get(final int id) {
41 | return notificationArray.get(id);
42 | }
43 |
44 | public boolean contains(final int id) {
45 | return get(id) != null;
46 | }
47 |
48 | /**
49 | * Remove the {@link BaseNotificationItem} by the download id.
50 | *
51 | * @param id The download id.
52 | * @return The removed {@link BaseNotificationItem}.
53 | */
54 | public T remove(final int id) {
55 | final T n = get(id);
56 | if (n != null) {
57 | notificationArray.remove(id);
58 | return n;
59 | }
60 |
61 | return null;
62 | }
63 |
64 | /**
65 | * Input a {@link BaseNotificationItem}.
66 | */
67 | public void add(T notification) {
68 | notificationArray.remove(notification.getId());
69 | notificationArray.put(notification.getId(), notification);
70 | }
71 |
72 | /**
73 | * Show the notification with the exact progress.
74 | *
75 | * @param id The download id.
76 | * @param sofar The downloaded bytes so far.
77 | * @param total The total bytes of this task.
78 | */
79 | public void showProgress(final int id, final int sofar, final int total) {
80 | final T notification = get(id);
81 |
82 | if (notification == null) {
83 | return;
84 | }
85 |
86 | notification.updateStatus(FileDownloadStatus.progress);
87 | notification.update(sofar, total);
88 | }
89 |
90 | /**
91 | * Show the notification with indeterminate progress.
92 | *
93 | * @param id The download id.
94 | * @param status {@link FileDownloadStatus}
95 | */
96 | public void showIndeterminate(final int id, int status) {
97 | final BaseNotificationItem notification = get(id);
98 |
99 | if (notification == null) {
100 | return;
101 | }
102 |
103 | notification.updateStatus(status);
104 | notification.show(false);
105 | }
106 |
107 | /**
108 | * Cancel the notification by notification id.
109 | *
110 | * @param id The download id.
111 | */
112 | public void cancel(final int id) {
113 | final BaseNotificationItem notification = remove(id);
114 |
115 | if (notification == null) {
116 | return;
117 | }
118 |
119 | notification.cancel();
120 | }
121 |
122 | /**
123 | * Clear and cancel all notifications which inside this helper {@link #notificationArray}.
124 | */
125 | public void clear() {
126 | @SuppressWarnings("unchecked") SparseArray cloneArray =
127 | (SparseArray) notificationArray.clone();
128 | notificationArray.clear();
129 |
130 | for (int i = 0; i < cloneArray.size(); i++) {
131 | final BaseNotificationItem n = cloneArray.get(cloneArray.keyAt(i));
132 | n.cancel();
133 | }
134 |
135 | }
136 | }
137 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/services/DefaultIdGenerator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.services;
18 |
19 | import com.liulishuo.filedownloader.util.FileDownloadHelper;
20 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
21 |
22 | import static com.liulishuo.filedownloader.util.FileDownloadUtils.formatString;
23 |
24 | /**
25 | * The default id generator.
26 | */
27 |
28 | public class DefaultIdGenerator implements FileDownloadHelper.IdGenerator {
29 |
30 | @Override
31 | public int transOldId(int oldId, String url, String path, boolean pathAsDirectory) {
32 | return generateId(url, path, pathAsDirectory);
33 | }
34 |
35 | @Override
36 | public int generateId(String url, String path, boolean pathAsDirectory) {
37 | if (pathAsDirectory) {
38 | return FileDownloadUtils.md5(formatString("%sp%s@dir", url, path)).hashCode();
39 | } else {
40 | return FileDownloadUtils.md5(formatString("%sp%s", url, path)).hashCode();
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/services/FileDownloadBroadcastHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.services;
18 |
19 | import android.content.Intent;
20 |
21 | import com.liulishuo.filedownloader.model.FileDownloadModel;
22 | import com.liulishuo.filedownloader.model.FileDownloadStatus;
23 | import com.liulishuo.filedownloader.util.FileDownloadHelper;
24 | import com.liulishuo.filedownloader.util.FileDownloadUtils;
25 |
26 | /**
27 | * The handler broadcast from filedownloader.
28 | */
29 | public class FileDownloadBroadcastHandler {
30 | public static final String ACTION_COMPLETED = "filedownloader.intent.action.completed";
31 | public static final String KEY_MODEL = "model";
32 |
33 | /**
34 | * Parse the {@code intent} from the filedownloader broadcast.
35 | *
36 | * @param intent the intent from the broadcast.
37 | * @return the file download model.
38 | */
39 | public static FileDownloadModel parseIntent(Intent intent) {
40 | if (!ACTION_COMPLETED.equals(intent.getAction())) {
41 | throw new IllegalArgumentException(FileDownloadUtils.
42 | formatString("can't recognize the intent with action %s, on the current"
43 | + " version we only support action [%s]",
44 | intent.getAction(), ACTION_COMPLETED));
45 | }
46 |
47 | return intent.getParcelableExtra(KEY_MODEL);
48 | }
49 |
50 | public static void sendCompletedBroadcast(FileDownloadModel model) {
51 | if (model == null) throw new IllegalArgumentException();
52 | if (model.getStatus() != FileDownloadStatus.completed) throw new IllegalStateException();
53 |
54 | final Intent intent = new Intent(ACTION_COMPLETED);
55 | intent.putExtra(KEY_MODEL, model);
56 |
57 | FileDownloadHelper.getAppContext().sendBroadcast(intent);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/services/IFileDownloadServiceHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.liulishuo.filedownloader.services;
17 |
18 | import android.content.Intent;
19 | import android.os.IBinder;
20 |
21 | import com.liulishuo.filedownloader.services.FDServiceSharedHandler.FileDownloadServiceSharedConnection;
22 |
23 | /**
24 | * The handler for {@link FileDownloadService}.
25 | *
26 | * @see FileDownloadManager
27 | */
28 | @SuppressWarnings("UnusedParameters")
29 | interface IFileDownloadServiceHandler {
30 | /**
31 | * Will used to handling the onConnected in {@link FileDownloadServiceSharedConnection}.
32 | *
33 | * Called by the system every time a client explicitly starts the service by calling
34 | * {@link android.content.Context#startService}.
35 | */
36 | void onStartCommand(Intent intent, int flags, int startId);
37 |
38 | /**
39 | * Will establish the connection with binder in {@link FDServiceSeparateHandler}
40 | *
41 | * @return Return the communication channel to the service. Nullable.
42 | */
43 | IBinder onBind(Intent intent);
44 |
45 | /**
46 | * Called by the system to notify a Service that it is no longer used and is being removed.
47 | *
48 | * @see FileDownloadServiceSharedConnection
49 | * @see FDServiceSeparateHandler
50 | */
51 | void onDestroy();
52 | }
53 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/stream/FileDownloadRandomAccessFile.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.stream;
18 |
19 | import com.liulishuo.filedownloader.util.FileDownloadHelper;
20 |
21 | import java.io.BufferedOutputStream;
22 | import java.io.File;
23 | import java.io.FileDescriptor;
24 | import java.io.FileOutputStream;
25 | import java.io.IOException;
26 | import java.io.RandomAccessFile;
27 |
28 | /**
29 | * The FileDownloadOutputStream implemented using {@link RandomAccessFile}.
30 | */
31 |
32 | public class FileDownloadRandomAccessFile implements FileDownloadOutputStream {
33 | private final BufferedOutputStream out;
34 | private final FileDescriptor fd;
35 | private final RandomAccessFile randomAccess;
36 |
37 | FileDownloadRandomAccessFile(File file) throws IOException {
38 | randomAccess = new RandomAccessFile(file, "rw");
39 | fd = randomAccess.getFD();
40 | out = new BufferedOutputStream(new FileOutputStream(randomAccess.getFD()));
41 | }
42 |
43 | @Override
44 | public void write(byte[] b, int off, int len) throws IOException {
45 | out.write(b, off, len);
46 | }
47 |
48 | @Override
49 | public void flushAndSync() throws IOException {
50 | out.flush();
51 | fd.sync();
52 | }
53 |
54 | @Override
55 | public void close() throws IOException {
56 | out.close();
57 | randomAccess.close();
58 | }
59 |
60 | @Override
61 | public void seek(long offset) throws IOException {
62 | randomAccess.seek(offset);
63 | }
64 |
65 | @Override
66 | public void setLength(long totalBytes) throws IOException {
67 | randomAccess.setLength(totalBytes);
68 | }
69 |
70 | public static class Creator implements FileDownloadHelper.OutputStreamCreator {
71 |
72 | @Override
73 | public FileDownloadOutputStream create(File file) throws IOException {
74 | return new FileDownloadRandomAccessFile(file);
75 | }
76 |
77 | @Override
78 | public boolean supportSeek() {
79 | return true;
80 | }
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/util/DownloadServiceNotConnectedHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 | package com.liulishuo.filedownloader.util;
17 |
18 | import android.app.Notification;
19 |
20 | import com.liulishuo.filedownloader.FileDownloader;
21 | import com.liulishuo.filedownloader.model.FileDownloadStatus;
22 |
23 | /**
24 | * The helper for handling the case of requesting do something in the downloader service but the
25 | * downloader service isn't connected yet.
26 | *
27 | * @see FileDownloader#insureServiceBind()
28 | * @see FileDownloader#insureServiceBindAsync()
29 | */
30 | public class DownloadServiceNotConnectedHelper {
31 |
32 | private static final String CAUSE = ", but the download service isn't connected yet.";
33 | private static final String TIPS = "\nYou can use FileDownloader#isServiceConnected() to check"
34 | + " whether the service has been connected, \nbesides you can use following functions"
35 | + " easier to control your code invoke after the service has been connected: \n"
36 | + "1. FileDownloader#bindService(Runnable)\n"
37 | + "2. FileDownloader#insureServiceBind()\n"
38 | + "3. FileDownloader#insureServiceBindAsync()";
39 |
40 | public static boolean start(final String url, final String path,
41 | final boolean pathAsDirectory) {
42 | log("request start the task([%s], [%s], [%B]) in the download service", url, path,
43 | pathAsDirectory);
44 | return false;
45 | }
46 |
47 | public static boolean pause(final int id) {
48 | log("request pause the task[%d] in the download service", id);
49 | return false;
50 | }
51 |
52 | public static boolean isDownloading(final String url, final String path) {
53 | log("request check the task([%s], [%s]) is downloading in the download service", url, path);
54 | return false;
55 | }
56 |
57 | public static long getSofar(final int id) {
58 | log("request get the downloaded so far byte for the task[%d] in the download service", id);
59 | return 0;
60 | }
61 |
62 | public static long getTotal(final int id) {
63 | log("request get the total byte for the task[%d] in the download service", id);
64 | return 0;
65 | }
66 |
67 | public static byte getStatus(final int id) {
68 | log("request get the status for the task[%d] in the download service", id);
69 | return FileDownloadStatus.INVALID_STATUS;
70 | }
71 |
72 | public static void pauseAllTasks() {
73 | log("request pause all tasks in the download service");
74 | }
75 |
76 | public static boolean isIdle() {
77 | log("request check the download service is idle");
78 | return true;
79 | }
80 |
81 | public static void startForeground(int notificationId, Notification notification) {
82 | log("request set the download service as the foreground service([%d],[%s]),",
83 | notificationId, notification);
84 | }
85 |
86 | public static void stopForeground(boolean removeNotification) {
87 | log("request cancel the foreground status[%B] for the download service",
88 | removeNotification);
89 | }
90 |
91 | public static boolean setMaxNetworkThreadCount(int count) {
92 | log("request set the max network thread count[%d] in the download service", count);
93 | return false;
94 | }
95 |
96 | public static boolean clearTaskData(int id) {
97 | log("request clear the task[%d] data in the database", id);
98 | return false;
99 | }
100 |
101 | public static boolean clearAllTaskData() {
102 | log("request clear all tasks data in the database");
103 | return false;
104 | }
105 |
106 | private static void log(String message, Object... args) {
107 | FileDownloadLog.w(DownloadServiceNotConnectedHelper.class, message + CAUSE + TIPS, args);
108 | }
109 |
110 | }
111 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/util/ExtraKeys.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.util;
18 |
19 | public class ExtraKeys {
20 |
21 | public static final String IS_FOREGROUND = "is_foreground";
22 | }
23 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadExecutors.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.util;
18 |
19 | import java.util.concurrent.LinkedBlockingQueue;
20 | import java.util.concurrent.SynchronousQueue;
21 | import java.util.concurrent.ThreadFactory;
22 | import java.util.concurrent.ThreadPoolExecutor;
23 | import java.util.concurrent.TimeUnit;
24 | import java.util.concurrent.atomic.AtomicInteger;
25 |
26 | /**
27 | * Executors are used in entire FileDownloader internal for managing different threads.
28 | *
29 | * All thread pools in FileDownloader will comply with:
30 | *
31 | * The default thread count is 0, and the maximum pool size is {@code nThreads}; When there are less
32 | * than {@code nThreads} threads running, a new thread is created to handle the request, but when it
33 | * turn to idle and the interval time of waiting for new task more than {@code DEFAULT_IDLE_SECOND}
34 | * second, the thread will be terminate to reduce the cost of resources.
35 | */
36 | public class FileDownloadExecutors {
37 | private static final int DEFAULT_IDLE_SECOND = 15;
38 |
39 | public static ThreadPoolExecutor newFixedThreadPool(String prefix) {
40 | return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
41 | DEFAULT_IDLE_SECOND, TimeUnit.SECONDS,
42 | new SynchronousQueue(), new FileDownloadThreadFactory(prefix));
43 | }
44 |
45 | public static ThreadPoolExecutor newDefaultThreadPool(int nThreads, String prefix) {
46 | return newDefaultThreadPool(nThreads, new LinkedBlockingQueue(), prefix);
47 | }
48 |
49 | public static ThreadPoolExecutor newDefaultThreadPool(int nThreads,
50 | LinkedBlockingQueue queue,
51 | String prefix) {
52 | final ThreadPoolExecutor executor = new ThreadPoolExecutor(nThreads, nThreads,
53 | DEFAULT_IDLE_SECOND, TimeUnit.SECONDS, queue,
54 | new FileDownloadThreadFactory(prefix));
55 | executor.allowCoreThreadTimeOut(true);
56 | return executor;
57 | }
58 |
59 | static class FileDownloadThreadFactory implements ThreadFactory {
60 | private static final AtomicInteger POOL_NUMBER = new AtomicInteger(1);
61 | private final String namePrefix;
62 | private final ThreadGroup group;
63 | private final AtomicInteger threadNumber = new AtomicInteger(1);
64 |
65 | FileDownloadThreadFactory(String prefix) {
66 | group = Thread.currentThread().getThreadGroup();
67 | namePrefix = FileDownloadUtils.getThreadPoolName(prefix);
68 | }
69 |
70 | @Override
71 | public Thread newThread(Runnable r) {
72 | Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
73 |
74 | if (t.isDaemon()) t.setDaemon(false);
75 | if (t.getPriority() != Thread.NORM_PRIORITY) t.setPriority(Thread.NORM_PRIORITY);
76 | return t;
77 | }
78 | }
79 |
80 | }
81 |
--------------------------------------------------------------------------------
/library/src/main/java/com/liulishuo/filedownloader/util/FileDownloadLog.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.util;
18 |
19 | import android.util.Log;
20 |
21 | /**
22 | * The log printer help to control all logs in FileDownloader.
23 | *
24 | * If you want to print all priority FileDownloader logs, please set true to {@link #NEED_LOG},
25 | * otherwise, we just print the log which priority higher than or equal to {@link Log#WARN}.
26 | */
27 | public class FileDownloadLog {
28 |
29 | public static boolean NEED_LOG = false;
30 |
31 | private static final String TAG = "FileDownloader.";
32 |
33 | public static void e(Object o, Throwable e, String msg, Object... args) {
34 | log(Log.ERROR, o, e, msg, args);
35 | }
36 |
37 | public static void e(Object o, String msg, Object... args) {
38 | log(Log.ERROR, o, msg, args);
39 | }
40 |
41 | public static void i(Object o, String msg, Object... args) {
42 | log(Log.INFO, o, msg, args);
43 | }
44 |
45 | public static void d(Object o, String msg, Object... args) {
46 | log(Log.DEBUG, o, msg, args);
47 | }
48 |
49 | public static void w(Object o, String msg, Object... args) {
50 | log(Log.WARN, o, msg, args);
51 | }
52 |
53 | public static void v(Object o, String msg, Object... args) {
54 | log(Log.VERBOSE, o, msg, args);
55 | }
56 |
57 | private static void log(int priority, Object o, String message, Object... args) {
58 | log(priority, o, null, message, args);
59 | }
60 |
61 | private static void log(int priority, Object o, Throwable throwable, String message,
62 | Object... args) {
63 | final boolean force = priority >= Log.WARN;
64 | if (!force && !NEED_LOG) {
65 | return;
66 | }
67 |
68 | Log.println(priority, getTag(o), FileDownloadUtils.formatString(message, args));
69 | if (throwable != null) {
70 | throwable.printStackTrace();
71 | }
72 | }
73 |
74 | private static String getTag(final Object o) {
75 | return TAG + ((o instanceof Class)
76 | ? ((Class) o).getSimpleName() : o.getClass().getSimpleName());
77 | }
78 | }
79 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | FileDownloader
4 | FileDownloader is running.
5 |
--------------------------------------------------------------------------------
/library/src/test/java/com/liulishuo/filedownloader/FileDownloaderTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader;
18 |
19 | import com.liulishuo.filedownloader.download.CustomComponentHolder;
20 | import com.liulishuo.filedownloader.util.FileDownloadHelper;
21 |
22 | import junit.framework.Assert;
23 |
24 | import org.junit.Test;
25 | import org.junit.runner.RunWith;
26 | import org.robolectric.RobolectricTestRunner;
27 |
28 | import static org.robolectric.RuntimeEnvironment.application;
29 |
30 | @RunWith(RobolectricTestRunner.class)
31 | public class FileDownloaderTest {
32 |
33 | @Test
34 | public void setup_withContext_hold() {
35 | FileDownloader.setup(application);
36 |
37 | Assert.assertEquals(application.getApplicationContext(),
38 | FileDownloadHelper.getAppContext());
39 | }
40 |
41 | @Test
42 | public void setupOnApplicationOnCreate_withContext_hold() {
43 | FileDownloader.setupOnApplicationOnCreate(application);
44 |
45 | Assert.assertEquals(application.getApplicationContext(),
46 | FileDownloadHelper.getAppContext());
47 | }
48 |
49 | @Test
50 | public void setupOnApplicationOnCreate_InitCustomMaker_valid() {
51 | FileDownloader.setupOnApplicationOnCreate(application)
52 | .maxNetworkThreadCount(6)
53 | .commit();
54 |
55 | Assert.assertEquals(CustomComponentHolder.getImpl().getMaxNetworkThreadCount(), 6);
56 | }
57 | }
--------------------------------------------------------------------------------
/library/src/test/java/com/liulishuo/filedownloader/connection/FileDownloadUrlConnectionTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.connection;
18 |
19 | import org.junit.Before;
20 | import org.junit.Test;
21 | import org.mockito.Mock;
22 | import org.mockito.Mockito;
23 |
24 | import java.io.IOException;
25 | import java.net.Proxy;
26 | import java.net.URL;
27 | import java.net.URLConnection;
28 |
29 | import static org.mockito.Matchers.anyInt;
30 | import static org.mockito.Mockito.times;
31 | import static org.mockito.Mockito.verify;
32 | import static org.mockito.MockitoAnnotations.initMocks;
33 |
34 | @SuppressWarnings("CanBeFinal")
35 | public class FileDownloadUrlConnectionTest {
36 |
37 | @Mock
38 | private Proxy mProxy;
39 |
40 | @Mock
41 | private URLConnection mConnection;
42 |
43 | @Mock
44 | private URL mURL;
45 |
46 | @Before
47 | public void setUp() throws Exception {
48 | initMocks(this);
49 |
50 | Mockito.when(mURL.openConnection()).thenReturn(mConnection);
51 | Mockito.when(mURL.openConnection(mProxy)).thenReturn(mConnection);
52 | }
53 |
54 | @Test
55 | public void construct_noConfiguration_noAssigned() throws IOException {
56 | FileDownloadUrlConnection.Creator creator = new FileDownloadUrlConnection.Creator();
57 |
58 | creator.create("http://blog.dreamtobe.cn");
59 |
60 | verify(mConnection, times(0)).setConnectTimeout(anyInt());
61 | verify(mConnection, times(0)).setReadTimeout(anyInt());
62 | }
63 |
64 | @Test
65 | public void construct_validConfiguration_Assigned() throws IOException {
66 |
67 |
68 | FileDownloadUrlConnection.Creator creator = new FileDownloadUrlConnection.Creator(
69 | new FileDownloadUrlConnection.Configuration()
70 | .proxy(mProxy)
71 | .connectTimeout(1001)
72 | .readTimeout(1002)
73 | );
74 |
75 | creator.create(mURL);
76 |
77 | verify(mURL).openConnection(mProxy);
78 | verify(mConnection).setConnectTimeout(1001);
79 | verify(mConnection).setReadTimeout(1002);
80 | }
81 |
82 |
83 | }
--------------------------------------------------------------------------------
/library/src/test/java/com/liulishuo/filedownloader/download/DownloadRunnableTest.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015 LingoChamp Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.liulishuo.filedownloader.download;
18 |
19 | import com.liulishuo.filedownloader.connection.FileDownloadConnection;
20 |
21 | import org.junit.Before;
22 | import org.junit.Test;
23 | import org.junit.runner.RunWith;
24 | import org.mockito.Mock;
25 | import org.robolectric.RobolectricTestRunner;
26 |
27 | import java.io.IOException;
28 | import java.net.HttpURLConnection;
29 |
30 | import static org.mockito.ArgumentMatchers.any;
31 | import static org.mockito.Mockito.mock;
32 | import static org.mockito.Mockito.spy;
33 | import static org.mockito.Mockito.verify;
34 | import static org.mockito.Mockito.when;
35 | import static org.mockito.MockitoAnnotations.initMocks;
36 |
37 | @SuppressWarnings("ALL")
38 | @RunWith(RobolectricTestRunner.class)
39 | public class DownloadRunnableTest {
40 |
41 | @Mock
42 | private ConnectTask mockConnectTask;
43 |
44 | private ProcessCallback mockCallback;
45 |
46 | @SuppressWarnings("ThrowableInstanceNeverThrown")
47 | private Exception mockIOException = new IOException("test");
48 |
49 | private DownloadRunnable downloadRunnable;
50 |
51 | @Before
52 | public void setUp() {
53 | initMocks(this);
54 |
55 | mockCallback = spy(new MockProcessCallback());
56 | downloadRunnable = new DownloadRunnable.Builder()
57 | .setCallback(mockCallback)
58 | .buildForTest(mockConnectTask);
59 |
60 | when(mockConnectTask.getProfile()).thenReturn(mock(ConnectionProfile.class));
61 | }
62 |
63 | @Test
64 | public void run_withConnectFailed_retry() throws IOException, IllegalAccessException {
65 | when(mockConnectTask.connect()).thenThrow(mockIOException);
66 |
67 | downloadRunnable.run();
68 |
69 | verify(mockCallback).onRetry(mockIOException);
70 | }
71 |
72 | @Test
73 | public void run_responseCodeNotMet_error() throws IOException, IllegalAccessException {
74 | final FileDownloadConnection connection = mock(FileDownloadConnection.class);
75 | when(connection.getResponseCode()).thenReturn(HttpURLConnection.HTTP_PRECON_FAILED);
76 | when(mockConnectTask.connect()).thenReturn(connection);
77 |
78 | downloadRunnable.run();
79 |
80 | // retry first.
81 | verify(mockCallback).onRetry(any(Exception.class));
82 |
83 | // then callback error.
84 | verify(mockCallback).onError(any(Exception.class));
85 | }
86 |
87 | private static class MockProcessCallback implements ProcessCallback {
88 |
89 | @Override
90 | public void onProgress(long increaseBytes) {
91 | }
92 |
93 | @Override
94 | public void onCompleted(DownloadRunnable doneRunnable, long startOffset, long endOffset) {
95 | }
96 |
97 | boolean isFirstTime = true;
98 |
99 | @Override
100 | public boolean isRetry(Exception exception) {
101 | if (isFirstTime) {
102 | isFirstTime = false;
103 | return true;
104 | }
105 |
106 | return false;
107 | }
108 |
109 | @Override
110 | public void onError(Exception exception) {
111 | }
112 |
113 |
114 | @Override
115 | public void onRetry(Exception exception) {
116 | }
117 |
118 | @Override
119 | public void syncProgressFromCache() {
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/library/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker:
--------------------------------------------------------------------------------
1 | mock-maker-inline
--------------------------------------------------------------------------------
/okcat.yml:
--------------------------------------------------------------------------------
1 | # you can use https://github.com/Jacksgong/okcat for debug filedownloader more gentle
2 | # we will filter out logs with the provided package (name)
3 | # this 'package' keyword is just using for android adb logcat
4 | package: com.liulishuo.filedownloader.demo
5 |
6 | # this 'log-line-regex' is just a regex for one line log
7 | # now we support keyword: 'data' 'time' 'level' 'tag' 'process' 'thread' 'message'
8 | # you don't have to provide all keyword, but you have to provide at least the 'message'
9 | # such as: 'message="(\S*)"'
10 | # log-line-regex: 'data,time,level,tag,process,thread,message = "(.\S*) (.\S*) ([A-Z])/([^:[]*):\[(\d*):([^] ]*)\] (.*?)$"'
11 |
12 | # on the case of filter logs from Android adb logcat, we using 'adb logcat -v brief -v threadtime' command to obtain logcat
13 | # in the normal case you don't need ot provide this config, because there is a perfect one on the okcat internal
14 | # but if you want to customize the regex log from adb logcat, it's free to define it such below
15 | # adb-log-line-regex: 'data,time,process,thread,level,tag,message="(.\S*) (.\S*) (\d*) (\d*) ([A-Z]) ([^:]*): (.*?)$"'
16 |
17 | # separator regex list
18 | # you can provide multiple regex to separate serial logs
19 | separator-regex-list:
20 | # on this case, if one line log match 'call start Url\[([^\]]*)\]' regex we will separate logs with \n and output a indie line with the '([^\]]*)' value as the title of separate
21 | - 'call start Url\[([^\]]*)\]'
22 |
23 | # tag keyword list
24 | # this list keyword is using for filter out which log need to be output
25 | # all provided keyword will be using for compare with each line tag, if a line with tag not contain any keyword on 'tag-keyword-list' it will be ignore to output
26 | tag-keyword-list:
27 | - FileDownloader
28 |
29 | # translate message map
30 | # if a message on a line start with provide keyword on the 'trans-msg-map' we will add the value of the keyword on the start of the message, and the word of value will be corlored to highlight it
31 | trans-msg-map:
32 | # such as this case:
33 | # origin message: 'filedownloader:lifecycle:over xxx'
34 | # after translate: '| Task OVER | filedownloader:lifecycle:over xxx'
35 | 'filedownloader:lifecycle:over': 'Task OVER'
36 | 'fetch data with': 'Start Fetch'
37 |
38 | # translate tag map
39 | # if a tag on a line contain provide keyword on the 'trans-tag-map' we will add the value of the keyword on the start of the message, and the background of the value word will be corlored to highlight it
40 | trans-tag-map:
41 | # such as this case:
42 | # origin message: 'FileDownloadApplication xxx'
43 | # after translate: 'FileDownloadApplication [Thread Change] xxx'
44 | 'FileDownloadApplication': '[Thread Change]'
45 | 'DownloadTaskHunter': '[Status Change]'
46 | 'ConnectTask': '[Request]'
47 |
48 | # hide message list
49 | # if a message on a line start with provide value on the 'hide-msg-list` and the length of the message is less than 100 word, it would be colored with gray to hide
50 | hide-msg-list:
51 | # here we hide message start with 'notify progress' and '~~~callback' because it is too frequently to output and useless in most case
52 | - 'notify progress'
53 | - '~~~callback'
54 |
55 | # highlight list
56 | # if any value on the 'hightlist-list' display on any message, the background of the value word would be colored to highlight it
57 | highlight-list:
58 | - 'Path['
59 | - 'Url['
60 | - 'Tag['
61 | - 'range['
62 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':demo', ':library'
2 |
--------------------------------------------------------------------------------