blob: 4059d9721fd4af50b51b584745b8b57ceaad9247 [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.taobao.weex.bridge;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.adapter.IWXUserTrackAdapter;
import com.taobao.weex.common.IWXBridge;
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.dom.CSSShorthand;
import com.taobao.weex.layout.ContentBoxMeasurement;
import com.taobao.weex.utils.WXExceptionUtils;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXWsonJSONSwitch;
import java.io.Serializable;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
/**
* Communication interface for Java code and JavaScript code.
*/
public class WXBridge implements IWXBridge {
private native int nativeInitFrameworkEnv(String framework, WXParams params, String cacheDir, boolean pieSupport);
private native int nativeInitFramework(String framework, WXParams params);
private native int nativeExecJS(String instanceId, String name, String function, WXJSObject[] args);
private native int nativeExecJSService(String javascript);
public native byte[] nativeExecJSWithResult(String instanceId, String _namespace, String _function, WXJSObject[] args);
public native int nativeCreateInstanceContext(String instanceId, String name, String function, WXJSObject[] args);
public native int nativeDestoryInstance(String instanceId, String name, String function, WXJSObject[] args);
public native String nativeExecJSOnInstance(String instanceId, String script, int type);
private native void nativeTakeHeapSnapshot(String filename);
private native void nativeBindMeasurementToRenderObject(long ptr);
private native void nativeSetRenderContainerWrapContent(boolean wrap, String instanceId);
public native long[] nativeGetFirstScreenRenderTime(String instanceId);
public native long[] nativeGetRenderFinishTime(String instanceId);
private native void nativeSetDefaultHeightAndWidthIntoRootDom(String instanceId, float defaultWidth, float defaultHeight, boolean isWidthWrapContent, boolean isHeightWrapContent);
private native void nativeOnInstanceClose(String instanceId);
private native void nativeForceLayout(String instanceId);
private native boolean nativeNotifyLayout(String instanceId);
private native void nativeSetStyleWidth(String instanceId, String ref, float value);
private native void nativeSetStyleHeight(String instanceId, String ref, float value);
private native void nativeSetMargin(String instanceId, String ref, int edge, float value);
private native void nativeSetPadding(String instanceId, String ref, int edge, float value);
private native void nativeSetPosition(String instanceId, String ref, int edge, float value);
private native void nativeMarkDirty(String instanceId, String ref, boolean dirty);
private native void nativeRegisterCoreEnv(String key, String value);
/**
* update global config,
* @param config params
* */
public native void nativeUpdateGlobalConfig(String config);
public static final boolean MULTIPROCESS = true;
@Override
public int initFramework(String framework, WXParams params) {
return nativeInitFramework(framework, params);
}
@Override
public int initFrameworkEnv(String framework, WXParams params, String cacheDir, boolean pieSupport) {
if (MULTIPROCESS) {
return nativeInitFrameworkEnv(framework, params, cacheDir, pieSupport);
} else {
return nativeInitFramework(framework, params);
}
}
@Override
public int execJS(String instanceId, String namespace, String function, WXJSObject[] args) {
return nativeExecJS(instanceId, namespace, function, args);
}
@Override
public byte[] execJSWithResult(String instanceId, String namespace, String function, WXJSObject[] args) {
return nativeExecJSWithResult(instanceId, namespace, function, args);
}
@Override
public int execJSService(String javascript) {
return nativeExecJSService(javascript);
}
@Override
public void takeHeapSnapshot(String filename) {
nativeTakeHeapSnapshot(filename);
}
@Override
public int createInstanceContext(String instanceId, String name, String function, WXJSObject[] args) {
return nativeCreateInstanceContext(instanceId, name, function, args);
}
@Override
public int destoryInstance(String instanceId, String name, String function, WXJSObject[] args) {
return nativeDestoryInstance(instanceId, name, function, args);
}
@Override
public String execJSOnInstance(String instanceId, String script, int type) {
return nativeExecJSOnInstance(instanceId, script, type);
}
public static final String TAG = "WXBridge";
/**
* JavaScript uses this methods to call Android code
*
* @param instanceId
* @param tasks
* @param callback
*/
public int callNative(String instanceId, byte[] tasks, String callback) {
return callNative(instanceId, (JSONArray) JSON.parseArray(new String(tasks)), callback);
}
@Override
public int callNative(String instanceId, String tasks, String callback) {
try{
return callNative(instanceId, JSONArray.parseArray(tasks), callback);
}catch (Exception e){
WXLogUtils.e(TAG, "callNative throw exception: " + e.getMessage());
return IWXBridge.INSTANCE_RENDERING;
}
}
private int callNative(String instanceId, JSONArray tasks, String callback){
long start = System.currentTimeMillis();
WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
if (instance != null) {
instance.firstScreenCreateInstanceTime(start);
}
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callNative(instanceId, tasks, callback);
} catch (Throwable e) {
WXLogUtils.e(TAG, "callNative throw exception:" + e.getMessage());
}
if (WXEnvironment.isApkDebugable()) {
if (errorCode == IWXBridge.DESTROY_INSTANCE) {
WXLogUtils.w("destroyInstance :" + instanceId + " JSF must stop callNative");
}
}
return errorCode;
}
public void reportJSException(String instanceId, String func, String exception) {
WXBridgeManager.getInstance().reportJSException(instanceId, func, exception);
}
/**
* Bridge module Js Method
* support Sync or Async through setting Annotation as {@link com.taobao.weex.annotation.JSMethod }
*
* @param instanceId Instance ID
* @param module the name of module
* @param method the name of method
* @param arguments the arguments of the method
* @param options option arguments for extending
* @return the result
*/
@Override
public Object callNativeModule(String instanceId, String module, String method, byte[] arguments, byte[] options) {
try{
JSONArray argArray = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(arguments);
JSONObject optionsObj = null;
if (options != null) {
optionsObj = (JSONObject) WXWsonJSONSwitch.parseWsonOrJSON(options);
}
Object object = WXBridgeManager.getInstance().callNativeModule(instanceId, module, method, argArray, optionsObj);
return WXWsonJSONSwitch.toWsonOrJsonWXJSObject(object);
}catch (Exception e){
WXLogUtils.e(TAG, e);
return new WXJSObject(null);
}
}
/**
* Bridge component Js Method
*
* @param instanceId Instance ID
* @param ref the ref of component
* @param method the name of method
* @param arguments the arguments of the method
* @param options option arguments for extending
*/
@Override
public void callNativeComponent(String instanceId, String ref, String method, byte[] arguments, byte[] optionsData) {
try{
JSONArray argArray = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(arguments);
Object options = WXWsonJSONSwitch.parseWsonOrJSON(optionsData);
WXBridgeManager.getInstance().callNativeComponent(instanceId, ref, method, argArray, options);
}catch (Exception e){
WXLogUtils.e(TAG, e);
}
}
public void setTimeoutNative(String callbackId, String time) {
WXBridgeManager.getInstance().setTimeout(callbackId, time);
}
public void setJSFrmVersion(String version) {
if (version != null) {
WXEnvironment.JS_LIB_SDK_VERSION = version;
}
}
@Override
public int callUpdateFinish(String instanceId, byte[] tasks, String callback) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callUpdateFinish(instanceId, callback);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callCreateBody throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callRefreshFinish(String instanceId, byte[] tasks, String callback) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callRefreshFinish(instanceId, callback);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callCreateFinish throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public void reportServerCrash(String instanceId, String crashFile) {
WXLogUtils.e(TAG, "reportServerCrash instanceId:" + instanceId);
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callReportCrashReloadPage(instanceId, crashFile);
// upload crash log
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "reloadPageNative throw exception:" + e.getMessage());
}
}
}
@Override
public int callCreateBody(String instanceId, String componentType, String ref,
HashMap<String, String> styles, HashMap<String, String> attributes, HashSet<String> events,
float[] margins, float[] paddings, float[] borders) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callCreateBody(instanceId, componentType, ref,
styles, attributes, events, margins, paddings, borders);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callCreateBody throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callAddElement(String instanceId, String componentType, String ref, int index, String parentRef,
HashMap<String, String> styles, HashMap<String, String> attributes, HashSet<String> events,
float[] margins, float[] paddings, float[] borders, boolean willLayout) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callAddElement(instanceId, componentType, ref, index, parentRef,
styles, attributes, events, margins, paddings, borders, willLayout);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
e.printStackTrace();
WXLogUtils.e(TAG, "callAddElement throw error:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callRemoveElement(String instanceId, String ref) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callRemoveElement(instanceId, ref);
} catch (Throwable e) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callRemoveElement throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callMoveElement(String instanceId, String ref, String parentref, int index) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callMoveElement(instanceId, ref, parentref, index);
} catch (Throwable e) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callMoveElement throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callAddEvent(String instanceId, String ref, String event) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callAddEvent(instanceId, ref, event);
} catch (Throwable e) {
//catch everything during call native.
// if(WXEnvironment.isApkDebugable()){
WXLogUtils.e(TAG, "callAddEvent throw exception:" + e.getMessage());
// }
}
return errorCode;
}
@Override
public int callRemoveEvent(String instanceId, String ref, String event) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callRemoveEvent(instanceId, ref, event);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callRemoveEvent throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callUpdateStyle(String instanceId, String ref,
HashMap<String, Object> styles,
HashMap<String, String> paddings,
HashMap<String, String> margins,
HashMap<String, String> borders) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callUpdateStyle(instanceId, ref, styles, paddings, margins, borders);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callUpdateStyle throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callUpdateAttrs(String instanceId, String ref, HashMap<String, String> attrs) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callUpdateAttrs(instanceId, ref, attrs);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callUpdateAttr throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callLayout(String instanceId, String ref, int top, int bottom, int left, int right, int height, int width, int index) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callLayout(instanceId, ref, top, bottom, left, right, height, width, index);
} catch (Throwable e) {
//catch everything during call native.
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callLayout throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public int callCreateFinish(String instanceId) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callCreateFinish(instanceId);
} catch (Throwable e) {
WXLogUtils.e(TAG, "callCreateFinish throw exception:" + e.getMessage());
}
return errorCode;
}
@Override
public int callAppendTreeCreateFinish(String instanceId, String ref) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callAppendTreeCreateFinish(instanceId, ref);
} catch (Throwable e) {
WXLogUtils.e(TAG, "callAppendTreeCreateFinish throw exception:" + e.getMessage());
}
return errorCode;
}
@Override
public int callHasTransitionPros(String instanceId, String ref, HashMap<String, String> styles) {
int errorCode = IWXBridge.INSTANCE_RENDERING;
try {
errorCode = WXBridgeManager.getInstance().callHasTransitionPros(instanceId, ref, styles);
} catch (Throwable e) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "callHasTransitionPros throw exception:" + e.getMessage());
}
}
return errorCode;
}
@Override
public ContentBoxMeasurement getMeasurementFunc(String instanceId, long renderObjectPtr) {
ContentBoxMeasurement obj = null;
try {
obj = WXBridgeManager.getInstance().getMeasurementFunc(instanceId, renderObjectPtr);
} catch (Throwable e) {
if (WXEnvironment.isApkDebugable()) {
WXLogUtils.e(TAG, "getMeasurementFunc throw exception:" + e.getMessage());
}
}
return obj;
}
@Override
public void bindMeasurementToRenderObject(long ptr){
nativeBindMeasurementToRenderObject(ptr);
}
@Override
public void setRenderContainerWrapContent(boolean wrap, String instanceId) {
nativeSetRenderContainerWrapContent(wrap, instanceId);
}
@Override
public long[] getFirstScreenRenderTime(String instanceId) {
return nativeGetFirstScreenRenderTime(instanceId);
}
@Override
public long[] getRenderFinishTime(String instanceId) {
return nativeGetRenderFinishTime(instanceId);
}
@Override
public void setDefaultHeightAndWidthIntoRootDom(String instanceId, float defaultWidth, float defaultHeight, boolean isWidthWrapContent, boolean isHeightWrapContent) {
nativeSetDefaultHeightAndWidthIntoRootDom(instanceId, defaultWidth, defaultHeight, isWidthWrapContent, isHeightWrapContent);
}
@Override
public void onInstanceClose(String instanceId) {
nativeOnInstanceClose(instanceId);
}
@Override
public void forceLayout(String instanceId) {
nativeForceLayout(instanceId);
}
@Override
public boolean notifyLayout(String instanceId) {
return nativeNotifyLayout(instanceId);
}
@Override
public void setStyleWidth(String instanceId, String ref, float value) {
nativeSetStyleWidth(instanceId, ref, value);
}
@Override
public void setMargin(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
nativeSetMargin(instanceId, ref, edge.ordinal(), value);
}
@Override
public void setPadding(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
nativeSetPadding(instanceId, ref, edge.ordinal(), value);
}
@Override
public void setPosition(String instanceId, String ref, CSSShorthand.EDGE edge, float value) {
nativeSetPosition(instanceId, ref, edge.ordinal(), value);
}
@Override
public void markDirty(String instanceId, String ref, boolean dirty) {
nativeMarkDirty(instanceId, ref, dirty);
}
@Override
public void setStyleHeight(String instanceId, String ref, float value) {
nativeSetStyleHeight(instanceId, ref, value);
}
@Override
public void registerCoreEnv(String key, String value) {
nativeRegisterCoreEnv(key, value);
}
public void reportNativeInitStatus(String statusCode, String errorMsg) {
if (WXErrorCode.WX_JS_FRAMEWORK_INIT_SINGLE_PROCESS_SUCCESS.getErrorCode().equals(statusCode)
|| WXErrorCode.WX_JS_FRAMEWORK_INIT_FAILED.getErrorCode().equals(statusCode)) {
IWXUserTrackAdapter userTrackAdapter = WXSDKManager.getInstance().getIWXUserTrackAdapter();
if (userTrackAdapter != null) {
Map<String, Serializable> params = new HashMap<>(3);
params.put(IWXUserTrackAdapter.MONITOR_ERROR_CODE, statusCode);
params.put(IWXUserTrackAdapter.MONITOR_ARG, "InitFrameworkNativeError");
params.put(IWXUserTrackAdapter.MONITOR_ERROR_MSG, errorMsg);
Log.e("Dyy", "reportNativeInitStatus is running and errorCode is " + statusCode + " And errorMsg is " + errorMsg);
userTrackAdapter.commit(null, null, IWXUserTrackAdapter.INIT_FRAMEWORK, null, params);
}
return;
}
for (WXErrorCode e : WXErrorCode.values()) {
if (e.getErrorType().equals(WXErrorCode.ErrorType.NATIVE_ERROR)
&& e.getErrorCode().equals(statusCode)) {
WXExceptionUtils.commitCriticalExceptionRT(null, e, "initFramework", errorMsg, null);
break;
}
}
}
}