diff --git a/Aria/src/main/java/com/arialyy/aria/core/Aria.java b/Aria/src/main/java/com/arialyy/aria/core/Aria.java index 538f8504..011086ad 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/Aria.java +++ b/Aria/src/main/java/com/arialyy/aria/core/Aria.java @@ -114,110 +114,4 @@ import com.arialyy.aria.core.upload.UploadTask; throw new IllegalArgumentException("不支持的类型"); } } - - /** - * 上传任务状态监听 - * - * @see Upload - * @deprecated 请使用注解函数的方式来实现事件的获取 - */ - @Deprecated public static class UploadSchedulerListener - implements ISchedulerListener { - - /** - * 预处理,有时有些地址链接比较慢,这时可以先在这个地方出来一些界面上的UI,如按钮的状态。 - * - * @param task 上传文物实体 - */ - @Override public void onPre(UploadTask task) { - - } - - @Override public void onTaskPre(UploadTask task) { - - } - - @Override public void onTaskResume(UploadTask task) { - - } - - @Override public void onTaskStart(UploadTask task) { - - } - - @Override public void onTaskStop(UploadTask task) { - - } - - @Override public void onTaskCancel(UploadTask task) { - - } - - @Override public void onTaskFail(UploadTask task) { - - } - - @Override public void onTaskComplete(UploadTask task) { - - } - - @Override public void onTaskRunning(UploadTask task) { - - } - } - - /** - * 下载任务状态监听 - * - * @see Download - * @deprecated 请使用注解函数的方式来实现事件的获取 - */ - @Deprecated public static class DownloadSchedulerListener - implements IDownloadSchedulerListener { - /** - * 预处理,有时有些地址链接比较慢,这时可以先在这个地方出来一些界面上的UI,如按钮的状态。 - * 需要注意的是,在该回调中,是得不到文件长度的,如果需要获取文件长度,需要在onTaskPre中获取 - * - * @param task 下载任务 - */ - @Override public void onPre(DownloadTask task) { - - } - - @Override public void onTaskPre(DownloadTask task) { - - } - - @Override public void onTaskResume(DownloadTask task) { - - } - - @Override public void onTaskStart(DownloadTask task) { - - } - - @Override public void onTaskStop(DownloadTask task) { - - } - - @Override public void onTaskCancel(DownloadTask task) { - - } - - @Override public void onTaskFail(DownloadTask task) { - - } - - @Override public void onTaskComplete(DownloadTask task) { - - } - - @Override public void onTaskRunning(DownloadTask task) { - - } - - @Override public void onNoSupportBreakPoint(DownloadTask task) { - - } - } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java index eaa834c8..2e8df2fa 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java +++ b/Aria/src/main/java/com/arialyy/aria/core/AriaManager.java @@ -398,7 +398,6 @@ import org.xml.sax.SAXException; if (key.contains(clsName)) { IReceiver receiver = mReceivers.get(key); if (receiver != null) { - receiver.removeSchedulerListener(); receiver.unRegister(); receiver.destroy(); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java index dd0ba87d..9422e90c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/BaseDListener.java @@ -30,7 +30,7 @@ import java.lang.ref.WeakReference; */ class BaseDListener> implements IDownloadListener { - private WeakReference outHandler; + protected WeakReference outHandler; private long mLastLen = 0; //上一次发送长度 private boolean isFirst = true; protected ENTITY mEntity; @@ -117,6 +117,7 @@ class BaseDListener> } else { mEntity.setSpeed(speed < 0 ? 0 : speed); } + mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java index 650772b6..c33dfeba 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/DownloadGroupListener.java @@ -17,6 +17,7 @@ package com.arialyy.aria.core.download; import android.os.Handler; import com.arialyy.aria.core.download.downloader.IDownloadGroupListener; +import com.arialyy.aria.core.scheduler.ISchedulers; /** * Created by Aria.Lao on 2017/7/20. @@ -30,28 +31,51 @@ class DownloadGroupListener extends BaseDListener listener) { - this.listener = listener; - DownloadSchedulers.getInstance().addSchedulerListener(targetName, listener); - return this; - } - - /** - * 移除回调 - * - * @see #unRegister() - */ - @Deprecated @Override public void removeSchedulerListener() { - if (listener != null) { - DownloadSchedulers.getInstance().removeSchedulerListener(targetName, listener); - } - } - @Override public void destroy() { targetName = null; listener = null; diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java index 19efe055..6d13beab 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/AbsGroupUtil.java @@ -127,6 +127,7 @@ public abstract class AbsGroupUtil implements IUtil { mTaskEntity.getEntity().update(); } } + /** * 启动子任务下载 * @@ -457,6 +458,7 @@ public abstract class AbsGroupUtil implements IUtil { private void handleSpeed(long speed) { entity.setSpeed(speed); entity.setConvertSpeed(speed <= 0 ? "" : CommonUtil.formatFileSize(speed) + "/s"); + entity.setPercent((int) (entity.getCurrentProgress() * 100 / entity.getFileSize())); } private void saveData(int state, long location) { diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java deleted file mode 100644 index 338d114b..00000000 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/FtpClientHelp.java +++ /dev/null @@ -1,118 +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.download.downloader; - -import android.text.TextUtils; -import android.util.Log; -import com.arialyy.aria.core.AriaManager; -import java.io.IOException; -import org.apache.commons.net.ftp.FTPClient; -import org.apache.commons.net.ftp.FTPReply; - -/** - * Created by Aria.Lao on 2017/7/26. - */ -public class FtpClientHelp { - private final String TAG = "FtpClientHelp"; - private static volatile FtpClientHelp INSTANCE = null; - - private FTPClient client; - private String serverIp, user, pw, account; - private int port; - - private FtpClientHelp() { - } - - public static FtpClientHelp getInstnce() { - if (INSTANCE == null) { - synchronized (AriaManager.LOCK) { - INSTANCE = new FtpClientHelp(); - } - } - return INSTANCE; - } - - public FTPClient getClient() { - if (client == null || !client.isConnected()) { - createClient(); - } - return client; - } - - /** - * 登录到FTP服务器,当客户端为null或客户端没有连接到FTP服务器时才会执行登录操作 - */ - public FTPClient login(String serverIp, int port, String user, String pw, String account) { - this.serverIp = serverIp; - this.port = port; - this.user = user; - this.pw = pw; - this.account = account; - if (client == null || !client.isConnected()) { - createClient(); - } - return client; - } - - /** - * 登出 - */ - public void logout() { - try { - if (client != null && client.isConnected()) { - client.logout(); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - - FTPClient createClient() { - new Thread(new Runnable() { - @Override public void run() { - client = new FTPClient(); - try { - client.connect(serverIp, port); - if (!TextUtils.isEmpty(account)) { - client.login(user, pw); - } else { - client.login(user, pw, account); - } - int reply = client.getReplyCode(); - if (!FTPReply.isPositiveCompletion(reply)) { - client.disconnect(); - Log.e(TAG, "无法连接到ftp服务器,错误码为:" + reply); - } - } catch (IOException e) { - Log.d(TAG, e.getMessage()); - } finally { - synchronized (FtpClientHelp.this) { - FtpClientHelp.this.notify(); - } - } - } - }).start(); - synchronized (FtpClientHelp.this) { - try { - wait(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - return client; - } -} diff --git a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadGroupListener.java b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadGroupListener.java index e0b0695f..4264cae4 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadGroupListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/download/downloader/IDownloadGroupListener.java @@ -17,7 +17,6 @@ package com.arialyy.aria.core.download.downloader; import com.arialyy.aria.core.download.DownloadEntity; import com.arialyy.aria.core.inf.IDownloadListener; -import com.arialyy.aria.core.inf.IEventListener; /** * Created by Aria.Lao on 2017/7/20. @@ -25,6 +24,11 @@ import com.arialyy.aria.core.inf.IEventListener; */ public interface IDownloadGroupListener extends IDownloadListener { + /** + * 子任务预处理 + */ + void onSubPre(DownloadEntity subEntity); + /** * 子任务支持断点回调 * @@ -56,4 +60,9 @@ public interface IDownloadGroupListener extends IDownloadListener { * 子任务取消下载 */ void onSubCancel(DownloadEntity subEntity); + + /** + * 子任务执行中 + */ + void onSubRunning(DownloadEntity subEntity); } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java index eb611d5f..1caf0d17 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/AbsEntity.java @@ -60,6 +60,11 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable */ private long completeTime; + /** + * 进度百分比 + */ + @Ignore private int percent; + private boolean isComplete = false; public boolean isComplete() { @@ -142,6 +147,14 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable this.completeTime = completeTime; } + public int getPercent() { + return percent; + } + + public void setPercent(int percent) { + this.percent = percent; + } + /** * 实体唯一标识符 */ @@ -165,6 +178,7 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable dest.writeLong(this.currentProgress); dest.writeLong(this.completeTime); dest.writeByte(this.isComplete ? (byte) 1 : (byte) 0); + dest.writeInt(this.percent); } protected AbsEntity(Parcel in) { @@ -178,5 +192,6 @@ public abstract class AbsEntity extends DbEntity implements IEntity, Parcelable this.currentProgress = in.readLong(); this.completeTime = in.readLong(); this.isComplete = in.readByte() != 0; + this.percent = in.readInt(); } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java index 0242daf3..aed2ad9a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/inf/IReceiver.java @@ -26,10 +26,6 @@ public interface IReceiver { */ void destroy(); - /** - * 移除事件回调 - */ - void removeSchedulerListener(); /** * 移除观察者 diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java index a77db95e..da969577 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulerListener.java @@ -15,12 +15,14 @@ */ package com.arialyy.aria.core.scheduler; +import com.arialyy.aria.core.inf.AbsNormalTask; import com.arialyy.aria.core.inf.ITask; /** * Created by Aria.Lao on 2017/6/7. */ -public class AbsSchedulerListener implements ISchedulerListener { +public class AbsSchedulerListener implements ISchedulerListener { + @Override public void onPre(TASK task) { } @@ -64,4 +66,32 @@ public class AbsSchedulerListener implements ISchedulerListe public void setListener(Object obj) { } + + public void onSubTaskPre(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskStart(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskStop(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskCancel(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskComplete(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskFail(TASK task, SUB_TASK subTask) { + + } + + public void onSubTaskRunning(TASK task, SUB_TASK subTask) { + + } } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java index 281324c9..a82b5f6a 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/AbsSchedulers.java @@ -21,6 +21,7 @@ import android.util.Log; import com.arialyy.aria.core.AriaManager; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.inf.AbsEntity; +import com.arialyy.aria.core.inf.AbsNormalTask; import com.arialyy.aria.core.inf.AbsTask; import com.arialyy.aria.core.inf.AbsTaskEntity; import com.arialyy.aria.core.inf.IEntity; @@ -45,9 +46,7 @@ abstract class AbsSchedulers> mSchedulerListeners = new ConcurrentHashMap<>(); - - private Map> mObservers = new ConcurrentHashMap<>(); + private Map> mObservers = new ConcurrentHashMap<>(); /** * 设置调度器类型 @@ -59,33 +58,9 @@ abstract class AbsSchedulers schedulerListener) { - mSchedulerListeners.put(targetName, schedulerListener); - } - - /** - * @param targetName 观察者,创建该监听器的对象类名 - * @see #unRegister(Object) - */ - @Override public void removeSchedulerListener(String targetName, - ISchedulerListener schedulerListener) { - //该内存泄露解决方案:http://stackoverflow.com/questions/14585829/how-safe-is-to-delete-already-removed-concurrenthashmap-element - for (Iterator>> iter = - mSchedulerListeners.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> entry = iter.next(); - if (entry.getKey().equals(targetName)) iter.remove(); - } - } - @Override public void register(Object obj) { String targetName = obj.getClass().getName(); - AbsSchedulerListener listener = mObservers.get(targetName); + AbsSchedulerListener listener = mObservers.get(targetName); if (listener == null) { listener = createListener(targetName); if (listener != null) { @@ -98,9 +73,9 @@ abstract class AbsSchedulers>> iter = + for (Iterator>> iter = mObservers.entrySet().iterator(); iter.hasNext(); ) { - Map.Entry> entry = iter.next(); + Map.Entry> entry = iter.next(); if (entry.getKey().equals(obj.getClass().getName())) iter.remove(); } } @@ -110,11 +85,11 @@ abstract class AbsSchedulers createListener(String targetName) { - AbsSchedulerListener listener = null; + private AbsSchedulerListener createListener(String targetName) { + AbsSchedulerListener listener = null; try { Class clazz = Class.forName(targetName + getProxySuffix()); - listener = (AbsSchedulerListener) clazz.newInstance(); + listener = (AbsSchedulerListener) clazz.newInstance(); } catch (ClassNotFoundException e) { Log.e(TAG, targetName + ",没有Aria的Download或Upload注解方法"); } catch (InstantiationException e) { @@ -131,8 +106,52 @@ abstract class AbsSchedulers 0) { + Set keys = mObservers.keySet(); + for (String key : keys) { + AbsSchedulerListener listener = mObservers.get(key); + switch (what) { + case SUB_PRE: + //listener.onSubTaskPre(task, ); + break; + case SUB_START: + break; + case SUB_STOP: + break; + case SUB_FAIL: + break; + case SUB_RUNNING: + break; + case SUB_CANCEL: + break; + case SUB_COMPLETE: + break; + } + } + } + } + + /** + * 处理普通任务事件 + */ + private void handleNormalEvent(TASK task, int what) { + ENTITY entity = task.getEntity(); + switch (what) { case STOP: if (task.getEntity().getState() == IEntity.STATE_WAIT) { break; @@ -153,8 +172,7 @@ abstract class AbsSchedulers 0) { - Set keys = mSchedulerListeners.keySet(); - for (String key : keys) { - callback(state, task, mSchedulerListeners.get(key)); - } - } else if (mObservers.size() > 0) { + if (mObservers.size() > 0) { Set keys = mObservers.keySet(); for (String key : keys) { callback(state, task, mObservers.get(key)); @@ -176,7 +189,7 @@ abstract class AbsSchedulers listener) { + private void callback(int state, TASK task, AbsSchedulerListener listener) { if (listener != null) { if (task == null) { Log.e(TAG, "TASK 为null,回调失败"); @@ -211,9 +224,7 @@ abstract class AbsSchedulers) listener).onNoSupportBreakPoint(task); - } + listener.onNoSupportBreakPoint(task); break; } } diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java index b8128680..533fecc3 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulerListener.java @@ -66,4 +66,8 @@ public interface ISchedulerListener { * 任务执行中 */ void onTaskRunning(TASK task); + + + + } \ No newline at end of file diff --git a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java index a88e1f29..c48ebf2e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java +++ b/Aria/src/main/java/com/arialyy/aria/core/scheduler/ISchedulers.java @@ -24,6 +24,11 @@ import com.arialyy.aria.core.inf.AbsTask; * 调度器功能接口 */ public interface ISchedulers extends Handler.Callback { + /** + * 为任务组任务 + */ + int IS_SUB_TASK = 0xd1; + /** * 断点支持 */ @@ -67,18 +72,39 @@ public interface ISchedulers extends Handler.Callback { int RESUME = 8; /** - * 注册下载器监听,一个观察者只能注册一次监听 - * - * @param targetName 观察者,创建该监听器的对象类名 - * @param schedulerListener {@link ISchedulerListener} + * 任务组子任务预处理 + */ + int SUB_PRE = 0xa1; + + /** + * 任务组子任务开始 + */ + int SUB_START = 0xa2; + + /** + * 任务组子任务停止 + */ + int SUB_STOP = 0xa3; + + /** + * 任务组子任务取消 + */ + int SUB_CANCEL = 0xa4; + + /** + * 任务组子任务失败 + */ + int SUB_FAIL = 0xa5; + + /** + * 任务组子任务执行执行中 */ - void addSchedulerListener(String targetName, ISchedulerListener schedulerListener); + int SUB_RUNNING = 0xa6; /** - * @param targetName 观察者,创建该监听器的对象类名 - * 取消注册监听器 + * 任务组子任务完成 */ - void removeSchedulerListener(String targetName, ISchedulerListener schedulerListener); + int SUB_COMPLETE = 0xa7; /** * 将当前类注册到Aria diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java index 4ec59630..0c0d9f6e 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/BaseUListener.java @@ -106,6 +106,7 @@ class BaseUListener> } else { mEntity.setSpeed(speed < 0 ? 0 : speed); } + mEntity.setPercent((int) (mEntity.getCurrentProgress() * 100 / mEntity.getFileSize())); } /** diff --git a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java index 70cdee95..2036547c 100644 --- a/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java +++ b/Aria/src/main/java/com/arialyy/aria/core/upload/UploadReceiver.java @@ -97,8 +97,6 @@ public class UploadReceiver extends AbsReceiver { Set keys = am.getReceiver().keySet(); for (String key : keys) { - IReceiver receiver = am.getReceiver().get(key); - receiver.removeSchedulerListener(); am.getReceiver().remove(key); } } @@ -108,26 +106,6 @@ public class UploadReceiver extends AbsReceiver { listener = null; } - /** - * 添加调度器回调 - * - * @see #register() - */ - @Deprecated public UploadReceiver addSchedulerListener(ISchedulerListener listener) { - this.listener = listener; - UploadSchedulers.getInstance().addSchedulerListener(targetName, listener); - return this; - } - - /** - * @see #unRegister() - */ - @Deprecated @Override public void removeSchedulerListener() { - if (listener != null) { - UploadSchedulers.getInstance().removeSchedulerListener(targetName, listener); - } - } - /** * 将当前类注册到Aria */ diff --git a/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java b/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java index 67ef1f6a..11521b9d 100644 --- a/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java +++ b/AriaAnnotations/src/main/java/com/arialyy/annotations/DownloadGroup.java @@ -111,48 +111,48 @@ import java.lang.annotation.Target; * 任务组子任务预处理的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskPre { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务开始的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskStart { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务停止的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskStop { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务删除的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskCancel { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务失败的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskFail { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务完成的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskComplete { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } /** * 任务组子任务正在执行的注解 */ @Retention(RetentionPolicy.CLASS) @Target(ElementType.METHOD) @interface onSubTaskRunning { - String value() default AriaConstance.NO_URL; + String[] value() default { AriaConstance.NO_URL }; } } diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java index 72c4b985..913bd72e 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/AriaProcessor.java @@ -16,6 +16,7 @@ package com.arialyy.compiler; import com.arialyy.annotations.Download; +import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.Upload; import com.google.auto.service.AutoService; import java.util.LinkedHashSet; @@ -53,17 +54,24 @@ import javax.lang.model.element.TypeElement; annotataions.add(Download.onTaskRunning.class.getCanonicalName()); annotataions.add(Download.onTaskStart.class.getCanonicalName()); annotataions.add(Download.onTaskStop.class.getCanonicalName()); - //下载任务的注解 - annotataions.add(Download.onPre.class.getCanonicalName()); - annotataions.add(Download.onNoSupportBreakPoint.class.getCanonicalName()); - annotataions.add(Download.onTaskCancel.class.getCanonicalName()); - annotataions.add(Download.onTaskComplete.class.getCanonicalName()); - annotataions.add(Download.onTaskFail.class.getCanonicalName()); - annotataions.add(Download.onTaskPre.class.getCanonicalName()); - annotataions.add(Download.onTaskResume.class.getCanonicalName()); - annotataions.add(Download.onTaskRunning.class.getCanonicalName()); - annotataions.add(Download.onTaskStart.class.getCanonicalName()); - annotataions.add(Download.onTaskStop.class.getCanonicalName()); + //下载任务组的注解 + annotataions.add(DownloadGroup.onPre.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskCancel.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskComplete.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskFail.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskPre.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskResume.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskRunning.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskStart.class.getCanonicalName()); + annotataions.add(DownloadGroup.onTaskStop.class.getCanonicalName()); + //任务组子任务的注解 + annotataions.add(DownloadGroup.onSubTaskPre.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskCancel.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskComplete.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskFail.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskRunning.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskStart.class.getCanonicalName()); + annotataions.add(DownloadGroup.onSubTaskStop.class.getCanonicalName()); //上传任务的注解 annotataions.add(Upload.onPre.class.getCanonicalName()); annotataions.add(Upload.onNoSupportBreakPoint.class.getCanonicalName()); @@ -86,6 +94,7 @@ import javax.lang.model.element.TypeElement; mHandler.clean(); mHandler.handleDownload(roundEnv); mHandler.handleDownloadGroup(roundEnv); + mHandler.handleDownloadGroupSub(roundEnv); mHandler.handleUpload(roundEnv); mHandler.createProxyFile(); return true; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java new file mode 100644 index 00000000..d019aa09 --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/CountFiler.java @@ -0,0 +1,123 @@ +/* + * 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.compiler; + +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.Filer; +import javax.lang.model.element.Modifier; + +/** + * Created by lyy on 2017/9/6. + * 各类注解统计技术类 + */ +final class CountFiler { + private Filer mFiler; + private ParamObtainUtil mPbUtil; + + CountFiler(Filer filer, ParamObtainUtil pbUtil) { + mFiler = filer; + mPbUtil = pbUtil; + } + + /** + * 每一种注解对应的统计类 + */ + void createCountFile() throws IOException { + Set keys = mPbUtil.getListenerClass().keySet(); + TypeSpec.Builder builder = TypeSpec.classBuilder(ProxyConstance.PROXY_COUNTER_NAME) + .addModifiers(Modifier.PUBLIC, Modifier.FINAL); + + FieldSpec mappingField = FieldSpec.builder( + ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), + ProxyConstance.PROXY_COUNTER_MAP) + .addModifiers(Modifier.PRIVATE) + .initializer("new $T()", HashMap.class) + .build(); + builder.addField(mappingField); + + //增加构造函数 + CodeBlock.Builder cb = CodeBlock.builder(); + cb.add("Set set = null;\n"); + for (String key : keys) { + addTypeData(key, mPbUtil.getListenerClass().get(key), cb); + } + MethodSpec structure = + MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); + builder.addMethod(structure); + + builder.addMethod( + createMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD, ProxyConstance.COUNT_DOWNLOAD)); + builder.addMethod( + createMethod(ProxyConstance.COUNT_METHOD_UPLOAD, ProxyConstance.COUNT_UPLOAD)); + builder.addMethod(createMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD_GROUP, + ProxyConstance.COUNT_DOWNLOAD_GROUP)); + + JavaFile jf = JavaFile.builder(ProxyConstance.PROXY_COUNTER_PACKAGE, builder.build()).build(); + createFile(jf); + } + + /** + * 创建不同任务类型的代理类集合 + * + * @param key {@link ParamObtainUtil#addListenerMapping(String, String)} + */ + private MethodSpec createMethod(String methodName, String key) { + MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName); + ParameterizedTypeName returnName = + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class)); + builder.addModifiers(Modifier.PUBLIC, Modifier.FINAL) + .returns(returnName) + .addCode("return " + ProxyConstance.PROXY_COUNTER_MAP + ".get(\"" + key + "\");\n"); + return builder.build(); + } + + /** + * 添加每一种注解对应类 + * + * @param type {@link ParamObtainUtil#addListenerMapping(String, String)} + */ + private void addTypeData(String type, Set clsNames, CodeBlock.Builder cb) { + if (clsNames == null || clsNames.isEmpty()) return; + StringBuilder sb = new StringBuilder(); + sb.append("set = new $T();\n"); + for (String clsName : clsNames) { + sb.append("set.add(\"").append(clsName).append("\");\n"); + } + sb.append("typeMapping.put(\"").append(type).append("\", ").append("set);\n"); + cb.add(sb.toString(), ClassName.get(HashSet.class)); + } + + private void createFile(JavaFile jf) throws IOException { + if (ProxyConstance.DEBUG) { + // 如果需要在控制台打印生成的文件,则去掉下面的注释 + jf.writeTo(System.out); + } else { + jf.writeTo(mFiler); + } + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java index fa4ce99e..78917280 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ElementHandler.java @@ -18,31 +18,9 @@ package com.arialyy.compiler; import com.arialyy.annotations.Download; import com.arialyy.annotations.DownloadGroup; import com.arialyy.annotations.Upload; -import com.squareup.javapoet.ClassName; -import com.squareup.javapoet.CodeBlock; -import com.squareup.javapoet.FieldSpec; -import com.squareup.javapoet.JavaFile; -import com.squareup.javapoet.MethodSpec; -import com.squareup.javapoet.ParameterSpec; -import com.squareup.javapoet.TypeSpec; -import com.squareup.javapoet.ParameterizedTypeName; import java.io.IOException; -import java.lang.annotation.Annotation; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; import javax.annotation.processing.Filer; import javax.annotation.processing.RoundEnvironment; -import javax.lang.model.element.Element; -import javax.lang.model.element.ElementKind; -import javax.lang.model.element.ExecutableElement; -import javax.lang.model.element.Modifier; -import javax.lang.model.element.PackageElement; -import javax.lang.model.element.TypeElement; -import javax.lang.model.element.VariableElement; import javax.lang.model.util.Elements; /** @@ -50,16 +28,13 @@ import javax.lang.model.util.Elements; * 元素处理 */ class ElementHandler { - private static final boolean DEBUG = false; private Filer mFiler; - private Elements mElementUtil; - private Map mMethods = new HashMap<>(); - private Map> mListenerClass = new HashMap<>(); + private ParamObtainUtil mPbUtil; ElementHandler(Filer filer, Elements elements) { mFiler = filer; - mElementUtil = elements; + mPbUtil = new ParamObtainUtil(elements); } /** @@ -69,43 +44,68 @@ class ElementHandler { * PackageElement 一般代表Package */ void handleDownload(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onNoSupportBreakPoint.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onNoSupportBreakPoint.class, ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskCancel.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onPre.class, ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskPre.class, ProxyConstance.TASK_PRE); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskResume.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskPre.class, + ProxyConstance.TASK_PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskRunning.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStop.class, ProxyConstance.TASK_STOP); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD, roundEnv, Download.onTaskStop.class, + ProxyConstance.TASK_STOP); } /** * 处理搜索到的下载任务组注解 */ void handleDownloadGroup(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskCancel.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onPre.class, + ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskFail.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskPre.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskPre.class, ProxyConstance.TASK_PRE); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskResume.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskRunning.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskRunning.class, + ProxyConstance.TASK_RUNNING); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStop.class, + ProxyConstance.TASK_STOP); + } + + /** + * 处理搜索到的下载任务组子任务注解 + */ + void handleDownloadGroupSub(RoundEnvironment roundEnv) { + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskPre.class, + ProxyConstance.TASK_PRE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskCancel.class, + ProxyConstance.TASK_CANCEL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskComplete.class, + ProxyConstance.TASK_COMPLETE); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStart.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.DOWNLOAD_GROUP, roundEnv, DownloadGroup.onTaskStop.class, + mPbUtil.saveMethod(TaskEnum.DOWNLOAD_GROUP_SUB, roundEnv, DownloadGroup.onSubTaskStop.class, ProxyConstance.TASK_STOP); } @@ -113,488 +113,38 @@ class ElementHandler { * 处理搜索到的上传注解F */ void handleUpload(RoundEnvironment roundEnv) { - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onNoSupportBreakPoint.class, + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onNoSupportBreakPoint.class, ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onPre.class, ProxyConstance.PRE); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskCancel.class, ProxyConstance.TASK_CANCEL); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskComplete.class, + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onPre.class, ProxyConstance.PRE); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskCancel.class, + ProxyConstance.TASK_CANCEL); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskComplete.class, ProxyConstance.TASK_COMPLETE); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskFail.class, ProxyConstance.TASK_FAIL); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskResume.class, ProxyConstance.TASK_RESUME); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskRunning.class, ProxyConstance.TASK_RUNNING); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStart.class, ProxyConstance.TASK_START); - saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStop.class, ProxyConstance.TASK_STOP); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskFail.class, + ProxyConstance.TASK_FAIL); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskResume.class, + ProxyConstance.TASK_RESUME); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskRunning.class, + ProxyConstance.TASK_RUNNING); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStart.class, + ProxyConstance.TASK_START); + mPbUtil.saveMethod(TaskEnum.UPLOAD, roundEnv, Upload.onTaskStop.class, + ProxyConstance.TASK_STOP); } /** - * 在build文件夹中生成如下代码的文件 - *
-   *   
-   * package com.arialyy.simple.download;
-   *
-   * import com.arialyy.aria.core.download.DownloadTask;
-   * import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
-   *
-   * public final class SingleTaskActivity$$DownloadListenerProxy extends
-   * AbsSchedulerListener {
-   * private SingleTaskActivity obj;
-   *
-   *    public void onPre(final DownloadTask task) {
-   *      obj.onPre((DownloadTask)task);
-   *    }
-   *
-   *    public void onTaskStart(final DownloadTask task) {
-   *      obj.onStart((DownloadTask)task);
-   *    }
-   *
-   *    public void setListener(final Object obj) {
-   *      this.obj = (SingleTaskActivity)obj;
-   *    }
-   * }
-   *   
-   * 
+ * 在build文件夹中生成代理文件 */ void createProxyFile() { try { - createProxyListenerFile(); - createProxyClassFile(); + new EventProxyFiler(mFiler, mPbUtil).createEventProxyFile(); + //new CountFiler(mFiler, mPbUtil).createCountFile(); } catch (IOException e) { e.printStackTrace(); } } - /** - * 创建事件代理文件 - */ - private void createProxyListenerFile() throws IOException { - Set keys = mMethods.keySet(); - for (String key : keys) { - ProxyMethodParam entity = mMethods.get(key); - for (TaskEnum taskEnum : entity.taskEnums) { - JavaFile jf = - JavaFile.builder(entity.packageName, createProxyClass(entity, taskEnum)).build(); - createFile(jf); - } - } - } - - private void createFile(JavaFile jf) throws IOException { - if (DEBUG) { - // 如果需要在控制台打印生成的文件,则去掉下面的注释 - jf.writeTo(System.out); - } else { - jf.writeTo(mFiler); - } - } - - /** - * 每一种注解对应的类集合 - */ - private void createProxyClassFile() throws IOException { - Set keys = mListenerClass.keySet(); - TypeSpec.Builder builder = TypeSpec.classBuilder(ProxyConstance.PROXY_COUNTER_NAME) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - - FieldSpec mappingField = FieldSpec.builder( - ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), - ProxyConstance.PROXY_COUNTER_MAP) - .addModifiers(Modifier.PRIVATE) - .initializer("new $T()", HashMap.class) - .build(); - builder.addField(mappingField); - - //增加构造函数 - CodeBlock.Builder cb = CodeBlock.builder(); - cb.add("Set set = null;\n"); - for (String key : keys) { - addTypeData(key, mListenerClass.get(key), cb); - } - MethodSpec structure = - MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); - builder.addMethod(structure); - - builder.addMethod( - creatMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD, ProxyConstance.COUNT_DOWNLOAD)); - builder.addMethod(creatMethod(ProxyConstance.COUNT_METHOD_UPLOAD, ProxyConstance.COUNT_UPLOAD)); - builder.addMethod(creatMethod(ProxyConstance.COUNT_METHOD_DOWNLOAD_GROUP, - ProxyConstance.COUNT_DOWNLOAD_GROUP)); - - JavaFile jf = JavaFile.builder(ProxyConstance.PROXY_COUNTER_PACKAGE, builder.build()).build(); - createFile(jf); - } - - /** - * 创建不同任务类型的代理类集合 - * - * @param key {@link #addListenerMapping(String, String)} - */ - private MethodSpec creatMethod(String methodName, String key) { - MethodSpec.Builder builder = MethodSpec.methodBuilder(methodName); - ParameterizedTypeName returnName = - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class)); - builder.addModifiers(Modifier.PUBLIC, Modifier.FINAL) - .returns(returnName) - .addCode("return " + ProxyConstance.PROXY_COUNTER_MAP + ".get(\"" + key + "\");\n"); - return builder.build(); - } - - /** - * 添加每一种注解对应类 - * - * @param type {@link #addListenerMapping(String, String)} - */ - private void addTypeData(String type, Set clsNames, CodeBlock.Builder cb) { - if (clsNames == null || clsNames.isEmpty()) return; - StringBuilder sb = new StringBuilder(); - sb.append("set = new $T();\n"); - for (String clsName : clsNames) { - sb.append("set.add(\"").append(clsName).append("\");\n"); - } - sb.append("typeMapping.put(\"").append(type).append("\", ").append("set);\n"); - cb.add(sb.toString(), ClassName.get(HashSet.class)); - } - - /** - * 创建代理方法 - * - * @param taskEnum 任务类型枚举{@link TaskEnum} - * @param annotation {@link Download}、{@link Upload} - * @param methodName 被代理类注解的方法名 - */ - private MethodSpec createProxyMethod(TaskEnum taskEnum, Class annotation, - String methodName) { - ClassName task = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); - - ParameterSpec parameterSpec = - ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build(); - StringBuilder sb = new StringBuilder(); - sb.append("Set keys = keyMapping.get(\"").append(methodName).append("\");\n"); - sb.append("if (keys != null) {\n\tif (keys.contains(task.getKey())) {\n") - .append("\t\tobj.") - .append(methodName) - .append("((") - .append(taskEnum.getClassName()) - .append(")task);\n") - .append("\t}\n} else {\n") - .append("\tobj.") - .append(methodName) - .append("((") - .append(taskEnum.getClassName()) - .append(")task);\n}\n"); - - return MethodSpec.methodBuilder(annotation.getSimpleName()) - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addParameter(parameterSpec) - .addAnnotation(Override.class) - .addCode(sb.toString()) - .build(); - } - - /** - * 创建代理类 - */ - private TypeSpec createProxyClass(ProxyMethodParam entity, TaskEnum taskEnum) { - TypeSpec.Builder builder = TypeSpec.classBuilder(entity.className + taskEnum.getProxySuffix()) - .addModifiers(Modifier.PUBLIC, Modifier.FINAL); - - //添加被代理的类的字段 - ClassName obj = ClassName.get(entity.packageName, entity.className); - FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build(); - builder.addField(observerField); - - //添加url映射表 - FieldSpec mappingField = FieldSpec.builder( - ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), - ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), - "keyMapping").addModifiers(Modifier.PRIVATE).initializer("new $T()", HashMap.class).build(); - builder.addField(mappingField); - - //添加注解方法 - Map, String> temp = entity.methods.get(taskEnum); - if (temp != null) { - for (Class annotation : temp.keySet()) { - MethodSpec method = createProxyMethod(taskEnum, annotation, temp.get(annotation)); - builder.addMethod(method); - } - } - - //增加构造函数 - CodeBlock.Builder cb = CodeBlock.builder(); - cb.add("Set set = null;\n"); - for (String methodName : entity.keyMappings.keySet()) { - Set keys = entity.keyMappings.get(methodName); - if (keys == null || keys.size() == 0) continue; - StringBuilder sb = new StringBuilder(); - sb.append("set = new $T();\n"); - for (String key : keys) { - if (key.isEmpty()) continue; - sb.append("set.add(\"").append(key).append("\");\n"); - } - - sb.append("keyMapping.put(\"").append(methodName).append("\", ").append("set);\n"); - cb.add(sb.toString(), ClassName.get(HashSet.class)); - } - MethodSpec structure = - MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); - builder.addMethod(structure); - - //添加设置代理的类 - ParameterSpec parameterSpec = - ParameterSpec.builder(Object.class, "obj").addModifiers(Modifier.FINAL).build(); - MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER) - .addModifiers(Modifier.PUBLIC) - .returns(void.class) - .addParameter(parameterSpec) - .addAnnotation(Override.class) - .addCode("this.obj = (" + entity.className + ")obj;\n") - .build(); - builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n"); - - //创建父类参数 - ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener"); - //创建泛型 - ClassName typeVariableName = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); - builder.superclass(ParameterizedTypeName.get(superClass, typeVariableName)); - builder.addMethod(listener); - return builder.build(); - } - void clean() { - mMethods.clear(); - } - - /** - * 查找并保存扫描到的方法 - */ - private void saveMethod(TaskEnum taskEnum, RoundEnvironment roundEnv, - Class annotationClazz, int annotationType) { - for (Element element : roundEnv.getElementsAnnotatedWith(annotationClazz)) { - ElementKind kind = element.getKind(); - if (kind == ElementKind.METHOD) { - ExecutableElement method = (ExecutableElement) element; - TypeElement classElement = (TypeElement) method.getEnclosingElement(); - PackageElement packageElement = mElementUtil.getPackageOf(classElement); - checkDownloadMethod(taskEnum, method); - String methodName = method.getSimpleName().toString(); - String className = method.getEnclosingElement().toString(); //全类名 - ProxyMethodParam proxyEntity = mMethods.get(className); - if (proxyEntity == null) { - proxyEntity = new ProxyMethodParam(); - proxyEntity.taskEnums = new HashSet<>(); - proxyEntity.packageName = packageElement.getQualifiedName().toString(); - proxyEntity.className = classElement.getSimpleName().toString(); - mMethods.put(className, proxyEntity); - } - proxyEntity.taskEnums.add(taskEnum); - if (proxyEntity.methods.get(taskEnum) == null) { - proxyEntity.methods.put(taskEnum, new HashMap, String>()); - } - proxyEntity.methods.get(taskEnum).put(annotationClazz, methodName); - proxyEntity.keyMappings.put(methodName, getValues(taskEnum, method, annotationType)); - } - } - } - - /** - * 获取注解的内容 - */ - private Set getValues(TaskEnum taskEnum, ExecutableElement method, int annotationType) { - String clsName = method.getEnclosingElement().toString(); - String[] keys = null; - switch (taskEnum) { - case DOWNLOAD: - keys = getDownloadValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD); - break; - case UPLOAD: - keys = getUploadValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_UPLOAD); - break; - case DOWNLOAD_GROUP: - keys = getDownloadGroupValues(method, annotationType); - addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP); - break; - } - return keys == null ? null : convertSet(keys); - } - - /** - * 添加方法映射 - * - * @param clsName 注解事件的类 - * @param key {@link ProxyConstance#COUNT_DOWNLOAD}、{@link ProxyConstance#COUNT_UPLOAD}、{@link - * ProxyConstance#COUNT_DOWNLOAD_GROUP} - */ - private void addListenerMapping(String clsName, String key) { - Set cls = mListenerClass.get(key); - if (cls == null) { - cls = new HashSet<>(); - mListenerClass.put(key, cls); - } - cls.add(clsName); - } - - /** - * 获取下载任务组的注解数据 - */ - private String[] getDownloadGroupValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(DownloadGroup.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - values = method.getAnnotation(DownloadGroup.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(DownloadGroup.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(DownloadGroup.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(DownloadGroup.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(DownloadGroup.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(DownloadGroup.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(DownloadGroup.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(DownloadGroup.onTaskFail.class).value(); - break; - } - return values; - } - - /** - * 获取上传的注解数据 - */ - private String[] getUploadValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(Upload.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - //values = method.getAnnotation(Upload.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(Upload.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(Upload.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(Upload.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(Upload.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(Upload.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(Upload.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(Upload.onTaskFail.class).value(); - break; - case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: - //values = method.getAnnotation(Upload.onNoSupportBreakPoint.class).value(); - break; - } - return values; - } - - /** - * 获取下载的注解数据 - */ - private String[] getDownloadValues(ExecutableElement method, int annotationType) { - String[] values = null; - switch (annotationType) { - case ProxyConstance.PRE: - values = method.getAnnotation(Download.onPre.class).value(); - break; - case ProxyConstance.TASK_PRE: - values = method.getAnnotation(Download.onTaskPre.class).value(); - break; - case ProxyConstance.TASK_RESUME: - values = method.getAnnotation(Download.onTaskResume.class).value(); - break; - case ProxyConstance.TASK_START: - values = method.getAnnotation(Download.onTaskStart.class).value(); - break; - case ProxyConstance.TASK_RUNNING: - values = method.getAnnotation(Download.onTaskRunning.class).value(); - break; - case ProxyConstance.TASK_STOP: - values = method.getAnnotation(Download.onTaskStop.class).value(); - break; - case ProxyConstance.TASK_COMPLETE: - values = method.getAnnotation(Download.onTaskComplete.class).value(); - break; - case ProxyConstance.TASK_CANCEL: - values = method.getAnnotation(Download.onTaskCancel.class).value(); - break; - case ProxyConstance.TASK_FAIL: - values = method.getAnnotation(Download.onTaskFail.class).value(); - break; - case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: - values = method.getAnnotation(Download.onNoSupportBreakPoint.class).value(); - break; - } - return values; - } - - /** - * 检查和下载相关的方法,如果被注解的方法为private或参数不合法,则抛异常 - */ - private void checkDownloadMethod(TaskEnum taskEnum, ExecutableElement method) { - String methodName = method.getSimpleName().toString(); - String className = method.getEnclosingElement().toString(); - Set modifiers = method.getModifiers(); - if (modifiers.contains(Modifier.PRIVATE)) { - throw new IllegalAccessError(className + "." + methodName + "不能为private方法"); - } - List params = (List) method.getParameters(); - if (params.size() > 1) { - throw new IllegalArgumentException( - className + "." + methodName + "参数错误, 参数只有一个,且参数必须是" + getCheckParams(taskEnum)); - } - if (!params.get(0).asType().toString().equals(getCheckParams(taskEnum))) { - throw new IllegalArgumentException(className - + "." - + methodName - + "参数【" - + params.get(0).getSimpleName() - + "】类型错误,参数必须是" - + getCheckParams(taskEnum)); - } - } - - /** - * 字符串数组转set - * - * @param keys 注解中查到的key - */ - private Set convertSet(final String[] keys) { - if (keys == null || keys.length == 0) { - return null; - } - if (keys[0].isEmpty()) return null; - Set set = new HashSet<>(); - Collections.addAll(set, keys); - return set; - } - - private String getCheckParams(TaskEnum taskEnum) { - return taskEnum.pkg + "." + taskEnum.getClassName(); + mPbUtil.getMethodParams().clear(); } } diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java b/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java new file mode 100644 index 00000000..f5480410 --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/EventProxyFiler.java @@ -0,0 +1,244 @@ +/* + * 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.compiler; + +import com.arialyy.annotations.Download; +import com.arialyy.annotations.Upload; +import com.squareup.javapoet.ClassName; +import com.squareup.javapoet.CodeBlock; +import com.squareup.javapoet.FieldSpec; +import com.squareup.javapoet.JavaFile; +import com.squareup.javapoet.MethodSpec; +import com.squareup.javapoet.ParameterSpec; +import com.squareup.javapoet.ParameterizedTypeName; +import com.squareup.javapoet.TypeSpec; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.Filer; +import javax.lang.model.element.Modifier; + +/** + * Created by lyy on 2017/9/6. + * 任务事件代理文件 + * + *
+ *   
+ * package com.arialyy.simple.download;
+ *
+ * import com.arialyy.aria.core.download.DownloadTask;
+ * import com.arialyy.aria.core.scheduler.AbsSchedulerListener;
+ *
+ * public final class SingleTaskActivity$$DownloadListenerProxy extends
+ * AbsSchedulerListener {
+ * private SingleTaskActivity obj;
+ *
+ *    public void onPre(final DownloadTask task) {
+ *      obj.onPre((DownloadTask)task);
+ *    }
+ *
+ *    public void onTaskStart(final DownloadTask task) {
+ *      obj.onStart((DownloadTask)task);
+ *    }
+ *
+ *    public void setListener(final Object obj) {
+ *      this.obj = (SingleTaskActivity)obj;
+ *    }
+ * }
+ *   
+ * 
+ */ +final class EventProxyFiler { + + private Filer mFiler; + private ParamObtainUtil mPbUtil; + + EventProxyFiler(Filer filer, ParamObtainUtil pbUtil) { + mFiler = filer; + mPbUtil = pbUtil; + } + + /** + * 创建任务事件代理文件 + */ + void createEventProxyFile() throws IOException { + Map map = mPbUtil.getMethodParams(); + Set keys = mPbUtil.getMethodParams().keySet(); + for (String key : keys) { + //if (key.equals( + // "com.arialyy.simple.download.SingleTaskActivity$$DownloadGroupListenerProxy")) { + // + // ProxyClassParam entity = mPbUtil.getMethodParams().get(key); + // JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build(); + // createFile(jf); + //} + + ProxyClassParam entity = mPbUtil.getMethodParams().get(key); + JavaFile jf = JavaFile.builder(entity.packageName, createProxyClass(entity)).build(); + createFile(jf); + + } + } + + /** + * 创建代理方法 + * + * @param taskEnum 任务类型枚举{@link TaskEnum} + * @param annotation {@link Download}、{@link Upload} + * @param methodName 被代理类注解的方法名 + */ + private MethodSpec createProxyMethod(TaskEnum taskEnum, Class annotation, + String methodName) { + ClassName task = ClassName.get(taskEnum.getPkg(), taskEnum.getClassName()); + + ParameterSpec taskParam = + ParameterSpec.builder(task, "task").addModifiers(Modifier.FINAL).build(); + + String callCode; + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + callCode = "task, subTask"; + } else { + callCode = "task"; + } + StringBuilder sb = new StringBuilder(); + sb.append("Set keys = keyMapping.get(\"").append(methodName).append("\");\n"); + sb.append("if (keys != null) {\n\tif (keys.contains(task.getKey())) {\n") + .append("\t\tobj.") + .append(methodName) + .append("((") + .append(taskEnum.getClassName()) + .append(")") + .append(callCode) + .append(");\n\t}\n} else {\n") + .append("\tobj.") + .append(methodName) + .append("((") + .append(taskEnum.getClassName()) + .append(")") + .append(callCode) + .append(");\n}\n"); + + MethodSpec.Builder builder = MethodSpec.methodBuilder(annotation.getSimpleName()) + .addModifiers(Modifier.PUBLIC) + .returns(void.class) + .addParameter(taskParam) + .addAnnotation(Override.class) + .addCode(sb.toString()); + + //任务组接口 + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + ClassName subTask = ClassName.get(TaskEnum.DOWNLOAD.pkg, TaskEnum.DOWNLOAD.className); + ParameterSpec subTaskParam = + ParameterSpec.builder(subTask, "subTask").addModifiers(Modifier.FINAL).build(); + + builder.addParameter(subTaskParam); + } + + //PrintLog.getInstance().info(builder.build().toString()); + + return builder.build(); + } + + /** + * 创建代理类 + */ + private TypeSpec createProxyClass(ProxyClassParam entity) { + TypeSpec.Builder builder = + TypeSpec.classBuilder(entity.proxyClassName).addModifiers(Modifier.PUBLIC, Modifier.FINAL); + + //添加被代理的类的字段 + ClassName obj = ClassName.get(entity.packageName, entity.className); + FieldSpec observerField = FieldSpec.builder(obj, "obj").addModifiers(Modifier.PRIVATE).build(); + builder.addField(observerField); + + //添加url映射表 + FieldSpec mappingField = FieldSpec.builder( + ParameterizedTypeName.get(ClassName.get(Map.class), ClassName.get(String.class), + ParameterizedTypeName.get(ClassName.get(Set.class), ClassName.get(String.class))), + "keyMapping").addModifiers(Modifier.PRIVATE).initializer("new $T()", HashMap.class).build(); + builder.addField(mappingField); + + //添加注解方法 + for (TaskEnum te : entity.methods.keySet()) { + Map, String> temp = entity.methods.get(te); + if (temp != null) { + for (Class annotation : temp.keySet()) { + MethodSpec method = createProxyMethod(te, annotation, temp.get(annotation)); + builder.addMethod(method); + } + } + } + + //增加构造函数 + CodeBlock.Builder cb = CodeBlock.builder(); + cb.add("Set set = null;\n"); + for (String methodName : entity.keyMappings.keySet()) { + //PrintLog.getInstance().info("methodName ====> " + methodName); + Set keys = entity.keyMappings.get(methodName); + if (keys == null || keys.size() == 0) continue; + StringBuilder sb = new StringBuilder(); + sb.append("set = new $T();\n"); + for (String key : keys) { + if (key.isEmpty()) continue; + sb.append("set.add(\"").append(key).append("\");\n"); + } + + sb.append("keyMapping.put(\"").append(methodName).append("\", ").append("set);\n"); + cb.add(sb.toString(), ClassName.get(HashSet.class)); + } + MethodSpec structure = + MethodSpec.constructorBuilder().addModifiers(Modifier.PUBLIC).addCode(cb.build()).build(); + builder.addMethod(structure); + + //添加设置代理的类 + ParameterSpec parameterSpec = + ParameterSpec.builder(Object.class, "obj").addModifiers(Modifier.FINAL).build(); + MethodSpec listener = MethodSpec.methodBuilder(ProxyConstance.SET_LISTENER) + .addModifiers(Modifier.PUBLIC) + .returns(void.class) + .addParameter(parameterSpec) + .addAnnotation(Override.class) + .addCode("this.obj = (" + entity.className + ")obj;\n") + .build(); + builder.addJavadoc("该文件为Aria自动生成的代理文件,请不要修改该文件的任何代码!\n"); + + //创建父类参数 + ClassName superClass = ClassName.get("com.arialyy.aria.core.scheduler", "AbsSchedulerListener"); + //主任务泛型参数 + ClassName taskTypeVariable = + ClassName.get(entity.mainTaskEnum.pkg, entity.mainTaskEnum.className); + //子任务泛型参数 + ClassName subTaskTypeVariable = + ClassName.get(entity.subTaskEnum.pkg, entity.subTaskEnum.className); + + builder.superclass( + ParameterizedTypeName.get(superClass, taskTypeVariable, subTaskTypeVariable)); + builder.addMethod(listener); + return builder.build(); + } + + private void createFile(JavaFile jf) throws IOException { + if (ProxyConstance.DEBUG) { + // 如果需要在控制台打印生成的文件,则去掉下面的注释 + jf.writeTo(System.out); + } else { + jf.writeTo(mFiler); + } + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java new file mode 100644 index 00000000..ef334390 --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ParamObtainUtil.java @@ -0,0 +1,221 @@ +/* + * 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.compiler; + +import java.lang.annotation.Annotation; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.ElementKind; +import javax.lang.model.element.ExecutableElement; +import javax.lang.model.element.Modifier; +import javax.lang.model.element.PackageElement; +import javax.lang.model.element.TypeElement; +import javax.lang.model.element.VariableElement; +import javax.lang.model.util.Elements; + +/** + * Created by Aria.Lao on 2017/9/6. + * 构建代理文件的参数获取工具 + */ +class ParamObtainUtil { + private Map mMethodParams = new HashMap<>(); + private Map> mListenerClass = new HashMap<>(); + private Elements mElementUtil; + + ParamObtainUtil(Elements elements) { + mElementUtil = elements; + } + + /** + * 获取需要创建的代理类参数 + */ + Map> getListenerClass() { + return mListenerClass; + } + + /** + * 获取搜索到的代理方法参数 + */ + Map getMethodParams() { + return mMethodParams; + } + + /** + * 查找并保存扫描到的方法 + */ + void saveMethod(TaskEnum taskEnum, RoundEnvironment roundEnv, + Class annotationClazz, int annotationType) { + for (Element element : roundEnv.getElementsAnnotatedWith(annotationClazz)) { + ElementKind kind = element.getKind(); + if (kind == ElementKind.METHOD) { + ExecutableElement method = (ExecutableElement) element; + TypeElement classElement = (TypeElement) method.getEnclosingElement(); + PackageElement packageElement = mElementUtil.getPackageOf(classElement); + checkDownloadMethod(taskEnum, method); + String methodName = method.getSimpleName().toString(); + String className = method.getEnclosingElement().toString(); //全类名\ + String key = className + taskEnum.proxySuffix; + ProxyClassParam proxyEntity = mMethodParams.get(key); + + if (proxyEntity == null) { + proxyEntity = new ProxyClassParam(); + proxyEntity.taskEnums = new HashSet<>(); + proxyEntity.packageName = packageElement.getQualifiedName().toString(); + proxyEntity.className = classElement.getSimpleName().toString(); + proxyEntity.proxyClassName = proxyEntity.className + taskEnum.proxySuffix; + proxyEntity.mainTaskEnum = taskEnum; + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB || taskEnum == TaskEnum.DOWNLOAD_GROUP) { + proxyEntity.subTaskEnum = TaskEnum.DOWNLOAD; + } + mMethodParams.put(key, proxyEntity); + } + proxyEntity.taskEnums.add(taskEnum); + if (proxyEntity.methods.get(taskEnum) == null) { + proxyEntity.methods.put(taskEnum, new HashMap, String>()); + } + proxyEntity.methods.get(taskEnum).put(annotationClazz, methodName); + proxyEntity.keyMappings.put(methodName, getValues(taskEnum, method, annotationType)); + } + } + } + + /** + * 获取注解的内容 + */ + private Set getValues(TaskEnum taskEnum, ExecutableElement method, int annotationType) { + String clsName = method.getEnclosingElement().toString(); + String[] keys = null; + switch (taskEnum) { + case DOWNLOAD: + keys = ValuesUtil.getDownloadValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD); + break; + case UPLOAD: + keys = ValuesUtil.getUploadValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_UPLOAD); + break; + case DOWNLOAD_GROUP: + keys = ValuesUtil.getDownloadGroupValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP); + break; + case DOWNLOAD_GROUP_SUB: + keys = ValuesUtil.getDownloadGroupSubValues(method, annotationType); + addListenerMapping(clsName, ProxyConstance.COUNT_DOWNLOAD_GROUP_SUB); + break; + } + return keys == null ? null : convertSet(keys); + } + + /** + * 添加方法映射 + * + * @param clsName 注解事件的类 + * @param key {@link ProxyConstance#COUNT_DOWNLOAD}、{@link ProxyConstance#COUNT_UPLOAD}、{@link + * ProxyConstance#COUNT_DOWNLOAD_GROUP}、{@link ProxyConstance#COUNT_DOWNLOAD_GROUP_SUB} + */ + void addListenerMapping(String clsName, String key) { + Set cls = mListenerClass.get(key); + if (cls == null) { + cls = new HashSet<>(); + mListenerClass.put(key, cls); + } + cls.add(clsName); + } + + /** + * 检查和下载相关的方法,如果被注解的方法为private或参数不合法,则抛异常 + */ + private void checkDownloadMethod(TaskEnum taskEnum, ExecutableElement method) { + String methodName = method.getSimpleName().toString(); + String className = method.getEnclosingElement().toString(); + Set modifiers = method.getModifiers(); + if (modifiers.contains(Modifier.PRIVATE)) { + throw new IllegalAccessError(className + "." + methodName + "不能为private方法"); + } + List params = (List) method.getParameters(); + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + if (params.size() != 2) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数错误, 参数只有两个,且第一个参数必须是" + + getCheckParams(taskEnum) + + ",第二个参数必须是" + + getCheckSubParams(taskEnum)); + } + } else { + if (params.size() != 1) { + throw new IllegalArgumentException( + className + "." + methodName + "参数错误, 参数只能有一个,且参数必须是" + getCheckParams(taskEnum)); + } + } + if (!params.get(0).asType().toString().equals(getCheckParams(taskEnum))) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数【" + + params.get(0).getSimpleName() + + "】类型错误,参数必须是" + + getCheckParams(taskEnum)); + } + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + if (!params.get(1).asType().toString().equals(getCheckSubParams(taskEnum))) { + throw new IllegalArgumentException(className + + "." + + methodName + + "参数【" + + params.get(0).getSimpleName() + + "】类型错误,参数必须是" + + getCheckSubParams(taskEnum)); + } + } + } + + /** + * 字符串数组转set + * + * @param keys 注解中查到的key + */ + private Set convertSet(final String[] keys) { + if (keys == null || keys.length == 0) { + return null; + } + if (keys[0].isEmpty()) return null; + Set set = new HashSet<>(); + Collections.addAll(set, keys); + return set; + } + + private String getCheckParams(TaskEnum taskEnum) { + return taskEnum.pkg + "." + taskEnum.className; + } + + /** + * 检查任务组子任务第二个参数 + */ + private String getCheckSubParams(TaskEnum taskEnum) { + if (taskEnum == TaskEnum.DOWNLOAD_GROUP_SUB) { + return TaskEnum.DOWNLOAD.pkg + "." + TaskEnum.DOWNLOAD.className; + } + return ""; + } +} diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java b/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java index 161a2214..2ad5d754 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/PrintLog.java @@ -55,7 +55,7 @@ class PrintLog { mMessager.printMessage(Diagnostic.Kind.ERROR, String.format(msg, args)); } - private void warning(String msg) { + public void warning(String msg) { mMessager.printMessage(Diagnostic.Kind.WARNING, msg); } diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java similarity index 75% rename from AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java rename to AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java index 3cc813aa..60aaa60a 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyMethodParam.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyClassParam.java @@ -22,11 +22,30 @@ import java.util.Set; /** * Created by Aria.Lao on 2017/6/7. - * 创建代理方法的参数 + * 代理类参数 */ -class ProxyMethodParam { +class ProxyClassParam { + /** + * 代理文件名 + */ + String proxyClassName; + /** + * 被代理的类所在的包 + */ String packageName; + /** + * 被代理的类 + */ String className; + /** + * 主任务泛型参数 + */ + TaskEnum mainTaskEnum; + /** + * 子任务泛型参数 + */ + TaskEnum subTaskEnum = TaskEnum.NORMAL; + Set taskEnums; Map> keyMappings = new HashMap<>(); Map, String>> methods = new HashMap<>(); diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java index 98fcb980..623f95c0 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ProxyConstance.java @@ -20,6 +20,7 @@ package com.arialyy.compiler; * 扫描器常量 */ interface ProxyConstance { + boolean DEBUG = false; /** * 设置观察者的方法 */ @@ -41,6 +42,7 @@ interface ProxyConstance { String COUNT_DOWNLOAD = "download"; String COUNT_DOWNLOAD_GROUP = "downloadGroup"; + String COUNT_DOWNLOAD_GROUP_SUB = "downloadGroupSub"; String COUNT_UPLOAD = "upload"; String COUNT_METHOD_DOWNLOAD = "getDownloadCounter"; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java b/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java index 7620f1df..d7e2a9db 100644 --- a/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/TaskEnum.java @@ -22,9 +22,11 @@ package com.arialyy.compiler; enum TaskEnum { DOWNLOAD("com.arialyy.aria.core.download", "DownloadTask", "$$DownloadListenerProxy"), DOWNLOAD_GROUP("com.arialyy.aria.core.download", - "DownloadGroupTask", "$$DownloadGroupListenerProxy"), UPLOAD("com.arialyy.aria.core.upload", - "UploadTask", "$$UploadListenerProxy"), UPLOAD_GROUP("com.arialyy.aria.core.upload", - "UploadGroupTask", "$$UploadGroupListenerProxy"); + "DownloadGroupTask", "$$DownloadGroupListenerProxy"), DOWNLOAD_GROUP_SUB( + "com.arialyy.aria.core.download", "DownloadGroupTask", + "$$DownloadGroupListenerProxy"), UPLOAD("com.arialyy.aria.core.upload", "UploadTask", + "$$UploadListenerProxy"), UPLOAD_GROUP("com.arialyy.aria.core.upload", "UploadGroupTask", + "$$UploadGroupListenerProxy"), NORMAL("com.arialyy.aria.core.inf", "AbsNormalTask", ""); String pkg, className, proxySuffix; diff --git a/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java b/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java new file mode 100644 index 00000000..86d5231c --- /dev/null +++ b/AriaCompiler/src/main/java/com/arialyy/compiler/ValuesUtil.java @@ -0,0 +1,175 @@ +/* + * 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.compiler; + +import com.arialyy.annotations.Download; +import com.arialyy.annotations.DownloadGroup; +import com.arialyy.annotations.Upload; +import javax.lang.model.element.ExecutableElement; + +/** + * Created by lyy on 2017/9/6. + * 获取注解value工具 + */ +final class ValuesUtil { + /** + * 获取下载任务组子任务的的注解数据 + */ + static String[] getDownloadGroupSubValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(DownloadGroup.onSubTaskPre.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(DownloadGroup.onSubTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(DownloadGroup.onSubTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(DownloadGroup.onSubTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(DownloadGroup.onSubTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(DownloadGroup.onSubTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(DownloadGroup.onSubTaskFail.class).value(); + break; + } + return values; + } + + /** + * 获取下载任务组的注解数据 + */ + static String[] getDownloadGroupValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(DownloadGroup.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(DownloadGroup.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(DownloadGroup.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(DownloadGroup.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(DownloadGroup.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(DownloadGroup.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(DownloadGroup.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(DownloadGroup.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(DownloadGroup.onTaskFail.class).value(); + break; + } + return values; + } + + /** + * 获取上传的注解数据 + */ + static String[] getUploadValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(Upload.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + //values = method.getAnnotation(Upload.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(Upload.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(Upload.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(Upload.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(Upload.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(Upload.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(Upload.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(Upload.onTaskFail.class).value(); + break; + case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: + //values = method.getAnnotation(Upload.onNoSupportBreakPoint.class).value(); + break; + } + return values; + } + + /** + * 获取下载的注解数据 + */ + static String[] getDownloadValues(ExecutableElement method, int annotationType) { + String[] values = null; + switch (annotationType) { + case ProxyConstance.PRE: + values = method.getAnnotation(Download.onPre.class).value(); + break; + case ProxyConstance.TASK_PRE: + values = method.getAnnotation(Download.onTaskPre.class).value(); + break; + case ProxyConstance.TASK_RESUME: + values = method.getAnnotation(Download.onTaskResume.class).value(); + break; + case ProxyConstance.TASK_START: + values = method.getAnnotation(Download.onTaskStart.class).value(); + break; + case ProxyConstance.TASK_RUNNING: + values = method.getAnnotation(Download.onTaskRunning.class).value(); + break; + case ProxyConstance.TASK_STOP: + values = method.getAnnotation(Download.onTaskStop.class).value(); + break; + case ProxyConstance.TASK_COMPLETE: + values = method.getAnnotation(Download.onTaskComplete.class).value(); + break; + case ProxyConstance.TASK_CANCEL: + values = method.getAnnotation(Download.onTaskCancel.class).value(); + break; + case ProxyConstance.TASK_FAIL: + values = method.getAnnotation(Download.onTaskFail.class).value(); + break; + case ProxyConstance.TASK_NO_SUPPORT_BREAKPOINT: + values = method.getAnnotation(Download.onNoSupportBreakPoint.class).value(); + break; + } + return values; + } +} diff --git a/CHINESE_README.md b/CHINESE_README.md index 391c0f1b..72a13264 100644 --- a/CHINESE_README.md +++ b/CHINESE_README.md @@ -317,6 +317,7 @@ Aria.download(this).load(DOWNLOAD_URL).setExtendField(str) -keep class com.arialyy.aria.**{*;} -keep class **$$DownloadListenerProxy{ *; } -keep class **$$UploadListenerProxy{ *; } +-keep class **$$DownloadGroupSubListenerProxy{*;} -keepclasseswithmembernames class * { @Download.* ; @Upload.* ; diff --git a/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java index 15c0fa88..a2e47588 100644 --- a/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java +++ b/app/src/main/java/com/arialyy/simple/download/SimpleNotification.java @@ -20,6 +20,7 @@ import android.app.NotificationManager; import android.content.Context; import android.os.Environment; import android.support.v4.app.NotificationCompat; +import com.arialyy.annotations.Download; import com.arialyy.aria.core.Aria; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.simple.R; @@ -50,14 +51,13 @@ public class SimpleNotification { .setProgress(100, 0, false) .setSmallIcon(R.mipmap.ic_launcher); mManager.notify(mNotifiyId, mBuilder.build()); - Aria.download(mContext).addSchedulerListener(new DownloadCallback(mBuilder, mManager)); + Aria.download(mContext).register(); } public void start() { Aria.download(mContext) .load(DOWNLOAD_URL) - .setDownloadPath( - Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk") + .setDownloadPath(Environment.getExternalStorageDirectory() + "/Download/消灭星星.apk") .start(); } @@ -65,47 +65,31 @@ public class SimpleNotification { Aria.download(mContext).load(DOWNLOAD_URL).pause(); } - private static class DownloadCallback extends Aria.DownloadSchedulerListener { - NotificationCompat.Builder mBuilder; - NotificationManager mManager; - - private DownloadCallback(NotificationCompat.Builder builder, NotificationManager manager) { - mBuilder = builder; - mManager = manager; - } - - @Override public void onTaskStart(DownloadTask task) { - super.onTaskStart(task); - } + @Download.onTaskStart public void onTaskStart(DownloadTask task) { + } - @Override public void onTaskPre(DownloadTask task) { - super.onTaskPre(task); - } + @Download.onTaskPre public void onTaskPre(DownloadTask task) { + } - @Override public void onTaskStop(DownloadTask task) { - super.onTaskStop(task); - } + @Download.onTaskStop public void onTaskStop(DownloadTask task) { + } - @Override public void onTaskRunning(DownloadTask task) { - super.onTaskRunning(task); - long len = task.getFileSize(); - int p = (int) (task.getCurrentProgress() * 100 / len); - if (mBuilder != null) { - mBuilder.setProgress(100, p, false); - mManager.notify(mNotifiyId, mBuilder.build()); - } + @Download.onTaskRunning public void onTaskRunning(DownloadTask task) { + long len = task.getFileSize(); + int p = (int) (task.getCurrentProgress() * 100 / len); + if (mBuilder != null) { + mBuilder.setProgress(100, p, false); + mManager.notify(mNotifiyId, mBuilder.build()); } + } - @Override public void onTaskComplete(DownloadTask task) { - super.onTaskComplete(task); - if (mBuilder != null) { - mBuilder.setProgress(100, 100, false); - mManager.notify(mNotifiyId, mBuilder.build()); - } + @Download.onTaskComplete public void onTaskComplete(DownloadTask task) { + if (mBuilder != null) { + mBuilder.setProgress(100, 100, false); + mManager.notify(mNotifiyId, mBuilder.build()); } + } - @Override public void onTaskCancel(DownloadTask task) { - super.onTaskCancel(task); - } + @Download.onTaskCancel public void onTaskCancel(DownloadTask task) { } } diff --git a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java index 53bf464f..bef50a66 100644 --- a/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java +++ b/app/src/main/java/com/arialyy/simple/download/SingleTaskActivity.java @@ -27,7 +27,9 @@ import android.widget.RadioGroup; import android.widget.Toast; import butterknife.Bind; import com.arialyy.annotations.Download; +import com.arialyy.annotations.DownloadGroup; import com.arialyy.aria.core.Aria; +import com.arialyy.aria.core.download.DownloadGroupTask; import com.arialyy.aria.core.download.DownloadTarget; import com.arialyy.aria.core.download.DownloadTask; import com.arialyy.aria.core.download.DownloadTaskEntity; @@ -114,6 +116,14 @@ public class SingleTaskActivity extends BaseActivity { return true; } + @DownloadGroup.onSubTaskFail void onSubTaskFail(DownloadGroupTask groupTask, DownloadTask subTask){ + + } + + @DownloadGroup.onPre void onGroupPre(DownloadGroupTask groupTask){ + + } + @Download.onPre(DOWNLOAD_URL) protected void onPre(DownloadTask task) { setBtState(false); } diff --git a/gradle.properties b/gradle.properties index 299cc485..61c4b125 100644 --- a/gradle.properties +++ b/gradle.properties @@ -13,3 +13,5 @@ # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true #Wed Dec 07 20:19:22 CST 2016 +org.gradle.daemon=true +org.gradle.jvmargs=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005 \ No newline at end of file