refactor: devkit depends on doric
This commit is contained in:
@@ -1,11 +0,0 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
public class DataModel {
|
||||
public String contextId;
|
||||
public String source;
|
||||
|
||||
public DataModel(String contextId, String source) {
|
||||
this.contextId = contextId;
|
||||
this.source = source;
|
||||
}
|
||||
}
|
@@ -0,0 +1,30 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricNativeDriver;
|
||||
import pub.doric.engine.IStatusCallback;
|
||||
|
||||
public class DoricContextDebuggable {
|
||||
private DoricContext doricContext;
|
||||
private DoricDebugDriver doricDebugDriver;
|
||||
|
||||
public DoricContextDebuggable(DoricContext doricContext) {
|
||||
this.doricContext = doricContext;
|
||||
}
|
||||
|
||||
public void startDebug() {
|
||||
doricDebugDriver = new DoricDebugDriver(new IStatusCallback() {
|
||||
@Override
|
||||
public void start() {
|
||||
doricContext.setDriver(doricDebugDriver);
|
||||
doricContext.reInit();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void stopDebug() {
|
||||
doricDebugDriver.destroy();
|
||||
doricContext.setDriver(DoricNativeDriver.getInstance());
|
||||
doricContext.reInit();
|
||||
}
|
||||
}
|
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import pub.doric.DoricRegistry;
|
||||
import pub.doric.IDoricDriver;
|
||||
import pub.doric.async.AsyncCall;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
import pub.doric.engine.IStatusCallback;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
/**
|
||||
* @Description: Doric
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-07-18
|
||||
*/
|
||||
public class DoricDebugDriver implements IDoricDriver {
|
||||
private final DoricJSEngine doricJSEngine;
|
||||
private final ExecutorService mBridgeExecutor;
|
||||
private final Handler mUIHandler;
|
||||
private final Handler mJSHandler;
|
||||
|
||||
|
||||
public DoricDebugDriver(IStatusCallback statusCallback) {
|
||||
doricJSEngine = new DoricDebugJSEngine(statusCallback);
|
||||
mBridgeExecutor = Executors.newCachedThreadPool();
|
||||
mUIHandler = new Handler(Looper.getMainLooper());
|
||||
mJSHandler = doricJSEngine.getJSHandler();
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
|
||||
@Override
|
||||
public JSDecoder call() {
|
||||
try {
|
||||
return doricJSEngine.invokeDoricMethod(method, args);
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("invokeDoricMethod(%s,...),error is %s", method, e.getLocalizedMessage());
|
||||
return new JSDecoder(null);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> AsyncResult<T> asyncCall(Callable<T> callable, ThreadMode threadMode) {
|
||||
switch (threadMode) {
|
||||
case JS:
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, callable);
|
||||
case UI:
|
||||
return AsyncCall.ensureRunInHandler(mUIHandler, callable);
|
||||
case INDEPENDENT:
|
||||
default:
|
||||
return AsyncCall.ensureRunInExecutor(mBridgeExecutor, callable);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.prepareContext(contextId, script, source);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("createContext %s error is %s", source, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> destroyContext(final String contextId) {
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
doricJSEngine.destroyContext(contextId);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
DoricLog.e("destroyContext %s error is %s", contextId, e.getLocalizedMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public DoricRegistry getRegistry() {
|
||||
return doricJSEngine.getRegistry();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
doricJSEngine.teardown();
|
||||
mBridgeExecutor.shutdown();
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
import pub.doric.devkit.remote.DoricRemoteJSExecutor;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
import pub.doric.engine.IStatusCallback;
|
||||
|
||||
public class DoricDebugJSEngine extends DoricJSEngine {
|
||||
|
||||
private IStatusCallback statusCallback;
|
||||
|
||||
public DoricDebugJSEngine(IStatusCallback statusCallback) {
|
||||
super();
|
||||
this.statusCallback = statusCallback;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initJSEngine() {
|
||||
mDoricJSE = new DoricRemoteJSExecutor(statusCallback);
|
||||
}
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
package pub.doric.devkit;
|
||||
|
||||
public interface IStatusCallback {
|
||||
void start();
|
||||
}
|
181
Android/devkit/src/main/java/pub/doric/devkit/LocalServer.java
Normal file
181
Android/devkit/src/main/java/pub/doric/devkit/LocalServer.java
Normal file
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import android.util.Log;
|
||||
import android.webkit.MimeTypeMap;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSONBuilder;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.Inet4Address;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.SocketException;
|
||||
import java.util.Collection;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import fi.iki.elonen.NanoHTTPD;
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
|
||||
/**
|
||||
* @Description: com.github.penfeizhou.doricdemo
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 2019-08-03
|
||||
*/
|
||||
public class LocalServer extends NanoHTTPD {
|
||||
private final Context context;
|
||||
private Map<String, APICommand> commandMap = new HashMap<>();
|
||||
|
||||
public LocalServer(Context context, int port) {
|
||||
super(port);
|
||||
this.context = context;
|
||||
commandMap.put("allContexts", new APICommand() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "allContexts";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object exec(IHTTPSession session) {
|
||||
Collection<DoricContext> ret = DoricContextManager.aliveContexts();
|
||||
JSONArray jsonArray = new JSONArray();
|
||||
for (DoricContext doricContext : ret) {
|
||||
JSONBuilder jsonBuilder = new JSONBuilder();
|
||||
jsonBuilder.put("source", doricContext.getSource());
|
||||
jsonBuilder.put("id", doricContext.getContextId());
|
||||
jsonArray.put(jsonBuilder.toJSONObject());
|
||||
}
|
||||
return jsonArray;
|
||||
}
|
||||
});
|
||||
commandMap.put("context", new APICommand() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "context";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object exec(IHTTPSession session) {
|
||||
String id = session.getParms().get("id");
|
||||
DoricContext doricContext = DoricContextManager.getContext(id);
|
||||
if (doricContext != null) {
|
||||
return new JSONBuilder()
|
||||
.put("id", doricContext.getContextId())
|
||||
.put("source", doricContext.getSource())
|
||||
.put("script", doricContext.getScript())
|
||||
.toJSONObject();
|
||||
}
|
||||
return "{}";
|
||||
}
|
||||
});
|
||||
commandMap.put("reload", new APICommand() {
|
||||
@Override
|
||||
public String name() {
|
||||
return "reload";
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object exec(IHTTPSession session) {
|
||||
Map<String, String> files = new HashMap<>();
|
||||
try {
|
||||
session.parseBody(files);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
String id = session.getParms().get("id");
|
||||
DoricContext doricContext = DoricContextManager.getContext(id);
|
||||
if (doricContext != null) {
|
||||
try {
|
||||
JSONObject jsonObject = new JSONObject(files.get("postData"));
|
||||
doricContext.reload(jsonObject.optString("script"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "success";
|
||||
}
|
||||
return "fail";
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static String getIpAddressString() {
|
||||
try {
|
||||
for (Enumeration<NetworkInterface> enNetI = NetworkInterface
|
||||
.getNetworkInterfaces(); enNetI.hasMoreElements(); ) {
|
||||
NetworkInterface netI = enNetI.nextElement();
|
||||
for (Enumeration<InetAddress> enumIpAddr = netI
|
||||
.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
|
||||
InetAddress inetAddress = enumIpAddr.nextElement();
|
||||
if (inetAddress instanceof Inet4Address && !inetAddress.isLoopbackAddress()) {
|
||||
return inetAddress.getHostAddress();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "0.0.0.0";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
super.start();
|
||||
Log.d("Debugger", String.format("Open http://%s:8910/index.html to start debug", getIpAddressString()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response serve(IHTTPSession session) {
|
||||
Uri uri = Uri.parse(session.getUri());
|
||||
List<String> segments = uri.getPathSegments();
|
||||
if (segments.size() > 1 && "api".equals(segments.get(0))) {
|
||||
String cmd = segments.get(1);
|
||||
APICommand apiCommand = commandMap.get(cmd);
|
||||
if (apiCommand != null) {
|
||||
Object ret = apiCommand.exec(session);
|
||||
return NanoHTTPD.newFixedLengthResponse(Response.Status.OK, "application/json", ret.toString());
|
||||
}
|
||||
}
|
||||
String fileName = session.getUri().substring(1);
|
||||
AssetManager assetManager = context.getAssets();
|
||||
try {
|
||||
InputStream inputStream = assetManager.open("debugger/" + fileName);
|
||||
String mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(fileName.substring(fileName.lastIndexOf(".") + 1));
|
||||
return NanoHTTPD.newFixedLengthResponse(Response.Status.OK, mimeType, inputStream, inputStream.available());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return NanoHTTPD.newFixedLengthResponse(Response.Status.OK, "text/html", "HelloWorld");
|
||||
}
|
||||
|
||||
public interface APICommand {
|
||||
String name();
|
||||
|
||||
Object exec(IHTTPSession session);
|
||||
}
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* 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 pub.doric.devkit.remote;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
import com.github.pengfeizhou.jscore.JSRuntimeException;
|
||||
import com.github.pengfeizhou.jscore.JavaFunction;
|
||||
import com.github.pengfeizhou.jscore.JavaValue;
|
||||
|
||||
import pub.doric.engine.IDoricJSE;
|
||||
import pub.doric.engine.IStatusCallback;
|
||||
|
||||
public class DoricRemoteJSExecutor implements IDoricJSE {
|
||||
|
||||
private final RemoteJSExecutor mRemoteJSExecutor;
|
||||
|
||||
public DoricRemoteJSExecutor(IStatusCallback statusCallback) {
|
||||
this.mRemoteJSExecutor = new RemoteJSExecutor(statusCallback);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String loadJS(String script, String source) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.loadJS(script, source);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder evaluateJS(String script, String source, boolean hashKey) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.evaluateJS(script, source, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSFunction(String name, JavaFunction javaFunction) {
|
||||
mRemoteJSExecutor.injectGlobalJSFunction(name, javaFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectGlobalJSObject(String name, JavaValue javaValue) {
|
||||
mRemoteJSExecutor.injectGlobalJSObject(name, javaValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JSDecoder invokeMethod(String objectName, String functionName, JavaValue[] javaValues, boolean hashKey) throws JSRuntimeException {
|
||||
return mRemoteJSExecutor.invokeMethod(objectName, functionName, javaValues, hashKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void teardown() {
|
||||
mRemoteJSExecutor.destroy();
|
||||
}
|
||||
}
|
@@ -25,7 +25,7 @@ import okhttp3.WebSocket;
|
||||
import okhttp3.WebSocketListener;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.event.QuitDebugEvent;
|
||||
import pub.doric.devkit.IStatusCallback;
|
||||
import pub.doric.engine.IStatusCallback;
|
||||
|
||||
public class RemoteJSExecutor {
|
||||
private final WebSocket webSocket;
|
||||
|
@@ -15,20 +15,16 @@ import androidx.fragment.app.DialogFragment;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import pub.doric.DoricContext;
|
||||
import pub.doric.DoricContextManager;
|
||||
import pub.doric.devkit.BuildConfig;
|
||||
import pub.doric.devkit.DataModel;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.IDevKit;
|
||||
import pub.doric.devkit.R;
|
||||
|
||||
public class DebugContextPanel extends DialogFragment {
|
||||
|
||||
private ArrayList<DataModel> dataModels;
|
||||
|
||||
public DebugContextPanel(ArrayList<DataModel> dataModels) {
|
||||
this.dataModels = dataModels;
|
||||
public DebugContextPanel() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -61,22 +57,22 @@ public class DebugContextPanel extends DialogFragment {
|
||||
LinearLayout container = getView().findViewById(R.id.container);
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
|
||||
for (final DataModel dataModel : dataModels) {
|
||||
for (final DoricContext doricContext : DoricContextManager.aliveContexts()) {
|
||||
View cell = inflater.inflate(R.layout.layout_debug_context_cell, container, false);
|
||||
|
||||
TextView contextIdTextView = cell.findViewById(R.id.context_id_text_view);
|
||||
contextIdTextView.setText(dataModel.contextId);
|
||||
contextIdTextView.setText(doricContext.getContextId());
|
||||
|
||||
TextView sourceTextView = cell.findViewById(R.id.source_text_view);
|
||||
sourceTextView.setText(dataModel.source);
|
||||
sourceTextView.setText(doricContext.getSource());
|
||||
|
||||
cell.findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.addProperty("contextId", dataModel.contextId);
|
||||
jsonObject.addProperty("contextId", doricContext.getContextId());
|
||||
jsonObject.addProperty("projectHome", BuildConfig.PROJECT_HOME);
|
||||
jsonObject.addProperty("source", dataModel.source.replace(".js", ".ts"));
|
||||
jsonObject.addProperty("source", doricContext.getSource().replace(".js", ".ts"));
|
||||
DoricDev.sendDevCommand(IDevKit.Command.DEBUG, jsonObject);
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
@@ -21,11 +21,8 @@ import org.greenrobot.eventbus.EventBus;
|
||||
import org.greenrobot.eventbus.Subscribe;
|
||||
import org.greenrobot.eventbus.ThreadMode;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.disposables.Disposable;
|
||||
import io.reactivex.functions.Consumer;
|
||||
import pub.doric.devkit.DataModel;
|
||||
import pub.doric.devkit.DevKit;
|
||||
import pub.doric.devkit.DoricDev;
|
||||
import pub.doric.devkit.R;
|
||||
@@ -37,10 +34,7 @@ public class DevPanel extends BottomSheetDialogFragment {
|
||||
|
||||
public static boolean isDevConnected = false;
|
||||
|
||||
ArrayList<DataModel> dataModels;
|
||||
|
||||
public DevPanel(ArrayList<DataModel> dataModels) {
|
||||
this.dataModels = dataModels;
|
||||
public DevPanel() {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -85,7 +79,7 @@ public class DevPanel extends BottomSheetDialogFragment {
|
||||
getView().findViewById(R.id.debug_text_view).setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
DebugContextPanel debugContextPanel = new DebugContextPanel(dataModels);
|
||||
DebugContextPanel debugContextPanel = new DebugContextPanel();
|
||||
debugContextPanel.show(getActivity().getSupportFragmentManager(), "DebugContextPanel");
|
||||
dismissAllowingStateLoss();
|
||||
}
|
||||
|
Reference in New Issue
Block a user