rename hego to doric
This commit is contained in:
2
Android/doric/src/main/AndroidManifest.xml
Normal file
2
Android/doric/src/main/AndroidManifest.xml
Normal file
@@ -0,0 +1,2 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.github.pengfeizhou.doric" />
|
@@ -0,0 +1,33 @@
|
||||
package com.github.pengfeizhou.doric;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class Doric {
|
||||
private static Application sApplication;
|
||||
|
||||
public static void init(Application application) {
|
||||
sApplication = application;
|
||||
}
|
||||
|
||||
public static Application application() {
|
||||
return sApplication;
|
||||
}
|
||||
|
||||
private static Map<String, String> bundles = new ConcurrentHashMap<>();
|
||||
|
||||
public static void registerJSBundle(String name, String bundle) {
|
||||
bundles.put(name, bundle);
|
||||
}
|
||||
|
||||
public static String getJSBundle(String name) {
|
||||
return bundles.get(name);
|
||||
}
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
package com.github.pengfeizhou.doric;
|
||||
|
||||
import com.github.pengfeizhou.doric.utils.DoricSettableFuture;
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricContext {
|
||||
private static AtomicInteger sCounter = new AtomicInteger();
|
||||
private final String mContextId;
|
||||
|
||||
private DoricContext(String contextId) {
|
||||
this.mContextId = contextId;
|
||||
}
|
||||
|
||||
public static DoricContext createContext(String script, String alias) {
|
||||
String contextId = String.valueOf(sCounter.incrementAndGet());
|
||||
DoricDriver.getInstance().createPage(contextId, script, alias);
|
||||
return new DoricContext(contextId);
|
||||
}
|
||||
|
||||
public DoricSettableFuture<JSDecoder> callEntity(String methodName, Object... args) {
|
||||
return DoricDriver.getInstance().invokeContextMethod(mContextId, methodName, args);
|
||||
}
|
||||
|
||||
public void teardown() {
|
||||
DoricDriver.getInstance().destoryContext(mContextId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,40 @@
|
||||
package com.github.pengfeizhou.doric;
|
||||
|
||||
import com.github.pengfeizhou.doric.engine.DoricJSEngine;
|
||||
import com.github.pengfeizhou.doric.utils.DoricSettableFuture;
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricDriver {
|
||||
private final DoricJSEngine doricJSEngine;
|
||||
|
||||
public DoricSettableFuture<JSDecoder> invokeContextMethod(final String contextId, final String method, final Object... args) {
|
||||
return doricJSEngine.invokeContextEntityMethod(contextId, method, args);
|
||||
}
|
||||
|
||||
private static class Inner {
|
||||
private static final DoricDriver sInstance = new DoricDriver();
|
||||
}
|
||||
|
||||
private DoricDriver() {
|
||||
doricJSEngine = new DoricJSEngine();
|
||||
}
|
||||
|
||||
public static DoricDriver getInstance() {
|
||||
return Inner.sInstance;
|
||||
}
|
||||
|
||||
public void createPage(final String contextId, final String script, final String source) {
|
||||
doricJSEngine.prepareContext(contextId, script, source);
|
||||
}
|
||||
|
||||
public void destoryContext(String contextId) {
|
||||
doricJSEngine.destroyContext(contextId);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,54 @@
|
||||
package com.github.pengfeizhou.doric;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricPanel extends FrameLayout {
|
||||
|
||||
private DoricContext mDoricContext;
|
||||
|
||||
public DoricPanel(@NonNull Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public DoricPanel(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public DoricPanel(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
|
||||
public DoricPanel(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
}
|
||||
|
||||
public void config(String script, String alias) {
|
||||
DoricContext doricContext = DoricContext.createContext(script, alias);
|
||||
config(doricContext);
|
||||
}
|
||||
|
||||
public void config(DoricContext doricContext) {
|
||||
mDoricContext = doricContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
}
|
||||
|
||||
public DoricContext getDoricContext() {
|
||||
return mDoricContext;
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
package com.github.pengfeizhou.doric.bridge;
|
||||
|
||||
import com.github.pengfeizhou.doric.DoricContext;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public abstract class BaseModule {
|
||||
private final DoricContext doricContext;
|
||||
|
||||
protected BaseModule(DoricContext doricContext) {
|
||||
this.doricContext = doricContext;
|
||||
}
|
||||
|
||||
public abstract String moduleName();
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package com.github.pengfeizhou.doric.bridge;
|
||||
|
||||
import com.github.pengfeizhou.doric.DoricContext;
|
||||
import com.github.pengfeizhou.doric.extension.DoricMethod;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class ModalModule extends BaseModule {
|
||||
|
||||
protected ModalModule(DoricContext doricContext) {
|
||||
super(doricContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String moduleName() {
|
||||
return "modal";
|
||||
}
|
||||
|
||||
@DoricMethod(name = "toast")
|
||||
public void toast() {
|
||||
|
||||
}
|
||||
}
|
@@ -0,0 +1,249 @@
|
||||
package com.github.pengfeizhou.doric.engine;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.github.pengfeizhou.doric.Doric;
|
||||
import com.github.pengfeizhou.doric.extension.DoricBridgeExtension;
|
||||
import com.github.pengfeizhou.doric.utils.DoricConstant;
|
||||
import com.github.pengfeizhou.doric.utils.DoricLog;
|
||||
import com.github.pengfeizhou.doric.utils.DoricSettableFuture;
|
||||
import com.github.pengfeizhou.doric.extension.DoricTimerExtension;
|
||||
import com.github.pengfeizhou.doric.utils.DoricUtils;
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.TimerCallback {
|
||||
private final Handler mJSHandler;
|
||||
private final DoricBridgeExtension mDoricBridgeExtension;
|
||||
private IDoricJSE mDoricJSE;
|
||||
private DoricTimerExtension mTimerExtension;
|
||||
|
||||
public DoricJSEngine() {
|
||||
HandlerThread handlerThread = new HandlerThread(this.getClass().getSimpleName());
|
||||
handlerThread.start();
|
||||
Looper looper = handlerThread.getLooper();
|
||||
mJSHandler = new Handler(looper, this);
|
||||
mJSHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
initJSExecutor();
|
||||
initHugoRuntime();
|
||||
}
|
||||
});
|
||||
mTimerExtension = new DoricTimerExtension(looper, this);
|
||||
mDoricBridgeExtension = new DoricBridgeExtension();
|
||||
}
|
||||
|
||||
|
||||
private void initJSExecutor() {
|
||||
mDoricJSE = new DoricJSExecutor();
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_LOG, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String type = args[0].string();
|
||||
String message = args[1].string();
|
||||
switch (type) {
|
||||
case "w":
|
||||
DoricLog.w(message, "_js");
|
||||
break;
|
||||
case "e":
|
||||
DoricLog.e(message, "_js");
|
||||
break;
|
||||
default:
|
||||
DoricLog.d(message, "_js");
|
||||
break;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_REQUIRE, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String name = args[0].string();
|
||||
String content = Doric.getJSBundle(name);
|
||||
if (TextUtils.isEmpty(content)) {
|
||||
DoricLog.e("error");
|
||||
return new JavaValue(false);
|
||||
}
|
||||
mDoricJSE.loadJS(packageModuleScript(name, content), "Module://" + name);
|
||||
return new JavaValue(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new JavaValue(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_TIMER_SET, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
mTimerExtension.setTimer(
|
||||
args[0].number().longValue(),
|
||||
args[1].number().longValue(),
|
||||
args[2].bool());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_TIMER_CLEAR, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
mTimerExtension.clearTimer(args[0].number().longValue());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
mDoricJSE.injectGlobalJSFunction(DoricConstant.INJECT_BRIDGE, new JavaFunction() {
|
||||
@Override
|
||||
public JavaValue exec(JSDecoder[] args) {
|
||||
try {
|
||||
String contextId = args[0].string();
|
||||
String module = args[1].string();
|
||||
String method = args[2].string();
|
||||
String callbackId = args[3].string();
|
||||
JSDecoder jsDecoder = args[4];
|
||||
return mDoricBridgeExtension.callNative(contextId, module, method, callbackId, jsDecoder);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initHugoRuntime() {
|
||||
loadBuiltinJS(DoricConstant.DORIC_BUNDLE_SANDBOX);
|
||||
String libName = DoricConstant.DORIC_MODULE_LIB;
|
||||
String libJS = DoricUtils.readAssetFile(DoricConstant.DORIC_BUNDLE_LIB);
|
||||
mDoricJSE.loadJS(packageModuleScript(libName, libJS), "Module://" + libName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void teardown() {
|
||||
mDoricJSE.teardown();
|
||||
}
|
||||
|
||||
private void loadBuiltinJS(String assetName) {
|
||||
String script = DoricUtils.readAssetFile(assetName);
|
||||
mDoricJSE.loadJS(script, "Assets://" + assetName);
|
||||
}
|
||||
|
||||
public void prepareContext(final String contextId, final String script, final String source) {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDoricJSE.loadJS(packageContextScript(contextId, script), "Context://" + source);
|
||||
}
|
||||
};
|
||||
doOnJSThread(runnable);
|
||||
}
|
||||
|
||||
public void doOnJSThread(Runnable runnable) {
|
||||
if (isJSThread()) {
|
||||
runnable.run();
|
||||
} else {
|
||||
mJSHandler.post(runnable);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroyContext(final String contextId) {
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mDoricJSE.loadJS(String.format(DoricConstant.TEMPLATE_CONTEXT_DESTROY, contextId), "_Context://" + contextId);
|
||||
}
|
||||
};
|
||||
doOnJSThread(runnable);
|
||||
}
|
||||
|
||||
private String packageContextScript(String contextId, String content) {
|
||||
return String.format(DoricConstant.TEMPLATE_CONTEXT_CREATE, content, contextId, contextId);
|
||||
}
|
||||
|
||||
private String packageModuleScript(String moduleName, String content) {
|
||||
return String.format(DoricConstant.TEMPLATE_MODULE, moduleName, content);
|
||||
}
|
||||
|
||||
public boolean isJSThread() {
|
||||
return Looper.myLooper() == mJSHandler.getLooper();
|
||||
}
|
||||
|
||||
public DoricSettableFuture<JSDecoder> invokeContextEntityMethod(final String contextId, final String method, final Object... args) {
|
||||
final Object[] nArgs = new Object[args.length + 2];
|
||||
nArgs[0] = contextId;
|
||||
nArgs[1] = method;
|
||||
if (args.length > 0) {
|
||||
System.arraycopy(args, 0, nArgs, 2, args.length);
|
||||
}
|
||||
return invokeDoricMethod(DoricConstant.DORIC_CONTEXT_INVOKE, nArgs);
|
||||
}
|
||||
|
||||
|
||||
public DoricSettableFuture<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
|
||||
final DoricSettableFuture<JSDecoder> settableFuture = new DoricSettableFuture<>();
|
||||
Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ArrayList<JavaValue> values = new ArrayList<>();
|
||||
for (Object arg : args) {
|
||||
if (arg == null) {
|
||||
values.add(new JavaValue());
|
||||
} else if (arg instanceof JSONObject) {
|
||||
values.add(new JavaValue((JSONObject) arg));
|
||||
} else if (arg instanceof String) {
|
||||
values.add(new JavaValue((String) arg));
|
||||
} else if (arg instanceof Integer) {
|
||||
values.add(new JavaValue((Integer) arg));
|
||||
} else if (arg instanceof Long) {
|
||||
values.add(new JavaValue((Long) arg));
|
||||
} else if (arg instanceof Double) {
|
||||
values.add(new JavaValue((Double) arg));
|
||||
} else if (arg instanceof Boolean) {
|
||||
values.add(new JavaValue((Boolean) arg));
|
||||
} else if (arg instanceof JavaValue) {
|
||||
values.add((JavaValue) arg);
|
||||
} else {
|
||||
values.add(new JavaValue(String.valueOf(arg)));
|
||||
}
|
||||
}
|
||||
settableFuture.set(mDoricJSE.invokeMethod(DoricConstant.GLOBAL_DORIC, method,
|
||||
values.toArray(new JavaValue[values.size()]), true));
|
||||
}
|
||||
};
|
||||
doOnJSThread(runnable);
|
||||
return settableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void callback(long timerId) {
|
||||
invokeDoricMethod(DoricConstant.DORIC_TIMER_CALLBACK, timerId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
package com.github.pengfeizhou.doric.engine;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSExecutor;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricJSExecutor implements IDoricJSE {
|
||||
|
||||
private final JSExecutor mJSExecutor;
|
||||
|
||||
public DoricJSExecutor() {
|
||||
this.mJSExecutor = JSExecutor.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadJS(String script, String source) throws JSRuntimeException {
|
||||
return mJSExecutor.loadJS(script, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException {
|
||||
return mJSExecutor.evaluateJS(script, source, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSFunction(String name, JavaFunction javaFunction) {
|
||||
mJSExecutor.injectGlobalJSFunction(name, javaFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSObject(String name, JavaValue javaValue) {
|
||||
mJSExecutor.injectGlobalJSObject(name, javaValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException {
|
||||
return mJSExecutor.invokeMethod(objectName, functionName, javaValues, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() {
|
||||
mJSExecutor.destroy();
|
||||
}
|
||||
}
|
@@ -0,0 +1,64 @@
|
||||
package com.github.pengfeizhou.doric.engine;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public interface IDoricJSE {
|
||||
/**
|
||||
* 执行JS语句
|
||||
*
|
||||
* @param script 执行的JS语句
|
||||
* @param source 该JS语句对应的文件名,在输出错误的堆栈信息时有用
|
||||
* @return 返回JS语句的执行结果,以String形式返回
|
||||
* @throws JSRuntimeException 如果执行的脚本有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
String loadJS(String script, String source) throws JSRuntimeException;
|
||||
|
||||
/**
|
||||
* 执行JS语句
|
||||
*
|
||||
* @param script 执行的JS语句
|
||||
* @param source 该JS语句对应的文件名,在输出错误的堆栈信息时有用
|
||||
* @param hashKey 是否在返回对象序列化时将key hash化
|
||||
* @return 返回JS语句的执行结果,以二进制数据的形式返回
|
||||
* @throws JSRuntimeException 如果执行的脚本有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException;
|
||||
|
||||
|
||||
/**
|
||||
* 向JS注入全局方法,由java实现
|
||||
*
|
||||
* @param name js的方法名
|
||||
* @param javaFunction java中对应的实现类
|
||||
*/
|
||||
void injectGlobalJSFunction(String name, JavaFunction javaFunction);
|
||||
|
||||
/**
|
||||
* 向JS注入全局变量
|
||||
*
|
||||
* @param name js中的变量名
|
||||
* @param javaValue 注入的全局变量,按Value进行组装
|
||||
*/
|
||||
void injectGlobalJSObject(String name, JavaValue javaValue);
|
||||
|
||||
/**
|
||||
* 执行JS某个方法
|
||||
*
|
||||
* @param objectName 执行的方法所属的变量名,如果方法为全局方法,该参数传null
|
||||
* @param functionName 执行的方法名
|
||||
* @param javaValues 方法需要的参数列表,按数组传入
|
||||
* @param hashKey 是否在返回对象序列化时将key hash化
|
||||
* @throws JSRuntimeException 如果执行的方法有异常,会抛出包含堆栈的JSRuntimeException
|
||||
*/
|
||||
JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException;
|
||||
|
||||
void teardown();
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.github.pengfeizhou.doric.extension;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricBridgeExtension {
|
||||
public DoricBridgeExtension() {
|
||||
|
||||
}
|
||||
|
||||
public JavaValue callNative(String contextId, String module, String method, String callbackId, JSDecoder jsDecoder) {
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.github.pengfeizhou.doric.extension;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DoricMethod {
|
||||
String name() default "";
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
package com.github.pengfeizhou.doric.extension;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
@Documented
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface DoricModule {
|
||||
String name() default "";
|
||||
}
|
@@ -0,0 +1,66 @@
|
||||
package com.github.pengfeizhou.doric.extension;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricTimerExtension implements Handler.Callback {
|
||||
|
||||
private static final int MSG_TIMER = 0;
|
||||
private final Handler mTimerHandler;
|
||||
private final TimerCallback mTimerCallback;
|
||||
private Set<Long> mDeletedTimerIds = new HashSet<>();
|
||||
|
||||
public DoricTimerExtension(Looper looper, TimerCallback timerCallback) {
|
||||
mTimerHandler = new Handler(looper, this);
|
||||
mTimerCallback = timerCallback;
|
||||
}
|
||||
|
||||
public void setTimer(long timerId, long time, boolean repeat) {
|
||||
TimerInfo timerInfo = new TimerInfo();
|
||||
timerInfo.timerId = timerId;
|
||||
timerInfo.time = time;
|
||||
timerInfo.repeat = repeat;
|
||||
mTimerHandler.sendMessageDelayed(Message.obtain(mTimerHandler, MSG_TIMER, timerInfo), timerInfo.time);
|
||||
}
|
||||
|
||||
public void clearTimer(long timerId) {
|
||||
mDeletedTimerIds.add(timerId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMessage(Message msg) {
|
||||
if (msg.obj instanceof TimerInfo) {
|
||||
TimerInfo timerInfo = (TimerInfo) msg.obj;
|
||||
if (mDeletedTimerIds.contains(timerInfo.timerId)) {
|
||||
mDeletedTimerIds.remove(timerInfo.timerId);
|
||||
} else {
|
||||
mTimerCallback.callback(timerInfo.timerId);
|
||||
if (timerInfo.repeat) {
|
||||
mTimerHandler.sendMessageDelayed(Message.obtain(mTimerHandler, MSG_TIMER, timerInfo), timerInfo.time);
|
||||
} else {
|
||||
mDeletedTimerIds.remove(timerInfo.timerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private class TimerInfo {
|
||||
long timerId;
|
||||
long time;
|
||||
boolean repeat;
|
||||
}
|
||||
|
||||
public interface TimerCallback {
|
||||
void callback(long timerId);
|
||||
}
|
||||
}
|
@@ -0,0 +1,44 @@
|
||||
package com.github.pengfeizhou.doric.extension;
|
||||
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class ModuleClassInfo {
|
||||
|
||||
private Class clz;
|
||||
|
||||
private Object instance;
|
||||
|
||||
private Map<String, Method> methodMap = new HashMap<>();
|
||||
public boolean stringify = false;
|
||||
|
||||
public ModuleClassInfo(Class clz) {
|
||||
this.clz = clz;
|
||||
try {
|
||||
this.instance = clz.newInstance();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Method[] methods = clz.getMethods();
|
||||
if (methods != null) {
|
||||
for (Method method : methods) {
|
||||
DoricMethod doricMethod = method.getAnnotation(DoricMethod.class);
|
||||
if (doricMethod != null) {
|
||||
if (TextUtils.isEmpty(doricMethod.name())) {
|
||||
methodMap.put(method.getName(), method);
|
||||
} else {
|
||||
methodMap.put(doricMethod.name(), method);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
package com.github.pengfeizhou.doric.utils;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricConstant {
|
||||
public static final String DORIC_BUNDLE_SANDBOX = "doric-sandbox.js";
|
||||
public static final String DORIC_BUNDLE_LIB = "doric-lib.js";
|
||||
public static final String DORIC_MODULE_LIB = "./index";
|
||||
|
||||
|
||||
|
||||
public static final String INJECT_LOG = "nativeLog";
|
||||
public static final String INJECT_REQUIRE = "nativeRequire";
|
||||
public static final String INJECT_TIMER_SET = "nativeSetTimer";
|
||||
public static final String INJECT_TIMER_CLEAR = "nativeClearTimer";
|
||||
public static final String INJECT_BRIDGE = "nativeBridge";
|
||||
|
||||
public static final String TEMPLATE_CONTEXT_CREATE = "Reflect.apply(" +
|
||||
"function(doric,context,require,exports){" + "\n" +
|
||||
"%s" + "\n" +
|
||||
"},doric.jsObtainContext(\"%s\"),[" +
|
||||
"undefined," +
|
||||
"doric.jsObtainContext(\"%s\")," +
|
||||
"doric.__require__" +
|
||||
",{}" +
|
||||
"])";
|
||||
|
||||
public static final String TEMPLATE_MODULE = "Reflect.apply(doric.jsRegisterModule,this,[" +
|
||||
"\"%s\"," +
|
||||
"Reflect.apply(function(__module){" +
|
||||
"(function(module,exports,require){" + "\n" +
|
||||
"%s" + "\n" +
|
||||
"})(__module,__module.exports,doric.__require__);" +
|
||||
"\nreturn __module.exports;" +
|
||||
"},this,[{exports:{}}])" +
|
||||
"])";
|
||||
public static final String TEMPLATE_CONTEXT_DESTROY = "doric.jsRelease(%s)";
|
||||
public static final String GLOBAL_DORIC = "doric";
|
||||
public static final String DORIC_CONTEXT_RELEASE = "jsReleaseContext";
|
||||
public static final String DORIC_CONTEXT_INVOKE = "jsCallEntityMethod";
|
||||
public static final String DORIC_TIMER_CALLBACK = "jsCallbackTimer";
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package com.github.pengfeizhou.doric.utils;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.github.pengfeizhou.doric.Doric;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricLog {
|
||||
private static String TAG = Doric.class.getSimpleName();
|
||||
|
||||
public static void d(String message, String... suffix) {
|
||||
StringBuilder stringBuilder = new StringBuilder(TAG);
|
||||
for (String s : suffix) {
|
||||
stringBuilder.append(s);
|
||||
}
|
||||
Log.d(stringBuilder.toString(), message);
|
||||
}
|
||||
|
||||
public static void w(String message, String... suffix) {
|
||||
StringBuilder stringBuilder = new StringBuilder(TAG);
|
||||
for (String s : suffix) {
|
||||
stringBuilder.append(s);
|
||||
}
|
||||
Log.w(stringBuilder.toString(), message);
|
||||
}
|
||||
|
||||
public static void e(String message, String... suffix) {
|
||||
StringBuilder stringBuilder = new StringBuilder(TAG);
|
||||
for (String s : suffix) {
|
||||
stringBuilder.append(s);
|
||||
}
|
||||
Log.e(stringBuilder.toString(), message);
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
package com.github.pengfeizhou.doric.utils;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* A super simple Future-like class that can safely notify another Thread when a value is ready.
|
||||
* Does not support setting errors or canceling.
|
||||
*/
|
||||
public class DoricSettableFuture<T> {
|
||||
|
||||
private final CountDownLatch mReadyLatch = new CountDownLatch(1);
|
||||
private volatile
|
||||
T mResult;
|
||||
|
||||
/**
|
||||
* Sets the result. If another thread has called {@link #get}, they will immediately receive the
|
||||
* value. Must only be called once.
|
||||
*/
|
||||
public void set(T result) {
|
||||
if (mReadyLatch.getCount() == 0) {
|
||||
throw new RuntimeException("Result has already been set!");
|
||||
}
|
||||
mResult = result;
|
||||
mReadyLatch.countDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait up to the timeout time for another Thread to set a value on this future. If a value has
|
||||
* already been set, this method will return immediately.
|
||||
* <p>
|
||||
* NB: For simplicity, we catch and wrap InterruptedException. Do NOT use this class if you
|
||||
* are in the 1% of cases where you actually want to handle that.
|
||||
*/
|
||||
public T get(long timeoutMS) {
|
||||
try {
|
||||
if (!mReadyLatch.await(timeoutMS, TimeUnit.MILLISECONDS)) {
|
||||
throw new TimeoutException();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return mResult;
|
||||
}
|
||||
|
||||
public static class TimeoutException extends RuntimeException {
|
||||
|
||||
public TimeoutException() {
|
||||
super("Timed out waiting for future");
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package com.github.pengfeizhou.doric.utils;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
|
||||
import com.github.pengfeizhou.doric.Doric;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricUtils {
|
||||
public static String readAssetFile(String assetFile) {
|
||||
InputStream inputStream = null;
|
||||
try {
|
||||
AssetManager assetManager = Doric.application().getAssets();
|
||||
inputStream = assetManager.open(assetFile);
|
||||
int length = inputStream.available();
|
||||
byte[] buffer = new byte[length];
|
||||
inputStream.read(buffer);
|
||||
return new String(buffer);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
3
Android/doric/src/main/res/values/strings.xml
Normal file
3
Android/doric/src/main/res/values/strings.xml
Normal file
@@ -0,0 +1,3 @@
|
||||
<resources>
|
||||
<string name="app_name">Doric</string>
|
||||
</resources>
|
Reference in New Issue
Block a user