| /* |
| * 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 org.apache.weex.bridge; |
| |
| import static org.apache.weex.bridge.WXModuleManager.createDomModule; |
| |
| import android.content.Context; |
| import android.net.Uri; |
| import android.os.Build; |
| import android.os.Handler; |
| import android.os.Handler.Callback; |
| import android.os.Looper; |
| import android.os.Message; |
| import android.support.annotation.NonNull; |
| import android.support.annotation.Nullable; |
| import android.support.annotation.RestrictTo; |
| import android.support.annotation.RestrictTo.Scope; |
| import android.support.annotation.UiThread; |
| import android.support.v4.util.ArrayMap; |
| import android.text.TextUtils; |
| import android.util.Log; |
| import android.util.Pair; |
| import com.alibaba.fastjson.JSON; |
| import com.alibaba.fastjson.JSONArray; |
| import com.alibaba.fastjson.JSONObject; |
| import org.apache.weex.Script; |
| import org.apache.weex.WXEnvironment; |
| import org.apache.weex.WXSDKEngine; |
| import org.apache.weex.WXSDKInstance; |
| import org.apache.weex.WXSDKManager; |
| import org.apache.weex.adapter.IWXConfigAdapter; |
| import org.apache.weex.adapter.IWXJSExceptionAdapter; |
| import org.apache.weex.adapter.IWXJsFileLoaderAdapter; |
| import org.apache.weex.adapter.IWXJscProcessManager; |
| import org.apache.weex.adapter.IWXUserTrackAdapter; |
| import org.apache.weex.common.IWXBridge; |
| import org.apache.weex.common.IWXDebugConfig; |
| import org.apache.weex.common.WXConfig; |
| import org.apache.weex.common.WXErrorCode; |
| import org.apache.weex.common.WXException; |
| import org.apache.weex.common.WXJSBridgeMsgType; |
| import org.apache.weex.common.WXJSExceptionInfo; |
| import org.apache.weex.common.WXRefreshData; |
| import org.apache.weex.common.WXRenderStrategy; |
| import org.apache.weex.common.WXRuntimeException; |
| import org.apache.weex.common.WXThread; |
| import org.apache.weex.dom.CSSShorthand; |
| import org.apache.weex.jsEngine.JSEngine; |
| import org.apache.weex.layout.ContentBoxMeasurement; |
| import org.apache.weex.performance.WXInstanceApm; |
| import org.apache.weex.performance.WXStateRecord; |
| import org.apache.weex.ui.WXComponentRegistry; |
| import org.apache.weex.ui.WXRenderManager; |
| import org.apache.weex.ui.action.ActionReloadPage; |
| import org.apache.weex.ui.action.BasicGraphicAction; |
| import org.apache.weex.ui.action.GraphicActionAddChildToRichtext; |
| import org.apache.weex.ui.action.GraphicActionAddElement; |
| import org.apache.weex.ui.action.GraphicActionAddEvent; |
| import org.apache.weex.ui.action.GraphicActionAppendTreeCreateFinish; |
| import org.apache.weex.ui.action.GraphicActionCreateBody; |
| import org.apache.weex.ui.action.GraphicActionCreateFinish; |
| import org.apache.weex.ui.action.GraphicActionLayout; |
| import org.apache.weex.ui.action.GraphicActionMoveElement; |
| import org.apache.weex.ui.action.GraphicActionRefreshFinish; |
| import org.apache.weex.ui.action.GraphicActionRemoveChildFromRichtext; |
| import org.apache.weex.ui.action.GraphicActionRemoveElement; |
| import org.apache.weex.ui.action.GraphicActionRemoveEvent; |
| import org.apache.weex.ui.action.GraphicActionRenderSuccess; |
| import org.apache.weex.ui.action.GraphicActionUpdateAttr; |
| import org.apache.weex.ui.action.GraphicActionUpdateRichtextAttr; |
| import org.apache.weex.ui.action.GraphicActionUpdateRichtextStyle; |
| import org.apache.weex.ui.action.GraphicActionUpdateStyle; |
| import org.apache.weex.ui.action.GraphicPosition; |
| import org.apache.weex.ui.action.GraphicSize; |
| import org.apache.weex.ui.component.WXComponent; |
| import org.apache.weex.ui.module.WXDomModule; |
| import org.apache.weex.utils.WXExceptionUtils; |
| import org.apache.weex.utils.WXFileUtils; |
| import org.apache.weex.utils.WXJsonUtils; |
| import org.apache.weex.utils.WXLogUtils; |
| import org.apache.weex.utils.WXUtils; |
| import org.apache.weex.utils.WXViewUtils; |
| import org.apache.weex.utils.WXWsonJSONSwitch; |
| import org.apache.weex.utils.batch.BactchExecutor; |
| import org.apache.weex.utils.batch.Interceptor; |
| import org.apache.weex.utils.tools.LogDetail; |
| import java.io.BufferedReader; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileReader; |
| import java.io.InputStreamReader; |
| import java.io.Serializable; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Method; |
| import java.text.DateFormat; |
| import java.text.SimpleDateFormat; |
| import java.util.*; |
| import java.util.concurrent.CountDownLatch; |
| import java.util.concurrent.TimeUnit; |
| import java.util.regex.Pattern; |
| |
| /** |
| * Manager class for communication between JavaScript and Android. |
| * <ol> |
| * <li> |
| * Handle Android to JavaScript call, can be one of the following |
| * <ul> |
| * <li>{@link #createInstance(String, String, Map, String)}</li> |
| * <li>{@link #destroyInstance(String)}</li> |
| * <li>{@link #refreshInstance(String, WXRefreshData)}</li> |
| * <li>{@link #registerModules(Map)}</li> |
| * <li>{@link #registerComponents(List)}</li> |
| * <li>{@link #invokeCallJSBatch(Message)}</li> |
| * </ul> |
| * </li> |
| * <li> |
| * Handle JavaScript to Android call |
| * </li> |
| * <li> |
| * Handle next tick of message. |
| * </li> |
| * </ol> |
| */ |
| public class WXBridgeManager implements Callback, BactchExecutor { |
| |
| private static Class clazz_debugProxy = null; |
| public static final String METHOD_CREATE_INSTANCE = "createInstance"; |
| public static final String METHOD_CREATE_PAGE_WITH_CONTENT = "CreatePageWithContent"; |
| public static final String METHOD_UPDATE_COMPONENT_WITH_DATA = "UpdateComponentData"; |
| private static final String METHOD_POST_TASK_TO_MSG_LOOP = "PostTaskToMsgLoop"; |
| private static final String METHOD_JSFM_NOT_INIT_IN_EAGLE_MODE = "JsfmNotInitInEagleMode"; |
| private static final String METHOD_MOVE_RENDER_OBJECT = "RenderPage::MoveRenderObject"; |
| public static final String METHOD_DESTROY_INSTANCE = "destroyInstance"; |
| public static final String METHOD_CALL_JS = "callJS"; |
| public static final String METHOD_SET_TIMEOUT = "setTimeoutCallback"; |
| public static final String METHOD_REGISTER_MODULES = "registerModules"; |
| public static final String METHOD_REGISTER_COMPONENTS = "registerComponents"; |
| public static final String METHOD_FIRE_EVENT = "fireEvent"; |
| public static final String METHD_FIRE_EVENT_SYNC = "fireEventSync"; |
| public static final String METHD_COMPONENT_HOOK_SYNC = "componentHook"; |
| public static final String METHOD_CALLBACK = "callback"; |
| public static final String METHOD_REFRESH_INSTANCE = "refreshInstance"; |
| public static final String METHOD_FIRE_EVENT_ON_DATA_RENDER_NODE = "fireEventOnDataRenderNode"; |
| public static final String METHOD_NOTIFY_TRIM_MEMORY = "notifyTrimMemory"; |
| public static final String METHOD_NOTIFY_SERIALIZE_CODE_CACHE = |
| "notifySerializeCodeCache"; |
| public static final String METHOD_CREATE_INSTANCE_CONTEXT = "createInstanceContext"; |
| |
| public static final String KEY_METHOD = "method"; |
| public static final String KEY_ARGS = "args"; |
| |
| // args |
| public static final String COMPONENT = "component"; |
| public static final String REF = "ref"; |
| public static final String MODULE = "module"; |
| public static final String METHOD = "method"; |
| public static final String KEY_PARAMS = "params"; |
| public static final String ARGS = "args"; |
| public static final String OPTIONS = "options"; |
| public static final String INITLOGFILE = "/jsserver_start.log"; |
| private static final String NON_CALLBACK = "-1"; |
| private static final String UNDEFINED = "undefined"; |
| private static final String BUNDLE_TYPE = "bundleType"; |
| private static final String RENDER_STRATEGY = "renderStrategy"; |
| private static final int INIT_FRAMEWORK_OK = 1; |
| private static final int CRASHREINIT = 50; |
| static volatile WXBridgeManager mBridgeManager; |
| private static long LOW_MEM_VALUE = 120; |
| public volatile static int reInitCount = 1; |
| private volatile static int sInitFrameWorkCount = 0; |
| private static String crashUrl = null; |
| private static long lastCrashTime = 0; |
| |
| private static String mRaxApi = null; |
| // private static String mRaxExtApi = null; |
| |
| // add for clound setting, default value is true |
| // can use it to control weex sandbox |
| // if true will open weex sandbox for multi context |
| private volatile static boolean isSandBoxContext = true; |
| |
| // add for cloud setting, default value is false. |
| // weexcore use single process or not |
| private static boolean isUseSingleProcess = false; |
| // add for cloud setting, default value is false. |
| // jsEngine use multiThread or not |
| private volatile static boolean isJsEngineMultiThreadEnable = false; |
| |
| public enum BundType { |
| Vue, |
| Rax, |
| Others |
| }; |
| |
| private static final boolean BRIDGE_LOG_SWITCH = false; |
| |
| /** |
| * Whether JS Framework(main.js) has been initialized. |
| */ |
| private volatile static boolean mInit = false; |
| |
| private static String globalConfig = "none"; |
| private static String GLOBAL_CONFIG_KEY = "global_switch_config"; |
| |
| private static Map<String, String> mWeexCoreEnvOptions = new HashMap<>(); |
| |
| /** |
| * package |
| **/ |
| Handler mJSHandler; |
| /** |
| * next tick tasks, can set priority |
| */ |
| private WXHashMap<String, ArrayList<WXHashMap<String, Object>>> mNextTickTasks = new WXHashMap<>(); |
| /** |
| * JSThread |
| */ |
| private WXThread mJSThread; |
| private IWXBridge mWXBridge; |
| private Object mWxDebugProxy; |
| |
| private boolean mMock = false; |
| |
| private List<Map<String, Object>> mRegisterComponentFailList = new ArrayList<>(8); |
| private List<Map<String, Object>> mRegisterModuleFailList = new ArrayList<>(8); |
| private List<String> mRegisterServiceFailList = new ArrayList<>(8); |
| private HashSet<String> mDestroyedInstanceId = new HashSet<>(); |
| private StringBuilder mLodBuilder = new StringBuilder(50); |
| private Interceptor mInterceptor; |
| private WXParams mInitParams; |
| |
| private WXBridgeManager() { |
| initWXBridge(WXEnvironment.sRemoteDebugMode); |
| mJSThread = new WXThread("WeexJSBridgeThread", this); |
| mJSHandler = mJSThread.getHandler(); |
| } |
| |
| public static WXBridgeManager getInstance() { |
| if (mBridgeManager == null) { |
| synchronized (WXBridgeManager.class) { |
| if (mBridgeManager == null) { |
| mBridgeManager = new WXBridgeManager(); |
| } |
| } |
| } |
| return mBridgeManager; |
| } |
| |
| public void setUseSingleProcess(final boolean flag) { |
| if (flag != isUseSingleProcess) { |
| isUseSingleProcess = flag; |
| // //we should reinit framework if js framework has been initialized |
| // if (isJSFrameworkInit()) { |
| // if (isJSThread()) { |
| // WXSDKEngine.reload(); |
| // } else { |
| // post(new Runnable() { |
| // @Override |
| // public void run() { |
| // WXSDKEngine.reload(); |
| // } |
| // }); |
| // } |
| // } |
| } |
| } |
| |
| public void onInteractionTimeUpdate(final String instanceId){ |
| post(new Runnable() { |
| @Override |
| public void run() { |
| if (mWXBridge instanceof WXBridge ){ |
| ((WXBridge)mWXBridge).nativeOnInteractionTimeUpdate(instanceId); |
| } |
| } |
| }); |
| } |
| |
| public boolean jsEngineMultiThreadEnable() { |
| return isJsEngineMultiThreadEnable; |
| } |
| |
| public void checkJsEngineMultiThread() { |
| boolean flag = false; |
| IWXJscProcessManager wxJscProcessManager = WXSDKManager.getInstance().getWXJscProcessManager(); |
| if(wxJscProcessManager!=null) { |
| flag = wxJscProcessManager.enableBackupThread(); |
| } |
| |
| if(flag == WXBridgeManager.isJsEngineMultiThreadEnable) { |
| return; |
| } |
| |
| WXBridgeManager.isJsEngineMultiThreadEnable = flag; |
| //we should reinit framework if js framework has been initialized |
| if (isJSFrameworkInit()) { |
| if (isJSThread()) { |
| WXSDKEngine.reload(); |
| } else { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| WXSDKEngine.reload(); |
| } |
| }); |
| } |
| } |
| } |
| public void setSandBoxContext(final boolean flag) { |
| if (flag != isSandBoxContext) { |
| isSandBoxContext = flag; |
| // use diff context reinit jsf |
| if (isJSThread()) { |
| |
| setJSFrameworkInit(false); |
| WXModuleManager.resetAllModuleState(); |
| String jsf = ""; |
| if (!isSandBoxContext) { |
| jsf = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication()); |
| } else { |
| jsf = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication()); |
| } |
| initFramework(jsf); |
| WXServiceManager.reload(); |
| WXModuleManager.reload(); |
| WXComponentRegistry.reload(); |
| } else { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| setJSFrameworkInit(false); |
| WXModuleManager.resetAllModuleState(); |
| String jsf = ""; |
| if (!isSandBoxContext) { |
| jsf = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication()); |
| } else { |
| jsf = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication()); |
| } |
| initFramework(jsf); |
| WXServiceManager.reload(); |
| WXModuleManager.reload(); |
| WXComponentRegistry.reload(); |
| } |
| }); |
| } |
| } |
| } |
| |
| // setJSFrameworkInit and isJSFrameworkInit may use on diff thread |
| // use volatile |
| @RestrictTo(Scope.LIBRARY) |
| boolean isJSFrameworkInit() { |
| return mInit; |
| } |
| |
| private void setJSFrameworkInit(boolean init) { |
| mInit = init; |
| WXStateRecord.getInstance().recoreJsfmInitHistory("setJsfmInitFlag:"+init); |
| if (init == true) { |
| onJsFrameWorkInitSuccees(); |
| JSEngine.getInstance().engineInitFinished(); |
| } |
| } |
| |
| private void initWXBridge(boolean remoteDebug) { |
| if (remoteDebug && WXEnvironment.isApkDebugable()) { |
| WXEnvironment.sDebugServerConnectable = true; |
| } |
| |
| if (WXEnvironment.sDebugServerConnectable && (WXEnvironment.isApkDebugable() || WXEnvironment.sForceEnableDevTool)) { |
| if (WXEnvironment.getApplication() != null) { |
| try { |
| if (clazz_debugProxy == null) { |
| clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy"); |
| } |
| if (clazz_debugProxy != null) { |
| Constructor constructor = clazz_debugProxy.getConstructor(Context.class, IWXDebugConfig.class); |
| if (constructor != null) { |
| mWxDebugProxy = constructor.newInstance(WXEnvironment.getApplication(), |
| new IWXDebugConfig() { |
| @Override |
| public WXBridgeManager getWXJSManager() { |
| return WXBridgeManager.this; |
| } |
| |
| @Override |
| public WXDebugJsBridge getWXDebugJsBridge() { |
| return new WXDebugJsBridge(); |
| } |
| }); |
| if (mWxDebugProxy != null) { |
| Method method_start = clazz_debugProxy.getMethod("start"); |
| if (method_start != null) { |
| method_start.invoke(mWxDebugProxy); |
| } |
| } |
| } |
| } |
| } catch (Throwable e) { |
| //Ignore, It will throw Exception on Release environment |
| } |
| WXServiceManager.execAllCacheJsService(); |
| } else { |
| WXLogUtils.e("WXBridgeManager", "WXEnvironment.sApplication is null, skip init Inspector"); |
| } |
| } |
| if (remoteDebug && mWxDebugProxy != null) { |
| try { |
| if (clazz_debugProxy == null ) { |
| clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy"); |
| } |
| if (clazz_debugProxy != null) { |
| Method method_getWXBridge = clazz_debugProxy.getMethod("getWXBridge"); |
| if (method_getWXBridge != null) { |
| mWXBridge = (IWXBridge) method_getWXBridge.invoke(mWxDebugProxy); |
| } |
| } |
| } catch (Throwable e) { |
| //Ignore, It will throw Exception on Release environment |
| } |
| } else { |
| mWXBridge = new WXBridge(); |
| } |
| } |
| |
| public String dumpIpcPageInfo(){ |
| if (mWXBridge instanceof WXBridge){ |
| return ((WXBridge)mWXBridge).nativeDumpIpcPageQueueInfo(); |
| } |
| return ""; |
| } |
| |
| public boolean isRebootExceedLimit(){ |
| return reInitCount > CRASHREINIT; |
| } |
| |
| public void stopRemoteDebug() { |
| if (mWxDebugProxy != null) { |
| try { |
| if (clazz_debugProxy == null) { |
| clazz_debugProxy = Class.forName("com.taobao.weex.devtools.debug.DebugServerProxy"); |
| } |
| if (clazz_debugProxy != null) { |
| Method method_stop = clazz_debugProxy.getMethod("stop", boolean.class); |
| if (method_stop != null) { |
| method_stop.invoke(mWxDebugProxy, true); |
| } |
| } |
| } catch (Throwable e) { |
| //Ignore, It will throw Exception on Release environment |
| } |
| } |
| } |
| |
| public Object callModuleMethod(String instanceId, String moduleStr, String methodStr, JSONArray args) { |
| return callModuleMethod(instanceId, moduleStr, methodStr, args, null); |
| } |
| |
| public Object callModuleMethod(String instanceId, String moduleStr, String methodStr, JSONArray args, JSONObject options) { |
| WXSDKInstance wxsdkInstance = WXSDKManager.getInstance() |
| .getSDKInstance(instanceId); |
| if (wxsdkInstance == null) { |
| return null; |
| } |
| if (wxsdkInstance.isNeedValidate() |
| && WXSDKManager.getInstance().getValidateProcessor() != null) { |
| WXValidateProcessor.WXModuleValidateResult validateResult = WXSDKManager |
| .getInstance().getValidateProcessor() |
| .onModuleValidate(wxsdkInstance, moduleStr, methodStr, args, options); |
| if (validateResult == null) { |
| return null; |
| } |
| if (validateResult.isSuccess) { |
| return WXModuleManager.callModuleMethod(instanceId, moduleStr, methodStr, |
| args); |
| } else { |
| JSONObject validateInfo = validateResult.validateInfo; |
| if (validateInfo != null) { |
| WXLogUtils.e("[WXBridgeManager] module validate fail. >>> " + validateInfo.toJSONString()); |
| } |
| return validateInfo; |
| } |
| } |
| try { |
| return WXModuleManager.callModuleMethod(instanceId, moduleStr, methodStr, args); |
| }catch(NumberFormatException e){ |
| ArrayMap<String, String> ext = new ArrayMap<>(); |
| ext.put("moduleName", moduleStr); |
| ext.put("methodName", methodStr); |
| ext.put("args", args.toJSONString()); |
| WXLogUtils.e("[WXBridgeManager] callNative : numberFormatException when parsing string to numbers in args", ext.toString()); |
| return null; |
| } |
| } |
| |
| /** |
| * Model switch. For now, debug model and release model are supported |
| */ |
| public void restart() { |
| setJSFrameworkInit(false); |
| WXModuleManager.resetAllModuleState(); |
| initWXBridge(WXEnvironment.sRemoteDebugMode); |
| mWXBridge.resetWXBridge(WXEnvironment.sRemoteDebugMode); |
| } |
| |
| /** |
| * Set current Instance |
| * |
| * @param instanceId {@link WXSDKInstance#getInstanceId()} |
| */ |
| public synchronized void setStackTopInstance(final String instanceId) { |
| post(new Runnable() { |
| |
| @Override |
| public void run() { |
| mNextTickTasks.setStackTopInstance(instanceId); |
| } |
| },instanceId, null, null); |
| } |
| |
| @Override |
| public void post(Runnable r) { |
| postWithName(r,null,null); |
| } |
| |
| public void postWithName(Runnable r, WXSDKInstance instance, String runnableName) { |
| Runnable secure = WXThread.secure(r,instance, runnableName); |
| if (mInterceptor != null && mInterceptor.take(secure)) { |
| //task is token by the interceptor |
| return; |
| } |
| if (mJSHandler == null) { |
| return; |
| } |
| |
| mJSHandler.post(secure); |
| } |
| |
| @Override |
| public void setInterceptor(Interceptor interceptor) { |
| mInterceptor = interceptor; |
| } |
| |
| public void post(Runnable r, Object token, WXSDKInstance instance, String runnableName) { |
| if (mJSHandler == null) { |
| return; |
| } |
| |
| Message m = Message.obtain(mJSHandler, WXThread.secure(r, instance, runnableName)); |
| m.obj = token; |
| m.sendToTarget(); |
| } |
| |
| public void post(Runnable r, Object token) { |
| post(r, token, null, null); |
| } |
| |
| public void postDelay(Runnable r,long delayMillis){ |
| if (mJSHandler == null) { |
| return; |
| } |
| mJSHandler.postDelayed(WXThread.secure(r),delayMillis); |
| } |
| |
| void setTimeout(String callbackId, String time) { |
| Message message = Message.obtain(); |
| message.what = WXJSBridgeMsgType.SET_TIMEOUT; |
| TimerInfo timerInfo = new TimerInfo(); |
| timerInfo.callbackId = callbackId; |
| timerInfo.time = (long) Float.parseFloat(time); |
| message.obj = timerInfo; |
| |
| mJSHandler.sendMessageDelayed(message, timerInfo.time); |
| } |
| |
| public void sendMessageDelayed(Message message, long delayMillis) { |
| if (message == null || mJSHandler == null || mJSThread == null |
| || !mJSThread.isWXThreadAlive() || mJSThread.getLooper() == null) { |
| return; |
| } |
| mJSHandler.sendMessageDelayed(message, delayMillis); |
| } |
| |
| public void removeMessage(int what, Object obj) { |
| if (mJSHandler == null || mJSThread == null |
| || !mJSThread.isWXThreadAlive() || mJSThread.getLooper() == null) { |
| return; |
| } |
| mJSHandler.removeMessages(what, obj); |
| } |
| |
| public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, Object options) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(module) || TextUtils.isEmpty(method)) { |
| WXLogUtils.d("[WXBridgeManager] call callNativeModule arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeModule", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId) |
| .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| try { |
| if (WXDomModule.WXDOM.equals(module)) { |
| WXDomModule dom = WXModuleManager.getDomModule(instanceId); |
| return dom.callDomMethod(method, arguments); |
| } else { |
| return callModuleMethod(instanceId, module, |
| method, arguments); |
| } |
| } catch (Exception e) { |
| String err = "[WXBridgeManager] callNative exception: " + WXLogUtils.getStackTrace(e); |
| WXLogUtils.e(err); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNativeModule", |
| err, null); |
| } |
| |
| return null; |
| } |
| |
| public Object callNativeModule(String instanceId, String module, String method, JSONArray arguments, JSONObject options) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(module) || TextUtils.isEmpty(method)) { |
| WXLogUtils.d("[WXBridgeManager] call callNativeModule arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeModule", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callNativeModule >>>> instanceId:").append(instanceId) |
| .append(", module:").append(module).append(", method:").append(method).append(", arguments:").append(arguments); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| try { |
| if (WXDomModule.WXDOM.equals(module)) { |
| WXDomModule dom = WXModuleManager.getDomModule(instanceId); |
| if(dom != null){ |
| return dom.callDomMethod(method, arguments); |
| } else { |
| createDomModule(WXSDKManager.getInstance().getSDKInstance(instanceId)); |
| } |
| } else { |
| return callModuleMethod(instanceId, module, |
| method, arguments, options); |
| } |
| } catch (Exception e) { |
| String err = "[WXBridgeManager] callNativeModule exception: " + WXLogUtils.getStackTrace(e); |
| WXLogUtils.e(err); |
| } |
| |
| return null; |
| } |
| |
| public Object callNativeComponent(String instanceId, String componentRef, String method, JSONArray arguments, Object options) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(componentRef) || TextUtils.isEmpty(method)) { |
| WXLogUtils.d("[WXBridgeManager] call callNativeComponent arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNativeComponent", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callNativeComponent >>>> instanceId:").append(instanceId) |
| .append(", componentRef:").append(componentRef).append(", method:").append(method).append(", arguments:").append(arguments); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| try { |
| WXDomModule dom = WXModuleManager.getDomModule(instanceId); |
| if (null != dom){ |
| dom.invokeMethod(componentRef, method, arguments); |
| }else { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if(null == instance || !instance.isDestroy()){ |
| WXLogUtils.e("WXBridgeManager","callNativeComponent exception :null == dom ,method:"+method); |
| } |
| } |
| |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callNativeComponent exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNativeComponent", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| return null; |
| } |
| |
| /** |
| * Dispatch the native task to be executed. |
| * |
| * @param instanceId {@link WXSDKInstance#getInstanceId()} |
| * @param tasks tasks to be executed |
| * @param callback next tick id |
| */ |
| public int callNative(String instanceId, JSONArray tasks, String callback) { |
| |
| if (TextUtils.isEmpty(instanceId) || tasks == null) { |
| WXLogUtils.d("[WXBridgeManager] call callNative arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callNative", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callNative >>>> instanceId:").append(instanceId) |
| .append(", tasks:").append(tasks).append(", callback:").append(callback); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| |
| long parseNanos = System.nanoTime(); |
| JSONArray array = tasks; |
| parseNanos = System.nanoTime() - parseNanos; |
| |
| if (null != array && array.size() > 0) { |
| int size = array.size(); |
| try { |
| JSONObject task; |
| for (int i = 0; i < size; ++i) { |
| task = (JSONObject) array.get(i); |
| if (task != null && WXSDKManager.getInstance().getSDKInstance(instanceId) != null) { |
| Object module = task.get(MODULE); |
| if (module != null) { |
| if (WXDomModule.WXDOM.equals(module)) { |
| WXDomModule dom = WXModuleManager.getDomModule(instanceId); |
| dom.callDomMethod(task, parseNanos); |
| } else { |
| JSONObject optionObj = task.getJSONObject(OPTIONS); |
| WXStateRecord.getInstance().recordAction(instanceId,"callModuleMethod:"+instanceId+","+module+","+task.get(METHOD)); |
| callModuleMethod(instanceId, (String) module, |
| (String) task.get(METHOD), (JSONArray) task.get(ARGS), optionObj); |
| } |
| } else if (task.get(COMPONENT) != null) { |
| WXDomModule dom = WXModuleManager.getDomModule(instanceId); |
| WXStateRecord.getInstance().recordAction(instanceId,"callDomMethod:"+instanceId+","+task.get(METHOD)); |
| dom.invokeMethod((String) task.get(REF), (String) task.get(METHOD), (JSONArray) task.get(ARGS)); |
| } else { |
| throw new IllegalArgumentException("unknown callNative"); |
| } |
| } |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callNative exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callNative", |
| WXLogUtils.getStackTrace(e) , null); |
| } |
| } |
| |
| if (UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) { |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| // get next tick |
| getNextTick(instanceId, callback); |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| // callUpdateFinish |
| public int callUpdateFinish(String instanceId, String callback) { |
| |
| if (TextUtils.isEmpty(instanceId)) { |
| WXLogUtils.d("[WXBridgeManager] call callUpdateFinish arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateFinish", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callUpdateFinish >>>> instanceId:").append(instanceId) |
| .append(", callback:").append(callback); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| if (WXSDKManager.getInstance().getSDKInstance(instanceId) != null) { |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callUpdateFinish exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateFinish", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| if (callback == null || callback.isEmpty() || UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) { |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| // get next tick |
| getNextTick(instanceId, callback); |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| // callRefreshFinish |
| public int callRefreshFinish(String instanceId, String callback) { |
| |
| if (TextUtils.isEmpty(instanceId)) { |
| WXLogUtils.d("[WXBridgeManager] call callRefreshFinish arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRefreshFinish", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callRefreshFinish >>>> instanceId:").append(instanceId) |
| .append(", callback:").append(callback); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| GraphicActionRefreshFinish action = new GraphicActionRefreshFinish(instance); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callRefreshFinish exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRefreshFinish", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| if (UNDEFINED.equals(callback) || NON_CALLBACK.equals(callback)) { |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| // get next tick |
| getNextTick(instanceId, callback); |
| return IWXBridge.INSTANCE_RENDERING; |
| |
| } |
| |
| public int callReportCrashReloadPage(String instanceId, String crashFile) { |
| boolean isCrashFileEmpty = TextUtils.isEmpty(crashFile); |
| try { |
| String url = null; |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| url = instance.getBundleUrl(); |
| instance.setHasException(true); |
| } |
| Map<String,String> extInfo = new HashMap<>(2); |
| extInfo.put("weexCoreThreadStackTrace:",WXBridgeManager.getInstance().getWeexCoreThreadStackTrace()); |
| extInfo.put("wxStateInfo",WXStateRecord.getInstance().getStateInfo().toString()); |
| |
| if(!isCrashFileEmpty) { |
| try { |
| if (WXEnvironment.getApplication() != null) { |
| crashFile = mInitParams.getCrashFilePath() + crashFile; |
| Log.d("jsengine", "callReportCrashReloadPage crashFile:" + crashFile); |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| WXStateRecord.getInstance().onJSCCrash(TextUtils.isEmpty(instanceId)?"null":instanceId); |
| callReportCrash(crashFile, instanceId, url,extInfo); |
| } else { |
| WXStateRecord.getInstance().onJSEngineReload(TextUtils.isEmpty(instanceId)?"null":instanceId); |
| commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_RELOAD_PAGE, "reboot jsc Engine", instanceId, url,extInfo); |
| } |
| JSEngine.getInstance().engineCrashed(); |
| WXLogUtils.e("reInitCount:"+reInitCount); |
| |
| if (reInitCount > CRASHREINIT) { |
| WXExceptionUtils.commitCriticalExceptionRT("jsEngine", WXErrorCode.WX_ERR_RELOAD_PAGE_EXCEED_LIMIT, |
| "callReportCrashReloadPage","reInitCount:"+reInitCount,extInfo); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| reInitCount++; |
| // reinit frame work |
| setJSFrameworkInit(false); |
| WXModuleManager.resetAllModuleState(); |
| initScriptsFramework(""); |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callReportCrashReloadPage exception: ", e); |
| } |
| try { |
| |
| if (WXSDKManager.getInstance().getSDKInstance(instanceId) != null) { |
| boolean reloadThisInstance = shouldReloadCurrentInstance( |
| WXSDKManager.getInstance().getSDKInstance(instanceId).getBundleUrl()); |
| new ActionReloadPage(instanceId, reloadThisInstance).executeAction(); |
| } |
| |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callReloadPage exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callReportCrashReloadPage", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| public boolean shouldReloadCurrentInstance(String aUrl) { |
| long time = System.currentTimeMillis(); |
| String bizUrl = aUrl; |
| IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter(); |
| if (adapter != null) { |
| boolean check_biz_url = Boolean.parseBoolean(adapter |
| .getConfig("android_weex_ext_config", |
| "check_biz_url", |
| "true")); |
| WXLogUtils.e("check_biz_url : " + check_biz_url); |
| if(check_biz_url && !TextUtils.isEmpty(aUrl)) { |
| Uri uri = Uri.parse(aUrl); |
| if(uri != null) { |
| bizUrl = uri.buildUpon().clearQuery().build().toString(); |
| } |
| } |
| } |
| |
| if (crashUrl == null || |
| (crashUrl != null && !crashUrl.equals(bizUrl)) || |
| ((time - lastCrashTime) > 15000)) { |
| crashUrl = bizUrl; |
| lastCrashTime = time; |
| return true; |
| } |
| lastCrashTime = time; |
| return false; |
| } |
| |
| public void callReportCrash(String crashFile, final String instanceId, final String url,final Map<String,String> extInfo) { |
| // statistic weex core process crash |
| Date date = new Date(); |
| DateFormat format = new SimpleDateFormat("yyyyMMddHHmmss", Locale.US); |
| String time = format.format(date); |
| final String origin_filename = crashFile + "." + time; |
| File oldfile = new File(crashFile); |
| File newfile = new File(origin_filename); |
| if (oldfile.exists()) { |
| oldfile.renameTo(newfile); |
| } |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| File file = new File(origin_filename); |
| if (file.exists()) { |
| if (file.length() > 0) { |
| StringBuilder result = new StringBuilder(); |
| try { |
| BufferedReader br = new BufferedReader(new FileReader(origin_filename)); |
| String s = null; |
| // boolean foundStart = false; |
| while ((s = br.readLine()) != null) { |
| if ("".equals(s)) { |
| continue; |
| } |
| // if (("r0:").equals(s)) { |
| // break; |
| // } |
| result.append(s + "\n"); |
| } |
| commitJscCrashAlarmMonitor(IWXUserTrackAdapter.JS_BRIDGE, WXErrorCode.WX_ERR_JSC_CRASH, result.toString(), instanceId, url,extInfo); |
| br.close(); |
| } catch (Exception e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| } else { |
| WXLogUtils.e("[WXBridgeManager] callReportCrash crash file is empty"); |
| } |
| if(!WXEnvironment.isApkDebugable()) |
| file.delete(); |
| } |
| } catch (Throwable throwable) { |
| WXLogUtils.e("[WXBridgeManager] callReportCrash exception: ", throwable); |
| } |
| } |
| }); |
| t.start(); |
| } |
| |
| private void getNextTick(final String instanceId, final String callback) { |
| addJSTask(METHOD_CALLBACK, instanceId, callback, "{}"); |
| sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH); |
| } |
| |
| private void getNextTick(final String instanceId) { |
| addJSTask(METHOD_CALLBACK, instanceId, "", "{}"); |
| sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH); |
| } |
| |
| public String syncExecJsOnInstanceWithResult(final String instanceId, final String js, final int type) { |
| final CountDownLatch waitLatch = new CountDownLatch(1); |
| EventResult callback = new EventResult(){ |
| @Override |
| public void onCallback(Object result) { |
| super.onCallback(result); |
| waitLatch.countDown(); |
| } |
| }; |
| try{ |
| execJSOnInstance(callback, instanceId, js, type); |
| waitLatch.await(100, TimeUnit.MILLISECONDS); |
| if (callback != null && callback.getResult() != null) { |
| return callback.getResult().toString(); |
| } |
| return ""; |
| }catch (Throwable e){ |
| WXLogUtils.e("syncCallExecJsOnInstance", e); |
| return ""; |
| } |
| } |
| |
| public void loadJsBundleInPreInitMode(final String instanceId, final String js){ |
| post(new Runnable() { |
| @Override |
| public void run() { |
| invokeExecJSOnInstance(instanceId, js, -1); |
| WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId); |
| if (null != instance && instance.isPreInitMode()){ |
| instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END); |
| instance.getApmForInstance().onStageWithTime(WXInstanceApm.KEY_PAGE_STAGES_END_EXCUTE_BUNDLE,WXUtils.getFixUnixTime()+600); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * ref, type, data, domChanges |
| * */ |
| public EventResult syncCallJSEventWithResult(final String method, final String instanceId, final List<Object> params, final Object... args) { |
| final CountDownLatch waitLatch = new CountDownLatch(1); |
| EventResult callback = new EventResult(){ |
| @Override |
| public void onCallback(Object result) { |
| super.onCallback(result); |
| waitLatch.countDown(); |
| } |
| }; |
| try{ |
| asyncCallJSEventWithResult(callback, method, instanceId, params, args); |
| waitLatch.await(100, TimeUnit.MILLISECONDS); |
| return callback; |
| }catch (Exception e){ |
| WXLogUtils.e("syncCallJSEventWithResult", e); |
| return callback; |
| } |
| } |
| |
| public void asyncCallJSEventVoidResult(final String method, final String instanceId, final List<Object> params, final Object... args) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| try{ |
| if (args == null || args.length == 0) { |
| return; |
| } |
| |
| ArrayList<Object> argsList = new ArrayList<>(); |
| for (Object arg : args) { |
| argsList.add(arg); |
| } |
| if (params != null) { |
| ArrayMap map = new ArrayMap(4); |
| map.put(KEY_PARAMS, params); |
| argsList.add(map); |
| } |
| |
| WXHashMap<String, Object> task = new WXHashMap<>(); |
| task.put(KEY_METHOD, method); |
| task.put(KEY_ARGS, argsList); |
| Object[] tasks = {task}; |
| WXJSObject[] jsArgs = { |
| new WXJSObject(WXJSObject.String, instanceId), |
| WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)}; |
| invokeExecJS(String.valueOf(instanceId), null, METHOD_CALL_JS, jsArgs, true); |
| jsArgs[0] = null; |
| jsArgs = null; |
| }catch (Exception e){ |
| WXLogUtils.e("asyncCallJSEventVoidResult" , e); |
| } |
| } |
| }); |
| } |
| |
| /** |
| * aync call js event and return result in eventResult callback |
| * */ |
| private void asyncCallJSEventWithResult(final EventResult eventCallback, final String method, final String instanceId, final List<Object> params, final Object... args) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| Object result = null; |
| try{ |
| if (args == null || args.length == 0) { |
| return; |
| } |
| |
| ArrayList<Object> argsList = new ArrayList<>(); |
| for (Object arg : args) { |
| argsList.add(arg); |
| } |
| if (params != null) { |
| ArrayMap map = new ArrayMap(4); |
| map.put(KEY_PARAMS, params); |
| argsList.add(map); |
| } |
| |
| WXHashMap<String, Object> task = new WXHashMap<>(); |
| task.put(KEY_METHOD, method); |
| task.put(KEY_ARGS, argsList); |
| Object[] tasks = {task}; |
| WXJSObject[] jsArgs = { |
| new WXJSObject(WXJSObject.String, instanceId), |
| WXWsonJSONSwitch.toWsonOrJsonWXJSObject(tasks)}; |
| ResultCallback<byte[]> resultCallback = null; |
| if (eventCallback != null) { |
| resultCallback = new ResultCallback<byte[]>() { |
| @Override |
| public void onReceiveResult(byte[] result) { |
| JSONArray arrayResult = (JSONArray) WXWsonJSONSwitch.parseWsonOrJSON(result); |
| if(arrayResult != null && arrayResult.size() > 0){ |
| eventCallback.onCallback(arrayResult.get(0)); |
| } |
| } |
| }; |
| } |
| invokeExecJSWithCallback(String.valueOf(instanceId), null, METHOD_CALL_JS, |
| jsArgs, resultCallback, true); |
| jsArgs[0] = null; |
| }catch (Exception e){ |
| WXLogUtils.e("asyncCallJSEventWithResult" , e); |
| } |
| } |
| }); |
| } |
| |
| private void addJSEventTask(final String method, final String instanceId, final List<Object> params, final Object... args) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| if (args == null || args.length == 0) { |
| return; |
| } |
| |
| ArrayList<Object> argsList = new ArrayList<>(); |
| for (Object arg : args) { |
| argsList.add(arg); |
| } |
| if (params != null) { |
| ArrayMap map = new ArrayMap(4); |
| map.put(KEY_PARAMS, params); |
| argsList.add(map); |
| } |
| |
| WXHashMap<String, Object> task = new WXHashMap<>(); |
| task.put(KEY_METHOD, method); |
| task.put(KEY_ARGS, argsList); |
| |
| |
| if (mNextTickTasks.get(instanceId) == null) { |
| ArrayList<WXHashMap<String, Object>> list = new ArrayList<>(); |
| list.add(task); |
| mNextTickTasks.put(instanceId, list); |
| } else { |
| mNextTickTasks.get(instanceId).add(task); |
| } |
| } |
| }); |
| } |
| |
| private void addJSTask(final String method, final String instanceId, final Object... args) { |
| addJSEventTask(method, instanceId, null, args); |
| } |
| |
| private void sendMessage(String instanceId, int what) { |
| Message msg = Message.obtain(mJSHandler); |
| msg.obj = instanceId; |
| msg.what = what; |
| msg.sendToTarget(); |
| } |
| |
| /** |
| * Initialize JavaScript framework |
| * |
| * @param framework String representation of the framework to be init. |
| */ |
| public synchronized void initScriptsFramework(String framework) { |
| Message msg = mJSHandler.obtainMessage(); |
| msg.obj = framework; |
| msg.what = WXJSBridgeMsgType.INIT_FRAMEWORK; |
| msg.setTarget(mJSHandler); |
| msg.sendToTarget(); |
| } |
| |
| @Deprecated |
| public void fireEvent(final String instanceId, final String ref, |
| final String type, final Map<String, Object> data) { |
| this.fireEvent(instanceId, ref, type, data, null); |
| } |
| |
| /** |
| * Do not direct invoke this method in Components, use {@link WXSDKInstance#fireEvent(String, String, Map, Map)} instead. |
| * |
| * @param instanceId |
| * @param ref |
| * @param type |
| * @param data |
| * @param domChanges |
| */ |
| @Deprecated |
| public void fireEvent(final String instanceId, final String ref, |
| final String type, final Map<String, Object> data, final Map<String, Object> domChanges) { |
| fireEventOnNode(instanceId, ref, type, data, domChanges); |
| } |
| |
| /** |
| * Notify the JavaScript about the event happened on Android |
| */ |
| public void fireEventOnNode(final String instanceId, final String ref, |
| final String type, final Map<String, Object> data, final Map<String, Object> domChanges) { |
| fireEventOnNode(instanceId, ref, type, data, domChanges, null, null); |
| } |
| |
| /** |
| * Notify the JavaScript about the event happened on Android |
| */ |
| public void fireEventOnNode(final String instanceId, final String ref, |
| final String type, final Map<String, Object> data, |
| final Map<String, Object> domChanges, List<Object> params){ |
| fireEventOnNode(instanceId, ref, type, data, domChanges, params, null); |
| } |
| |
| public void fireEventOnNode(final String instanceId, final String ref, |
| final String type, final Map<String, Object> data, |
| final Map<String, Object> domChanges, List<Object> params, EventResult callback) { |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) |
| || TextUtils.isEmpty(type) || mJSHandler == null) { |
| return; |
| } |
| if (!checkMainThread()) { |
| throw new WXRuntimeException( |
| "fireEvent must be called by main thread"); |
| } |
| WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId); |
| if (instance != null && instance.isUsingEaglePlugin()) { |
| int mode = instance.getEaglePlugin().isSupportFireEvent(instanceId); |
| if (mode == WXEaglePlugin.NOT_SUPPORT){ |
| return; |
| } |
| fireEventOnDataRenderNode(instance.getEaglePlugin(), instanceId, ref, type, data, domChanges); |
| if (mode == WXEaglePlugin.EAGLE_ONLY){ |
| return; |
| } |
| //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT |
| } |
| |
| if (callback == null) { |
| addJSEventTask(METHOD_FIRE_EVENT, instanceId, params, ref, type, data, domChanges); |
| sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH); |
| } else { |
| asyncCallJSEventWithResult(callback, METHD_FIRE_EVENT_SYNC, instanceId, params, ref, type, data, domChanges); |
| } |
| } |
| |
| private void fireEventOnDataRenderNode(final WXEaglePlugin eaglePlugin, final String instanceId, final String ref, |
| final String type, final Map<String, Object> data, final Map<String, Object> domChanges) { |
| mJSHandler.postDelayed(WXThread.secure(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| long start = System.currentTimeMillis(); |
| if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("fireEventOnDataRenderNode >>>> instanceId:" + instanceId |
| + ", data:" + data); |
| } |
| eaglePlugin.fireEvent(instanceId, ref, type, |
| (data == null || data.isEmpty()) ? "{}" : JSON.toJSONString(data), |
| (domChanges == null || domChanges.isEmpty()) ? "{}" : JSON.toJSONString(domChanges)); |
| WXLogUtils.renderPerformanceLog("fireEventOnDataRenderNode", System.currentTimeMillis() - start); |
| } catch (Throwable e) { |
| String err = "[WXBridgeManager] fireEventOnDataRenderNode " + WXLogUtils.getStackTrace(e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "fireEventOnDataRenderNode", |
| err, null); |
| WXLogUtils.e(err); |
| } |
| } |
| }), 0); |
| } |
| |
| private boolean checkMainThread() { |
| return Looper.myLooper() == Looper.getMainLooper(); |
| } |
| |
| |
| /** |
| * Invoke JavaScript callback. Use {@link JSCallback} instead. |
| * |
| * @see #callback(String, String, String) |
| */ |
| @Deprecated |
| public void callback(String instanceId, String callback, String data) { |
| callback(instanceId, callback, data, false); |
| } |
| |
| /** |
| * Invoke JavaScript callback. Use {@link JSCallback} instead. |
| */ |
| @Deprecated |
| public void callback(final String instanceId, final String callback, |
| final Map<String, Object> data) { |
| callback(instanceId, callback, data, false); |
| } |
| |
| /** |
| * Use {@link JSCallback} instead. |
| * |
| * @param instanceId Weex Instance Id |
| * @param callback callback referenece handle |
| * @param data callback data |
| * @param keepAlive if keep callback instance alive for later use |
| */ |
| @Deprecated |
| public void callback(final String instanceId, final String callback, |
| final Object data, boolean keepAlive) { |
| callbackJavascript(instanceId, callback, data, keepAlive); |
| } |
| |
| /** |
| * Callback to Javascript function. |
| * |
| * @param instanceId Weex Instance Id |
| * @param callback callback referenece handle |
| * @param data callback data |
| * @param keepAlive if keep callback instance alive for later use |
| */ |
| void callbackJavascript(final String instanceId, final String callback, |
| final Object data, boolean keepAlive) { |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(callback) |
| || mJSHandler == null) { |
| return; |
| } |
| |
| WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId); |
| if (instance != null && instance.isUsingEaglePlugin()) { |
| int mode = instance.getEaglePlugin().isSupportJSCallback(instanceId); |
| if (mode == WXEaglePlugin.NOT_SUPPORT) { |
| return; |
| } |
| callbackJavascriptOnDataRender(instance.getEaglePlugin(), instanceId, callback, data, keepAlive); |
| if (mode == WXEaglePlugin.EAGLE_ONLY) { |
| return; |
| } |
| //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT |
| } |
| |
| |
| addJSTask(METHOD_CALLBACK, instanceId, callback, data, keepAlive); |
| sendMessage(instanceId, WXJSBridgeMsgType.CALL_JS_BATCH); |
| } |
| |
| void callbackJavascriptOnDataRender(final WXEaglePlugin eaglePlugin, final String instanceId, final String callback, final Object data, final boolean keepAlive){ |
| mJSHandler.postDelayed(WXThread.secure(new Runnable() { |
| @Override |
| public void run() { |
| try { |
| long start = System.currentTimeMillis(); |
| String data_str = JSON.toJSONString(data); |
| if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("callbackJavascriptOnDataRender >>>> instanceId:" + instanceId |
| + ", data:" + data_str); |
| } |
| eaglePlugin.invokeJSCallback(instanceId, callback, data_str, keepAlive); |
| WXLogUtils.renderPerformanceLog("callbackJavascriptOnDataRender", System.currentTimeMillis() - start); |
| } catch (Throwable e) { |
| String err = "[WXBridgeManager] callbackJavascriptOnDataRender " + WXLogUtils.getStackTrace(e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callbackJavascriptOnDataRender", |
| err, null); |
| WXLogUtils.e(err); |
| } |
| } |
| }), 0); |
| } |
| |
| /** |
| * Refresh instance |
| */ |
| public void refreshInstance(final String instanceId, final WXRefreshData jsonData) { |
| if (TextUtils.isEmpty(instanceId) || jsonData == null) { |
| return; |
| } |
| mJSHandler.postDelayed(WXThread.secure(new Runnable() { |
| @Override |
| public void run() { |
| invokeRefreshInstance(instanceId, jsonData); |
| } |
| }), 0); |
| } |
| |
| private void invokeRefreshInstance(String instanceId, WXRefreshData refreshData) { |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (!isSkipFrameworkInit(instanceId) && !isJSFrameworkInit()) { |
| if (instance != null) { |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() |
| + "invokeRefreshInstance FAILED for JSFrameworkInit FAILED, intance will invoke instance.onRenderError" |
| ); |
| } |
| String err = "[WXBridgeManager] invokeRefreshInstance: framework.js uninitialized."; |
| WXLogUtils.e(err); |
| return; |
| } |
| long start = System.currentTimeMillis(); |
| if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("refreshInstance >>>> instanceId:" + instanceId |
| + ", data:" + refreshData.data + ", isDirty:" + refreshData.isDirty); |
| } |
| |
| if (refreshData.isDirty) { |
| return; |
| } |
| WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String, |
| instanceId); |
| WXJSObject dataObj = new WXJSObject(WXJSObject.JSON, |
| refreshData.data == null ? "{}" : refreshData.data); |
| WXJSObject[] args = {instanceIdObj, dataObj}; |
| mWXBridge.refreshInstance(instanceId, null, METHOD_REFRESH_INSTANCE, args); |
| } catch (Throwable e) { |
| String err = "[WXBridgeManager] invokeRefreshInstance " + WXLogUtils.getStackTrace(e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "invokeRefreshInstance", |
| err, null); |
| WXLogUtils.e(err); |
| } |
| } |
| |
| public void commitJscCrashAlarmMonitor(final String type, final WXErrorCode errorCode, String errMsg, |
| String instanceId, String url,Map<String, String> extInfo) { |
| if (TextUtils.isEmpty(type) || errorCode == null) { |
| return; |
| } |
| |
| Log.d("ReportCrash", " commitJscCrashAlarmMonitor errMsg " + errMsg); |
| String method = "callReportCrash"; |
| String exception = "weex core process crash and restart exception"; |
| Map<String, String> extParams = new HashMap<String, String>(); |
| extParams.put("jscCrashStack", errMsg); |
| if (null != extInfo){ |
| extParams.putAll(extInfo); |
| } |
| IWXJSExceptionAdapter adapter = WXSDKManager.getInstance().getIWXJSExceptionAdapter(); |
| if (adapter != null) { |
| WXJSExceptionInfo jsException = new WXJSExceptionInfo(instanceId, url, errorCode, method, exception, extParams); |
| adapter.onJSException(jsException); |
| // if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.e(jsException.toString()); |
| // } |
| } |
| } |
| |
| private boolean isSkipFrameworkInit(String instanceId) { |
| final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| return isSkipFrameworkInit(instance); |
| } |
| |
| private boolean isSkipFrameworkInit(WXSDKInstance instance) { |
| if (instance == null) { |
| return false; |
| } |
| return instance.skipFrameworkInit(); |
| } |
| |
| /** |
| * Create instance. |
| */ |
| public void createInstance(final String instanceId, final String template, |
| final Map<String, Object> options, final String data) { |
| createInstance(instanceId, new Script(template), options, data); |
| } |
| |
| public void setLogLevel(final int level, final boolean isPerf) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| if(mWXBridge != null) { |
| mWXBridge.setLogType(level, isPerf); |
| } |
| } |
| }); |
| } |
| |
| public void createInstance(final String instanceId, final Script template, |
| final Map<String, Object> options, final String data) { |
| final WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance == null) { |
| WXLogUtils.e("WXBridgeManager", "createInstance failed, SDKInstance does not exist"); |
| return; |
| } |
| if (TextUtils.isEmpty(instanceId) || template == null || template.isEmpty() || mJSHandler == null) { |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + |
| " instanceId==" + instanceId + " template ==" + template + " mJSHandler== " + mJSHandler.toString() |
| ); |
| |
| instance.getApmForInstance().onStage("createInstance failed return; "+TextUtils.isEmpty(instanceId)+ ","+template.isEmpty()+","+(mJSHandler ==null)); |
| return; |
| } |
| |
| if (!isSkipFrameworkInit(instanceId) && !isJSFrameworkInit() && reInitCount == 1 && !WXEnvironment.sDebugServerConnectable) { |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + |
| " isJSFrameworkInit==" + isJSFrameworkInit() + " reInitCount == 1" ); |
| instance.getApmForInstance().onStage("createInstance failed jsfm isn't init return;"); |
| post(new Runnable() { |
| @Override |
| public void run() { |
| initFramework(""); |
| } |
| }, instanceId, instance,"initFrameworkInCreateInstance"); |
| return; |
| } |
| |
| WXModuleManager.createDomModule(instance); |
| instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_START); |
| post(new Runnable() { |
| @Override |
| public void run() { |
| instance.getApmForInstance().onStage("wxLoadBundleStartOnJsThread"); |
| long start = System.currentTimeMillis(); |
| mWXBridge.setPageArgument(instanceId, "renderTimeOrigin", String.valueOf(instance.getWXPerformance().renderTimeOrigin)); |
| mWXBridge.setInstanceRenderType(instance.getInstanceId(), instance.getRenderType()); |
| invokeCreateInstance(instance, template, options, data); |
| long end = System.currentTimeMillis(); |
| instance.getWXPerformance().callCreateInstanceTime = end - start; |
| instance.getWXPerformance().communicateTime = instance.getWXPerformance().callCreateInstanceTime; |
| } |
| }, instanceId, instance,"createInstance"); |
| } |
| |
| private void invokeCreateInstance(@NonNull WXSDKInstance instance, Script template, |
| Map<String, Object> options, String data) { |
| // add for sandbox, will delete on sandbox ok |
| if (!isSkipFrameworkInit(instance)){ |
| initFramework(""); |
| } |
| |
| if (mMock) { |
| mock(instance.getInstanceId()); |
| } else { |
| if (!isSkipFrameworkInit(instance) && !isJSFrameworkInit()) { |
| String err = "[WXBridgeManager] invokeCreateInstance: framework.js uninitialized."; |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() |
| ); |
| WXLogUtils.e(err); |
| instance.getApmForInstance().onStage("framework.js uninitialized and return"); |
| return; |
| } |
| |
| WXModuleManager.registerWhenCreateInstance(); |
| |
| try { |
| BundType type = BundType.Others; |
| try { |
| long start = System.currentTimeMillis(); |
| type = getBundleType(instance.getBundleUrl(), template.getContent()); |
| |
| if (WXEnvironment.isOpenDebugLog()) { |
| long end = System.currentTimeMillis(); |
| WXLogUtils.e("end getBundleType type:" + type.toString() + " time:" + (end - start)); |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| |
| try { |
| if (options == null) { |
| options = new HashMap<>(); |
| } |
| // on file there is { "framework": "Vue" } or others |
| if (options.get(BUNDLE_TYPE) == null) { |
| // may vue or Rax |
| if (type == BundType.Vue) { |
| options.put(BUNDLE_TYPE, "Vue"); |
| } else if (type == BundType.Rax) { |
| options.put(BUNDLE_TYPE, "Rax"); |
| } else { |
| options.put(BUNDLE_TYPE, "Others"); |
| } |
| Object recordBundleType = options.get(BUNDLE_TYPE); |
| if (recordBundleType instanceof String && "Others".equalsIgnoreCase((String)recordBundleType)){ |
| //same as iOS record |
| recordBundleType = "other"; |
| } |
| if (null != recordBundleType){ |
| instance.getApmForInstance().addProperty(WXInstanceApm.KEY_PAGE_PROPERTIES_BUNDLE_TYPE, recordBundleType); |
| } |
| } |
| if (options.get("env") == null) { |
| options.put("env", mInitParams.toMap()); |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| instance.bundleType = type; |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| WXLogUtils.d("createInstance >>>> instanceId:" + instance.getInstanceId() |
| + ", options:" |
| + WXJsonUtils.fromObjectToJSONString(options) |
| + ", data:" + data); |
| } |
| WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String, |
| instance.getInstanceId()); |
| WXJSObject instanceObj; |
| WXJSObject scriptType; |
| if (TextUtils.isEmpty(template.getContent())){ |
| //byte[] |
| instanceObj = new WXJSObject(WXJSObject.String, |
| template.getBinary()); |
| scriptType = new WXJSObject(WXJSObject.String, "binary"); |
| } else { |
| //String |
| instanceObj = new WXJSObject(WXJSObject.String, |
| template.getContent()); |
| scriptType = new WXJSObject(WXJSObject.NUMBER, "string"); |
| } |
| |
| |
| Object extraOption = null; |
| if(options != null && options.containsKey("extraOption")) { |
| extraOption = options.get("extraOption"); |
| options.remove("extraOption"); |
| } |
| |
| WXJSObject extraOptionObj = new WXJSObject(WXJSObject.JSON, |
| extraOption == null ? "{}" |
| : WXJsonUtils.fromObjectToJSONString(extraOption)); |
| |
| |
| WXJSObject optionsObj = new WXJSObject(WXJSObject.JSON, |
| options == null ? "{}" |
| : WXJsonUtils.fromObjectToJSONString(options)); |
| optionsObj = optionObjConvert(isSandBoxContext, type, optionsObj); |
| WXJSObject dataObj = new WXJSObject(WXJSObject.JSON, |
| data == null ? "{}" : data); |
| |
| WXJSObject apiObj; |
| if (type == BundType.Rax || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) { |
| if (mRaxApi == null) { |
| IWXJsFileLoaderAdapter iwxJsFileLoaderAdapter = WXSDKEngine.getIWXJsFileLoaderAdapter(); |
| if(iwxJsFileLoaderAdapter != null) { |
| mRaxApi = iwxJsFileLoaderAdapter.loadRaxApi(); |
| } |
| |
| if(TextUtils.isEmpty(mRaxApi)) { |
| mRaxApi = WXFileUtils.loadAsset("weex-rax-api.js", WXEnvironment.getApplication()); |
| } |
| } |
| apiObj = new WXJSObject(WXJSObject.String, |
| mRaxApi); |
| } else { |
| apiObj = new WXJSObject(WXJSObject.String, |
| ""); |
| } |
| |
| // When render strategy is data_render, put it into options. Others keep null. |
| WXJSObject renderStrategy = null; |
| if (instance.isUsingEaglePlugin()) { |
| //Eagle use plugin name as renderStrategy |
| renderStrategy = new WXJSObject(WXJSObject.String, instance.getEaglePluginName()); |
| } else if (instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER) { |
| //todo just for compat |
| //using eagle mode without eagle plugin, will report exception in c if no plugin was found. |
| renderStrategy = new WXJSObject(WXJSObject.String, "DATA_RENDER"); |
| } else if (instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) { |
| renderStrategy = new WXJSObject(WXJSObject.String, WXRenderStrategy.JSON_RENDER.getFlag()); |
| } |
| |
| WXJSObject[] args = {instanceIdObj, instanceObj, optionsObj, |
| dataObj, apiObj, renderStrategy, extraOptionObj}; |
| |
| instance.setTemplate(template.getContent()); |
| |
| instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END); |
| |
| // if { "framework": "Vue" } or { "framework": "Rax" } will use invokeCreateInstanceContext |
| // others will use invokeExecJS |
| if (!isSandBoxContext) { |
| instance.getApmForInstance().onStage("!isSandBoxContext,and excute"); |
| WXLogUtils.e("Instance " + instance.getInstanceId() + " Did Not Render in SandBox Mode"); |
| invokeExecJS(instance.getInstanceId(), null, METHOD_CREATE_INSTANCE, args, false); |
| return; |
| } |
| if (type == BundType.Vue || type == BundType.Rax |
| || instance.isUsingEaglePlugin() |
| || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY //Todo only for compat when plugin not registered |
| || instance.getRenderStrategy() == WXRenderStrategy.DATA_RENDER |
| || instance.getRenderStrategy() == WXRenderStrategy.JSON_RENDER) { |
| instance.getApmForInstance().onStage("wxBeforeInvokeCreateInstanceContext"); |
| |
| WXLogUtils.d("Instance " + instance.getInstanceId() + " Render in SandBox Mode And Render Type is " |
| + type + " Render Strategy is " + instance.getRenderStrategy()); |
| //extra args for create instance. |
| args = Arrays.copyOf(args,args.length+1); |
| args[args.length -1 ] = scriptType; |
| |
| int ret = invokeCreateInstanceContext(instance.getInstanceId(), null, "createInstanceContext", args, false); |
| instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END); |
| if(ret == 0) { |
| String err = "[WXBridgeManager] invokeCreateInstance : " + instance.getTemplateInfo(); |
| WXLogUtils.e("Instance " + instance.getInstanceId() + "Render error : " + err); |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + err); |
| } |
| return; |
| } else { |
| //bad case for js bundle with out bundletype header //vue or rax |
| //WXExceptionUtils.commitCriticalExceptionRT( |
| // instance.getInstanceId(), |
| // WXErrorCode.WX_KEY_EXCEPTION_NO_BUNDLE_TYPE, |
| // "invokeCreateInstance", |
| // WXErrorCode.WX_KEY_EXCEPTION_NO_BUNDLE_TYPE.getErrorMsg(), |
| // null |
| //); |
| |
| WXLogUtils.d("Instance " + instance.getInstanceId() + "Did not Render in SandBox Mode And Render Type is " |
| + type + " Render Strategy is " + instance.getRenderStrategy()); |
| instance.getApmForInstance().onStage("StartInvokeExecJSBadBundleType"); |
| invokeExecJS(instance.getInstanceId(), null, METHOD_CREATE_INSTANCE, args, false); |
| instance.getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_END); |
| return; |
| } |
| } catch (Throwable e) { |
| String err = "[WXBridgeManager] invokeCreateInstance " + e.getCause() |
| + instance.getTemplateInfo(); |
| instance.getApmForInstance().onStage("createInstance error :"+e.toString()); |
| WXLogUtils.e("Instance " + instance.getInstanceId() + "Render error : " + err); |
| instance.onRenderError( |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg() + err); |
| WXLogUtils.e(err); |
| } |
| } |
| } |
| |
| public WXJSObject optionObjConvert(boolean useSandBox, BundType type, WXJSObject opt) { |
| if (!useSandBox) { |
| return opt; |
| } |
| try { |
| String data = opt.data.toString(); |
| JSONObject obj = JSON.parseObject(data); |
| JSONObject optEnv; |
| if ((optEnv = obj.getJSONObject("env")) != null) { |
| JSONObject opts = optEnv.getJSONObject("options"); |
| if (opts != null) { |
| for (String s : opts.keySet()) { |
| optEnv.put(s, opts.getString(s)); |
| } |
| } |
| } |
| return new WXJSObject(WXJSObject.JSON, obj.toString()); |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| return opt; |
| |
| } |
| |
| /** |
| * check bundleType |
| * @param url |
| * @param temp |
| * @return |
| */ |
| public BundType getBundleType(String url, String temp) { |
| try { |
| if (url != null) { |
| Uri uri = Uri.parse(url); |
| String type = uri.getQueryParameter(BUNDLE_TYPE); |
| if ("Vue".equals(type) || "vue".equals(type)) { |
| return BundType.Vue; |
| } else if ("Rax".equals(type) || "rax".equals(type)) { |
| return BundType.Rax; |
| } |
| } |
| if (temp != null) { |
| final String FRAMEWORK="framework", VUE="vue", RAX="rax"; |
| |
| // Find the first line that starts with '//' and convert it to json |
| int bundleTypeStart = temp.indexOf("//"); |
| int bundleTypeEnd = temp.indexOf("\n", bundleTypeStart); |
| JSONObject bundleType = JSONObject.parseObject( |
| temp.substring(bundleTypeStart+2, bundleTypeEnd)); |
| String type = bundleType.getString(FRAMEWORK); |
| if(VUE.equalsIgnoreCase(type)){ |
| return BundType.Vue; |
| } |
| else if(RAX.equalsIgnoreCase(type)){ |
| return BundType.Rax; |
| } |
| else{ |
| // '//{ "framework": "Vue"}' is not found. |
| String regEx = "(use)(\\s+)(weex:vue)"; |
| Pattern pattern = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); |
| if (pattern.matcher(temp).find()) { |
| return BundType.Vue; |
| } |
| regEx = "(use)(\\s+)(weex:rax)"; |
| pattern = Pattern.compile(regEx, Pattern.CASE_INSENSITIVE); |
| if (pattern.matcher(temp).find()) { |
| return BundType.Rax; |
| } |
| } |
| } |
| return BundType.Others; |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| return BundType.Others; |
| } |
| } |
| |
| private void mock(String instanceId) { |
| |
| } |
| |
| public void destroyInstance(final String instanceId) { |
| if (mJSHandler == null |
| || TextUtils.isEmpty(instanceId)) { |
| return; |
| } |
| if (mDestroyedInstanceId != null) { |
| mDestroyedInstanceId.add(instanceId); |
| } |
| // clear message with instanceId |
| mJSHandler.removeCallbacksAndMessages(instanceId); |
| post(new Runnable() { |
| @Override |
| public void run() { |
| removeTaskByInstance(instanceId); |
| invokeDestroyInstance(instanceId); |
| } |
| }, instanceId, null, "destroyInstance"); |
| } |
| |
| private void removeTaskByInstance(String instanceId) { |
| mNextTickTasks.removeFromMapAndStack(instanceId); |
| } |
| |
| private void invokeDestroyInstance(String instanceId) { |
| try { |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| WXLogUtils.d("destroyInstance >>>> instanceId:" + instanceId); |
| } |
| WXJSObject instanceIdObj = new WXJSObject(WXJSObject.String, |
| instanceId); |
| WXJSObject[] args = {instanceIdObj}; |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| invokeDestoryInstance(instanceId, null, METHOD_DESTROY_INSTANCE, args, true); |
| // invokeExecJS(instanceId, null, METHOD_DESTROY_INSTANCE, args); |
| } |
| } catch (Throwable e) { |
| String err = "[WXBridgeManager] invokeDestroyInstance " + e.getCause(); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "invokeDestroyInstance", err, null); |
| WXLogUtils.e(err); |
| } |
| } |
| |
| @Override |
| public boolean handleMessage(Message msg) { |
| if (msg == null) { |
| return false; |
| } |
| |
| int what = msg.what; |
| switch (what) { |
| case WXJSBridgeMsgType.INIT_FRAMEWORK: |
| invokeInitFramework(msg); |
| break; |
| case WXJSBridgeMsgType.CALL_JS_BATCH: |
| invokeCallJSBatch(msg); |
| break; |
| case WXJSBridgeMsgType.SET_TIMEOUT: |
| TimerInfo timerInfo = (TimerInfo) msg.obj; |
| if (timerInfo == null) { |
| break; |
| } |
| WXJSObject obj = new WXJSObject(WXJSObject.String, timerInfo.callbackId); |
| WXJSObject[] args = {obj}; |
| invokeExecJS("", null, METHOD_SET_TIMEOUT, args); |
| break; |
| case WXJSBridgeMsgType.TAKE_HEAP_SNAPSHOT: |
| if (msg.obj != null) { |
| String filename = (String) msg.obj; |
| mWXBridge.takeHeapSnapshot(filename); |
| } |
| break; |
| default: |
| break; |
| } |
| return false; |
| } |
| |
| private void invokeExecJS(String instanceId, String namespace, String function, WXJSObject[] args) { |
| invokeExecJS(instanceId, namespace, function, args, true); |
| } |
| |
| public void invokeExecJS(final String instanceId, final String namespace, final String function, |
| final WXJSObject[] args, boolean logTaskDetail) { |
| if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("callJS >>>> instanceId:").append(instanceId) |
| .append("function:").append(function); |
| if (logTaskDetail) { |
| mLodBuilder.append(" tasks:").append(argsToJSON(args)); |
| } |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| final long start = System.currentTimeMillis(); |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| |
| if (instance != null && instance.isUsingEaglePlugin()) { |
| final WXEaglePlugin eaglePlugin = instance.getEaglePlugin(); |
| int mode = eaglePlugin.isSupportInvokeExecJS(instanceId); |
| if (mode == WXEaglePlugin.NOT_SUPPORT){ |
| return; |
| } |
| WXThread.secure(new Runnable() { |
| @Override |
| public void run() { |
| eaglePlugin.invokeExecJS(instanceId, namespace, function,args ); |
| } |
| }, instance, "ExecJsEagle").run(); |
| if (mode == WXEaglePlugin.EAGLE_ONLY){ |
| if (null != instance){ |
| long diff = System.currentTimeMillis()-start; |
| instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1); |
| instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_TIME,diff); |
| instance.callJsTime(diff); |
| } |
| return; |
| } |
| //assert mode == WXEaglePlugin.EAGLE_AND_SCRIPT |
| } |
| |
| WXThread.secure(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.execJS(instanceId, namespace, function, args); |
| } |
| }, instance, "ExecJs").run(); |
| if (null != instance){ |
| long diff = System.currentTimeMillis()-start; |
| instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_NUM,1); |
| instance.getApmForInstance().updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_JS_TIME,diff); |
| instance.callJsTime(diff); |
| } |
| } |
| |
| private Pair<Pair<String,Object>,Boolean> extractCallbackArgs(String data) { |
| try { |
| JSONArray obj = JSON.parseArray(data); |
| JSONObject arg_obj = obj.getJSONObject(0); |
| JSONArray args = arg_obj.getJSONArray("args"); |
| if (args.size()!=3){ |
| return null; |
| } |
| String method = arg_obj.getString("method"); |
| if (!"callback".equals(method)){ |
| return null; |
| } |
| |
| return new Pair<Pair<String,Object>, Boolean>(new Pair<String, Object>(args.getString(0), args.getJSONObject(1)),args.getBooleanValue(2)); |
| } catch (Exception e) { |
| return null; |
| } |
| } |
| |
| public int invokeCreateInstanceContext(String instanceId, String namespace, String function, |
| WXJSObject[] args, boolean logTaskDetail) { |
| WXLogUtils.d("invokeCreateInstanceContext instanceId:" + instanceId + " function:" |
| + function + String.format(" isJSFrameworkInit:%b", isJSFrameworkInit())); |
| mLodBuilder.append("createInstanceContext >>>> instanceId:").append(instanceId) |
| .append("function:").append(function); |
| if (logTaskDetail) |
| mLodBuilder.append(" tasks:").append(WXJsonUtils.fromObjectToJSONString(args)); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| // } |
| return mWXBridge.createInstanceContext(instanceId, namespace, function, args); |
| } |
| |
| public void invokeDestoryInstance(String instanceId, String namespace, String function, |
| WXJSObject[] args, boolean logTaskDetail) { |
| // if (WXEnvironment.isApkDebugable()) { |
| mLodBuilder.append("callJS >>>> instanceId:").append(instanceId) |
| .append("function:").append(function); |
| if (logTaskDetail) |
| mLodBuilder.append(" tasks:").append(WXJsonUtils.fromObjectToJSONString(args)); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| // } |
| mWXBridge.removeInstanceRenderType(instanceId); |
| mWXBridge.destoryInstance(instanceId, namespace, function, args); |
| } |
| |
| private void execJSOnInstance(final EventResult eventCallback, final String instanceId, final String js, final int type) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| String ret = invokeExecJSOnInstance(instanceId, js, type); |
| eventCallback.onCallback(ret); |
| } |
| }); |
| } |
| |
| private String invokeExecJSOnInstance(String instanceId, String js, int type) { |
| // if (WXEnvironment.isApkDebugable()) { |
| mLodBuilder.append("execJSOnInstance >>>> instanceId:").append(instanceId); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| // } |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| return mWXBridge.execJSOnInstance(instanceId, js, type); |
| } |
| return null; |
| } |
| |
| private void invokeExecJSWithCallback(String instanceId, String namespace, String function, |
| WXJSObject[] args , ResultCallback callback, boolean logTaskDetail){ |
| if (WXEnvironment.isOpenDebugLog() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("callJS >>>> instanceId:").append(instanceId) |
| .append("function:").append(function); |
| if(logTaskDetail) { |
| mLodBuilder.append(" tasks:").append(argsToJSON(args)); |
| } |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.execJSWithCallback(instanceId, namespace, function, args, callback); |
| } |
| } |
| |
| public @NonNull static String argsToJSON(WXJSObject[] args) { |
| StringBuilder builder = new StringBuilder(); |
| builder.append("["); |
| for(WXJSObject object : args){ |
| builder.append(WXWsonJSONSwitch.fromObjectToJSONString(object)); |
| builder.append(","); |
| } |
| builder.append("]"); |
| return builder.toString(); |
| } |
| |
| private void invokeInitFramework(Message msg) { |
| String framework = ""; |
| if (msg.obj != null) { |
| framework = (String) msg.obj; |
| } |
| |
| if (WXUtils.getAvailMemory(WXEnvironment.getApplication()) > LOW_MEM_VALUE) { |
| initFramework(framework); |
| } |
| } |
| |
| public static long sInitFrameWorkTimeOrigin; |
| public static StringBuilder sInitFrameWorkMsg = new StringBuilder(); |
| |
| private void initFramework(String framework) { |
| LogDetail logDetail = new LogDetail(); |
| logDetail.name("initFramework"); |
| logDetail.taskStart(); |
| if (WXSDKEngine.isSoInitialized() && !isJSFrameworkInit()) { |
| sInitFrameWorkTimeOrigin = System.currentTimeMillis(); |
| if (TextUtils.isEmpty(framework)) { |
| // if (WXEnvironment.isApkDebugable()) { |
| WXLogUtils.d("weex JS framework from assets"); |
| // } |
| |
| LogDetail logDetail2 = new LogDetail(); |
| logDetail2.name("loadJSFramework"); |
| logDetail2.taskStart(); |
| |
| IWXJsFileLoaderAdapter wxJsFileLoaderAdapter = WXSDKEngine.getIWXJsFileLoaderAdapter(); |
| |
| if (!isSandBoxContext) { |
| if(wxJsFileLoaderAdapter != null) { |
| framework = wxJsFileLoaderAdapter.loadJsFramework(); |
| } |
| |
| if(TextUtils.isEmpty(framework)) { |
| framework = WXFileUtils.loadAsset("main.js", WXEnvironment.getApplication()); |
| } |
| } else { |
| if(wxJsFileLoaderAdapter != null) { |
| framework = wxJsFileLoaderAdapter.loadJsFrameworkForSandBox(); |
| } |
| |
| if(TextUtils.isEmpty(framework)) { |
| framework = WXFileUtils.loadAsset("weex-main-jsfm.js", WXEnvironment.getApplication()); |
| } |
| } |
| sInitFrameWorkMsg.append("| weex JS framework from assets, isSandBoxContext: ").append(isSandBoxContext); |
| logDetail2.taskEnd(); |
| } |
| if (TextUtils.isEmpty(framework)) { |
| setJSFrameworkInit(false); |
| sInitFrameWorkMsg.append("| framework isEmpty "); |
| WXExceptionUtils.commitCriticalExceptionRT(null, WXErrorCode.WX_ERR_JS_FRAMEWORK, |
| "initFramework", "framework is empty!! ", null); |
| return; |
| } |
| try { |
| if (WXSDKManager.getInstance().getWXStatisticsListener() != null) { |
| long start = System.currentTimeMillis(); |
| WXSDKManager.getInstance().getWXStatisticsListener().onJsFrameworkStart(); |
| WXEnvironment.sJSFMStartListenerTime = System.currentTimeMillis() - start; |
| try { |
| IWXUserTrackAdapter adapter = WXSDKManager.getInstance().getIWXUserTrackAdapter(); |
| if (null != adapter){ |
| Map<String,Serializable> params = new HashMap<>(1); |
| params.put("time",String.valueOf(WXEnvironment.sJSFMStartListenerTime)); |
| adapter.commit(WXEnvironment.getApplication(),"sJSFMStartListener",IWXUserTrackAdapter.COUNTER,null,params); |
| } |
| }catch (Exception e){ |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| } |
| |
| long start = System.currentTimeMillis(); |
| String crashFile = ""; |
| try { |
| crashFile = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath(); |
| } catch (Exception e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| boolean pieSupport = true; |
| try { |
| if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) { |
| pieSupport = false; |
| } |
| } catch (Exception e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| sInitFrameWorkMsg.append(" | pieSupport:").append(pieSupport); |
| WXLogUtils.d("[WXBridgeManager] initFrameworkEnv crashFile:" + crashFile + " pieSupport:" + pieSupport); |
| // extends initFramework |
| LogDetail logDetail3 = new LogDetail(); |
| logDetail3.name("native initFrameworkEnv"); |
| logDetail3.taskStart(); |
| if (mWXBridge.initFrameworkEnv(framework, assembleDefaultOptions(), crashFile, pieSupport) == INIT_FRAMEWORK_OK) { |
| logDetail3.taskEnd(); |
| WXEnvironment.sJSLibInitTime = System.currentTimeMillis() - start; |
| WXEnvironment.sSDKInitTime = System.currentTimeMillis() - WXEnvironment.sSDKInitStart; |
| setJSFrameworkInit(true); |
| logDetail.taskEnd(); |
| if (WXSDKManager.getInstance().getWXStatisticsListener() != null) { |
| WXSDKManager.getInstance().getWXStatisticsListener().onJsFrameworkReady(); |
| } |
| |
| execRegisterFailTask(); |
| WXEnvironment.JsFrameworkInit = true; |
| sInitFrameWorkCount++; |
| WXLogUtils.e("initFrameWorkCount :"+ sInitFrameWorkCount); |
| registerDomModule(); |
| trackComponentAndModulesTime(); |
| } else { |
| sInitFrameWorkMsg.append(" | ExecuteJavaScript fail, reInitCount").append(reInitCount); |
| if (reInitCount > 1) { |
| WXLogUtils.e("[WXBridgeManager] invokeReInitFramework ExecuteJavaScript fail"); |
| } else { |
| WXLogUtils.e("[WXBridgeManager] invokeInitFramework ExecuteJavaScript fail"); |
| } |
| } |
| } catch (Throwable e) { |
| sInitFrameWorkMsg.append(" | invokeInitFramework exception ").append(e.toString()); |
| if (reInitCount > 1) { |
| WXLogUtils.e("[WXBridgeManager] invokeInitFramework ", e); |
| } else { |
| WXLogUtils.e("[WXBridgeManager] invokeInitFramework ", e); |
| } |
| } |
| |
| } |
| } |
| |
| private void trackComponentAndModulesTime() { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| WXEnvironment.sComponentsAndModulesReadyTime = System.currentTimeMillis() - WXEnvironment.sSDKInitStart; |
| } |
| }); |
| } |
| |
| @SuppressWarnings("unchecked") |
| private void invokeCallJSBatch(Message message) { |
| if (mNextTickTasks.isEmpty() || !isJSFrameworkInit()) { |
| if (!isJSFrameworkInit()) { |
| WXLogUtils.e("[WXBridgeManager] invokeCallJSBatch: framework.js uninitialized!! message:" + message.toString()); |
| } |
| return; |
| } |
| |
| try { |
| Object instanceId = message.obj; |
| |
| Object task = null; |
| Stack<String> instanceStack = mNextTickTasks.getInstanceStack(); |
| int size = instanceStack.size(); |
| for (int i = size - 1; i >= 0; i--) { |
| instanceId = instanceStack.get(i); |
| task = mNextTickTasks.remove(instanceId); |
| if (task != null && !((ArrayList) task).isEmpty()) { |
| break; |
| } |
| } |
| if (null != task){ |
| task = ((ArrayList) task).toArray(); |
| |
| WXJSObject[] args = { |
| new WXJSObject(WXJSObject.String, instanceId), |
| WXWsonJSONSwitch.toWsonOrJsonWXJSObject(task)}; |
| |
| invokeExecJS(String.valueOf(instanceId), null, METHOD_CALL_JS, args); |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e("WXBridgeManager", e); |
| String err = "invokeCallJSBatch#" + WXLogUtils.getStackTrace(e); |
| WXExceptionUtils.commitCriticalExceptionRT(null, WXErrorCode.WX_ERR_JS_FRAMEWORK, |
| "invokeCallJSBatch", err, null); |
| } |
| |
| // If task is not empty, loop until it is empty |
| if (!mNextTickTasks.isEmpty()) { |
| mJSHandler.sendEmptyMessage(WXJSBridgeMsgType.CALL_JS_BATCH); |
| } |
| } |
| |
| private WXParams assembleDefaultOptions() { |
| checkJsEngineMultiThread(); |
| |
| Map<String, String> config = WXEnvironment.getConfig(); |
| WXParams wxParams = new WXParams(); |
| wxParams.setPlatform(config.get(WXConfig.os)); |
| wxParams.setCacheDir(config.get(WXConfig.cacheDir)); |
| wxParams.setOsVersion(config.get(WXConfig.sysVersion)); |
| wxParams.setAppVersion(config.get(WXConfig.appVersion)); |
| wxParams.setWeexVersion(config.get(WXConfig.weexVersion)); |
| wxParams.setDeviceModel(config.get(WXConfig.sysModel)); |
| wxParams.setShouldInfoCollect(config.get("infoCollect")); |
| wxParams.setLogLevel(config.get(WXConfig.logLevel)); |
| wxParams.setLayoutDirection(config.get(WXConfig.layoutDirection)); |
| wxParams.setUseSingleProcess(isUseSingleProcess ? "true" : "false"); |
| wxParams.setCrashFilePath(WXEnvironment.getCrashFilePath(WXEnvironment.getApplication().getApplicationContext())); |
| wxParams.setLibJsbPath(WXEnvironment.CORE_JSB_SO_PATH); |
| wxParams.setLibJssPath(WXEnvironment.getLibJssRealPath()); |
| wxParams.setLibIcuPath(WXEnvironment.getLibJssIcuPath()); |
| wxParams.setLibLdPath(WXEnvironment.getLibLdPath()); |
| String libJScRealPath = WXEnvironment.getLibJScRealPath(); |
| wxParams.setLibJscPath(TextUtils.isEmpty(libJScRealPath)? "" : new File(libJScRealPath).getParent()); |
| String appName = config.get(WXConfig.appName); |
| if (!TextUtils.isEmpty(appName)) { |
| wxParams.setAppName(appName); |
| } |
| wxParams.setDeviceWidth(TextUtils.isEmpty(config.get("deviceWidth")) ? String.valueOf(WXViewUtils.getScreenWidth(WXEnvironment.sApplication)) : config.get("deviceWidth")); |
| wxParams.setDeviceHeight(TextUtils.isEmpty(config.get("deviceHeight")) ? String.valueOf(WXViewUtils.getScreenHeight(WXEnvironment.sApplication)) : config.get("deviceHeight")); |
| Map<String, String> customOptions = WXEnvironment.getCustomOptions(); |
| customOptions.put("enableBackupThread", String.valueOf(jsEngineMultiThreadEnable())); |
| IWXJscProcessManager wxJscProcessManager = WXSDKManager.getInstance().getWXJscProcessManager(); |
| if(wxJscProcessManager != null) { |
| customOptions.put("enableBackupThreadCache", String.valueOf(wxJscProcessManager.enableBackUpThreadCache())); |
| } |
| |
| if (!WXEnvironment.sUseRunTimeApi){ |
| customOptions.put("__enable_native_promise__","true"); |
| } |
| |
| String enableAlarmSignal = "true"; |
| IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter(); |
| if (null != adapter){ |
| try { |
| if (adapter.checkMode("white_screen_fix_open")){ |
| WXEnvironment.isWsFixMode = true; |
| enableAlarmSignal = "true"; |
| }else { |
| enableAlarmSignal = adapter.getConfigWhenInit("wxapm","enableAlarmSignal",enableAlarmSignal); |
| WXEnvironment.isWsFixMode = "true".equalsIgnoreCase(enableAlarmSignal); |
| } |
| }catch (Exception e){ |
| e.printStackTrace(); |
| } |
| } |
| if (null != enableAlarmSignal){ |
| customOptions.put("enableAlarmSignal",enableAlarmSignal); |
| } |
| WXLogUtils.e("weex","enableAlarmSignal:"+enableAlarmSignal); |
| |
| wxParams.setOptions(customOptions); |
| wxParams.setNeedInitV8(WXSDKManager.getInstance().needInitV8()); |
| mInitParams = wxParams; |
| return wxParams; |
| } |
| |
| public WXParams getInitParams() { |
| return mInitParams; |
| } |
| |
| private void execRegisterFailTask() { |
| |
| if (mRegisterModuleFailList.size() > 0) { |
| List<Map<String, Object>> moduleReceiver = new ArrayList<>(); |
| for (int i = 0, moduleCount = mRegisterModuleFailList.size(); i < moduleCount; ++i) { |
| invokeRegisterModules(mRegisterModuleFailList.get(i), moduleReceiver); |
| } |
| mRegisterModuleFailList.clear(); |
| if (moduleReceiver.size() > 0) { |
| mRegisterModuleFailList.addAll(moduleReceiver); |
| } |
| } |
| |
| if (mRegisterComponentFailList.size() > 0) { |
| List<Map<String, Object>> receiver = new ArrayList<>(); |
| invokeRegisterComponents(mRegisterComponentFailList, receiver); |
| mRegisterComponentFailList.clear(); |
| if (receiver.size() > 0) { |
| mRegisterComponentFailList.addAll(receiver); |
| } |
| } |
| |
| if (mRegisterServiceFailList.size() > 0) { |
| List<String> receiver = new ArrayList<>(); |
| for (String service : mRegisterServiceFailList) { |
| invokeExecJSService(service, receiver); |
| } |
| mRegisterServiceFailList.clear(); |
| if (receiver.size() > 0) { |
| mRegisterServiceFailList.addAll(receiver); |
| } |
| } |
| } |
| |
| /** |
| * Register Android module |
| * |
| * @param modules the format is like |
| * {'dom':['updateAttrs','updateStyle'],'event':['openUrl']} |
| */ |
| |
| public void registerModules(final Map<String, Object> modules) { |
| if (modules != null && modules.size() != 0) { |
| if (isJSThread()) { |
| invokeRegisterModules(modules, mRegisterModuleFailList); |
| } else { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| invokeRegisterModules(modules, mRegisterModuleFailList); |
| } |
| }); |
| } |
| } |
| } |
| |
| /** |
| * Registered component |
| */ |
| public void registerComponents(final List<Map<String, Object>> components) { |
| if (mJSHandler == null || components == null |
| || components.size() == 0) { |
| return; |
| } |
| Runnable runnable = new Runnable() { |
| @Override |
| public void run() { |
| invokeRegisterComponents(components, mRegisterComponentFailList); |
| } |
| }; |
| |
| if(isJSThread() && isJSFrameworkInit()){ |
| runnable.run(); |
| }else{ |
| post(runnable); |
| } |
| } |
| |
| public void execJSService(final String service) { |
| postWithName(new Runnable() { |
| @Override |
| public void run() { |
| invokeExecJSService(service, mRegisterServiceFailList); |
| } |
| },null,"execJSService"); |
| } |
| |
| private void invokeExecJSService(String service, List<String> receiver) { |
| try { |
| if (!isJSFrameworkInit()) { |
| WXLogUtils.e("[WXBridgeManager] invoke execJSService: framework.js uninitialized."); |
| receiver.add(service); |
| return; |
| } |
| mWXBridge.execJSService(service); |
| } catch (Throwable e) { |
| WXLogUtils.e("[WXBridgeManager] invokeRegisterService:", e); |
| |
| Map<String, String> data = new HashMap<String, String>(); |
| data.put("inputParams",service + "||" + receiver.toString()); |
| |
| WXExceptionUtils.commitCriticalExceptionRT("invokeExecJSService", |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_JSSERVICE_EXECUTE, |
| "invokeExecJSService", |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_JSSERVICE_EXECUTE.getErrorMsg() |
| + "[WXBridgeManager] invokeRegisterService:" |
| + WXLogUtils.getStackTrace(e), |
| data); |
| } |
| } |
| |
| public boolean isJSThread() { |
| return mJSThread != null && mJSThread.getId() == Thread.currentThread().getId(); |
| } |
| |
| private void invokeRegisterModules(Map<String, Object> modules, List<Map<String, Object>> failReceiver) { |
| if (modules == null || !isJSFrameworkInit()) { |
| if (!isJSFrameworkInit()) { |
| WXLogUtils.d("[WXinvokeRegisterModulesBridgeManager] invokeRegisterModules: framework.js uninitialized."); |
| } |
| failReceiver.add(modules); |
| return; |
| } |
| |
| WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(modules)}; |
| String errorMsg = null; |
| try { |
| if(0 == mWXBridge.execJS("", null, METHOD_REGISTER_MODULES, args)) { |
| errorMsg = "execJS error"; |
| } |
| try { |
| Iterator<String> iter = modules.keySet().iterator(); |
| while (iter.hasNext()) { |
| String module = iter.next(); |
| if (module != null) { |
| WXModuleManager.resetModuleState(module, true); |
| //WXLogUtils.e("[WXBridgeManager]invokeRegisterModules METHOD_REGISTER_MODULES success module:" + module); |
| } |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e("Weex [invokeRegisterModules]", e); |
| } |
| } catch (Throwable e) { |
| errorMsg = WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES.getErrorMsg() + |
| " \n " + e.getMessage() + modules.entrySet().toString(); |
| } |
| |
| if(!TextUtils.isEmpty(errorMsg)) { |
| WXLogUtils.e("[WXBridgeManager] invokeRegisterModules:", errorMsg); |
| WXExceptionUtils.commitCriticalExceptionRT(null, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_MODULES, |
| "invokeRegisterModules", errorMsg, |
| null ); |
| } |
| } |
| |
| private void invokeRegisterComponents(List<Map<String, Object>> components, List<Map<String, Object>> failReceiver) { |
| if (components == failReceiver) { |
| throw new RuntimeException("Fail receiver should not use source."); |
| } |
| if (!isJSFrameworkInit()) { |
| //WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents: framework.js uninitialized."); |
| |
| for (Map<String, Object> comp : components) { |
| failReceiver.add(comp); |
| } |
| return; |
| } |
| if (components == null) { |
| return; |
| } |
| |
| WXJSObject[] args = {WXWsonJSONSwitch.toWsonOrJsonWXJSObject(components)}; |
| String errorMsg = null; |
| try { |
| if(0 == mWXBridge.execJS("", null, METHOD_REGISTER_COMPONENTS, args)) { |
| errorMsg = "execJS error"; |
| } |
| } catch (Throwable e) { |
| errorMsg = WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_COMPONENT |
| + args.toString() |
| + WXLogUtils.getStackTrace(e); |
| } |
| |
| if(!TextUtils.isEmpty(errorMsg)) { |
| WXLogUtils.e("[WXBridgeManager] invokeRegisterComponents ", errorMsg); |
| WXExceptionUtils.commitCriticalExceptionRT(null, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_REGISTER_COMPONENT, |
| METHOD_REGISTER_COMPONENTS, errorMsg, |
| null); |
| } |
| } |
| |
| public void destroy() { |
| if (mJSThread != null) { |
| mJSThread.quit(); |
| } |
| mBridgeManager = null; |
| if (mDestroyedInstanceId != null) { |
| mDestroyedInstanceId.clear(); |
| } |
| |
| } |
| |
| /** |
| * Report JavaScript Exception |
| */ |
| public void reportJSException(String instanceId, String function, |
| String exception) { |
| WXLogUtils.e("reportJSException >>>> instanceId:" + instanceId |
| + ", exception function:" + function + ", exception:" |
| + exception); |
| WXSDKInstance instance = null; |
| WXErrorCode reportErrorCode = WXErrorCode.WX_ERR_JS_EXECUTE; |
| if (instanceId != null && (instance = WXSDKManager.getInstance().getSDKInstance(instanceId)) != null) { |
| instance.setHasException(true); |
| exception += "\n getTemplateInfo==" +instance.getTemplateInfo();//add network header info |
| if ((METHOD_CREATE_INSTANCE.equals(function)) || !instance.isContentMd5Match()) { |
| try { |
| //data render mode should report exception instead of reload page, |
| // so we use !isSkipFrameworkInit(instanceId) to skip the positive branch of if clause. |
| if (!isSkipFrameworkInit(instanceId) && isJSFrameworkInit() && (reInitCount > 1 && reInitCount < 10) && !instance.isNeedReLoad()) { |
| new ActionReloadPage(instanceId, true).executeAction(); |
| instance.setNeedLoad(true); |
| return; |
| } else { |
| String errorMsg = new StringBuilder() |
| .append(WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorMsg()) |
| .append(", exception function:").append(function) |
| .append(", exception:").append(exception) |
| .append(", extInitTime:").append(System.currentTimeMillis()-WXBridgeManager.sInitFrameWorkTimeOrigin).append("ms") |
| .append(", extInitErrorMsg:").append(WXBridgeManager.sInitFrameWorkMsg.toString()) |
| .toString(); |
| instance.onRenderError(//DegradPassivity to H5 |
| WXErrorCode.WX_DEGRAD_ERR_INSTANCE_CREATE_FAILED.getErrorCode(), |
| errorMsg |
| ); |
| if (!WXEnvironment.sInAliWeex){ |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE, function,exception,null); |
| } |
| return; |
| } |
| } catch (Exception e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| } |
| if (METHOD_CREATE_INSTANCE.equals(function) && !instance.getApmForInstance().hasAddView){ |
| reportErrorCode = WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE; |
| } else if ( METHOD_CREATE_INSTANCE_CONTEXT.equals(function) && !instance.getApmForInstance().hasAddView){ |
| reportErrorCode = WXErrorCode.WX_RENDER_ERR_JS_CREATE_INSTANCE_CONTEXT; |
| } else if ( |
| (METHOD_UPDATE_COMPONENT_WITH_DATA.equals(function) || |
| METHOD_CREATE_PAGE_WITH_CONTENT.equals(function) || |
| METHOD_POST_TASK_TO_MSG_LOOP.equals(function) || |
| METHOD_JSFM_NOT_INIT_IN_EAGLE_MODE.equals(function) ) |
| && !instance.getApmForInstance().hasAddView){ |
| reportErrorCode = WXErrorCode.WX_DEGRAD_EAGLE_RENDER_ERROR; |
| } else if (METHOD_MOVE_RENDER_OBJECT.equals(function)) { |
| reportErrorCode = WXErrorCode.WX_ERROR_MOVE_RENDER_OBJECT_OUT_OF_BOUNDS; |
| } |
| instance.onJSException(reportErrorCode.getErrorCode(), function, exception); |
| } |
| doReportJSException(instanceId,function,reportErrorCode,exception); |
| } |
| |
| private void doReportJSException(String instanceId, String function,WXErrorCode reportCode, String exception){ |
| WXSDKInstance instance = WXSDKManager.getInstance().getAllInstanceMap().get(instanceId); |
| IWXJSExceptionAdapter adapter = WXSDKManager.getInstance().getIWXJSExceptionAdapter(); |
| if (adapter != null) { |
| String exceptionId = instanceId; |
| |
| if (TextUtils.isEmpty(instanceId)) { |
| exceptionId = "instanceIdisNull"; |
| } |
| |
| if (instance == null) { |
| if (("initFramework").equals(function)) { |
| String exceptionExt = null; |
| try { |
| if (WXEnvironment.getApplication() != null) { |
| final String fileName = WXEnvironment.getApplication().getApplicationContext().getCacheDir().getPath() + INITLOGFILE; |
| try { |
| File file = new File(fileName); |
| if (file.exists()) { |
| if (file.length() > 0) { |
| StringBuilder result = new StringBuilder(); |
| try { |
| InputStreamReader read = new InputStreamReader(new FileInputStream(file), "UTF-8"); |
| BufferedReader br = new BufferedReader(read); |
| String s = null; |
| while ((s = br.readLine()) != null) { |
| result.append(s + "\n"); |
| } |
| exceptionExt = result.toString(); |
| br.close(); |
| } catch (Exception e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| } |
| file.delete(); |
| } |
| } catch (Throwable throwable) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(throwable)); |
| } |
| } |
| } catch (Throwable e) { |
| WXLogUtils.e(WXLogUtils.getStackTrace(e)); |
| } |
| exception += "\n" + exceptionExt; |
| WXLogUtils.e("reportJSException:" + exception); |
| |
| } |
| } |
| |
| |
| WXExceptionUtils.commitCriticalExceptionRT(exceptionId, reportCode, |
| function, |
| reportCode.getErrorMsg() + exception, |
| null); |
| |
| } |
| } |
| |
| private void registerDomModule() throws WXException { |
| /** Tell Javascript Framework what methods you have. This is Required.**/ |
| Map<String, Object> domMap = new HashMap<>(); |
| domMap.put(WXDomModule.WXDOM, WXDomModule.METHODS); |
| registerModules(domMap); |
| } |
| |
| //This method is deprecated because of performance issue. |
| @Deprecated |
| public void notifyTrimMemory() { |
| |
| } |
| |
| /** |
| * update js server global config, current support turn wson off |
| * by pass wson_off |
| * */ |
| public static void updateGlobalConfig(String config) { |
| if(TextUtils.isEmpty(config)){ |
| config = "none"; |
| } |
| if(!TextUtils.equals(config, globalConfig)){ |
| globalConfig = config; |
| WXEnvironment.addCustomOptions(GLOBAL_CONFIG_KEY, globalConfig); |
| Runnable runnable = new Runnable() { |
| @Override |
| public void run() { |
| if(mBridgeManager != null){ |
| if(mBridgeManager.isJSFrameworkInit()){ |
| if(mBridgeManager.mWXBridge instanceof WXBridge) { |
| final WXBridge bridge = (WXBridge) mBridgeManager.mWXBridge; |
| bridge.nativeUpdateGlobalConfig(globalConfig); |
| } |
| } |
| } |
| if(globalConfig.contains(WXWsonJSONSwitch.WSON_OFF)){ |
| WXWsonJSONSwitch.USE_WSON = false; |
| }else{ |
| WXWsonJSONSwitch.USE_WSON = true; |
| } |
| } |
| }; |
| if(mBridgeManager != null && mBridgeManager.isJSFrameworkInit()){ |
| mBridgeManager.post(runnable); |
| }else{ |
| runnable.run(); |
| } |
| } |
| } |
| |
| public |
| @Nullable |
| Looper getJSLooper() { |
| Looper ret = null; |
| if (mJSThread != null) { |
| ret = mJSThread.getLooper(); |
| } |
| return ret; |
| } |
| |
| public void notifySerializeCodeCache() { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| if (!isJSFrameworkInit()) |
| return; |
| |
| invokeExecJS("", null, METHOD_NOTIFY_SERIALIZE_CODE_CACHE, new WXJSObject[0]); |
| } |
| }); |
| } |
| |
| public void takeJSHeapSnapshot(String filename) { |
| Message msg = mJSHandler.obtainMessage(); |
| msg.obj = filename; |
| msg.what = WXJSBridgeMsgType.TAKE_HEAP_SNAPSHOT; |
| msg.setTarget(mJSHandler); |
| msg.sendToTarget(); |
| } |
| |
| public static class TimerInfo { |
| |
| public String callbackId; |
| public long time; |
| public String instanceId; |
| } |
| |
| public int callCreateBody(String pageId, String componentType, String ref, |
| HashMap<String, String> styles, HashMap<String, String> attributes, HashSet<String> events, |
| float[] margins, float[] paddings, float[] borders) { |
| |
| if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(componentType) || TextUtils.isEmpty(ref)) { |
| WXLogUtils.d("[WXBridgeManager] call callCreateBody arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callCreateBody", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callCreateBody >>>> pageId:").append(pageId) |
| .append(", componentType:").append(componentType).append(", ref:").append(ref) |
| .append(", styles:").append(styles == null ? "{}" : styles.toString()) |
| .append(", attributes:").append(attributes) |
| .append(", events:").append(events); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionCreateBody(instance, ref, componentType, |
| styles, attributes, events, margins, paddings, borders); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callCreateBody exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callCreateBody", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callAddElement(String pageId, 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) { |
| if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(componentType) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callAddElement arguments is null"); |
| } |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddElement", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callAddElement >>>> pageId:").append(pageId) |
| .append(", componentType:").append(componentType).append(", ref:").append(ref).append(", index:").append(index) |
| .append(", parentRef:").append(parentRef) |
| .append(", styles:").append(styles == null ? "{}" : styles.toString()) |
| .append(", attributes:").append(attributes) |
| .append(", events:").append(events); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId); |
| if (instance != null) { |
| final GraphicActionAddElement action = new GraphicActionAddElement(instance, ref, componentType, parentRef, index, |
| styles, attributes, events, margins, paddings, borders); |
| if(willLayout) { |
| instance.addInActiveAddElementAction(ref, action); |
| }else{ |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(pageId, action); |
| } |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callAddElement exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddElement", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callRemoveElement(String instanceId, String ref) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callRemoveElement arguments is null"); |
| } |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveElement", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callRemoveElement >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionRemoveElement(instance, ref); |
| if(instance.getInActiveAddElementAction(ref)!=null){ |
| instance.removeInActiveAddElmentAction(ref); |
| } |
| else { |
| WXSDKManager.getInstance().getWXRenderManager() |
| .postGraphicAction(action.getPageId(), action); |
| } |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callRemoveElement exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveElement", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callMoveElement(String instanceId, String ref, String parentref, int index) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(parentref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callMoveElement arguments is null"); |
| } |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callMoveElement", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callMoveElement >>>> instanceId:").append(instanceId) |
| .append(", parentref:").append(parentref) |
| .append(", index:").append(index) |
| .append(", ref:").append(ref); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionMoveElement(instance, ref, parentref, index); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callMoveElement exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callMoveElement", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callAddEvent(String instanceId, String ref, String event) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(event)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callAddEvent arguments is null"); |
| } |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddEvent", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callAddEvent >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref) |
| .append(", event:").append(event); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| new GraphicActionAddEvent(instance, ref, event).executeActionOnRender(); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callAddEvent exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddEvent", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| // get next tick |
| getNextTick(instanceId); |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callRemoveEvent(String instanceId, String ref, String event) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref) || TextUtils.isEmpty(event)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callRemoveEvent arguments is null"); |
| } |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveEvent", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callRemoveEvent >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref) |
| .append(", event:").append(event); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| new GraphicActionRemoveEvent(instance, ref, event).executeActionOnRender(); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callRemoveEvent exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveEvent", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| // get next tick |
| getNextTick(instanceId); |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callUpdateStyle(String instanceId, String ref, HashMap<String, Object> styles, |
| HashMap<String, String> paddings, |
| HashMap<String, String> margins, |
| HashMap<String, String> borders) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callUpdateStyle arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateStyle", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callUpdateStyle >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref).append(", styles:").append(styles == null ? "{}" : styles.toString()) |
| .append(", paddings:").append(paddings.toString()) |
| .append(", margins:").append(margins.toString()) |
| .append(", borders:").append(borders.toString()); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionUpdateStyle(instance, ref, styles, paddings, margins, borders); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callUpdateStyle exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateStyle", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callUpdateAttrs(String instanceId, String ref, HashMap<String, String> attrs) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callUpdateAttrs arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateAttrs", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callUpdateAttrs >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref).append(", attrs:").append(attrs.toString()); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionUpdateAttr(instance, ref, attrs); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callUpdateAttrs exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateAttrs", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| private void setExceedGPULimitComponentsInfo(String instanceId,String ref,GraphicSize layoutSize){ |
| float limit = WXRenderManager.getOpenGLRenderLimitValue(); |
| if(limit > 0 && (layoutSize.getHeight() > limit || layoutSize.getWidth() > limit)){ |
| JSONObject ext = new JSONObject(); |
| WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(instanceId,ref); |
| ext.put("GPU limit",String.valueOf(limit)); |
| ext.put("component.width",String.valueOf(layoutSize.getWidth())); |
| ext.put("component.height",String.valueOf(layoutSize.getHeight())); |
| if (component.getComponentType() != null && !component.getComponentType().isEmpty()) { |
| ext.put("component.type", component.getComponentType()); |
| } |
| if (component.getStyles() != null && !component.getStyles().isEmpty()) { |
| ext.put("component.style", component.getStyles().toString()); |
| } |
| if (component.getAttrs() != null && !component.getAttrs().isEmpty()) { |
| ext.put("component.attr", component.getAttrs().toString()); |
| } |
| if (component.getEvents() != null && !component.getEvents().isEmpty()) { |
| ext.put("component.event", component.getEvents().toString()); |
| } |
| if (component.getMargin() != null) { |
| ext.put("component.margin", component.getMargin().toString()); |
| } |
| if (component.getPadding() != null) { |
| ext.put("component.padding", component.getPadding().toString()); |
| } |
| if (component.getBorder() != null) { |
| ext.put("component.border", component.getBorder().toString()); |
| } |
| WXSDKManager.getInstance().getSDKInstance(instanceId).setComponentsInfoExceedGPULimit(ext); |
| } |
| } |
| |
| public int callAddChildToRichtext(String instanceId, String nodeType, String ref, String parentRef, String richTextRef, |
| HashMap<String, String> styles, HashMap<String, String> attrs){ |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callAddChildToRichtext arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAddChildToRichtext", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callAddChildToRichtext >>>> instanceId:").append(instanceId) |
| .append(", nodeType:").append(nodeType).append(", ref:").append(ref).append(", parentRef:") |
| .append(parentRef).append(", richTextRef:").append(richTextRef).append(", styles:") |
| .append(styles.toString()).append(", attrs:").append(attrs.toString()); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionAddChildToRichtext(instance,nodeType,ref,parentRef,richTextRef,styles,attrs |
| ); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callAddChildToRichtext exception: ", WXLogUtils.getStackTrace(e)); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAddChildToRichtext", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callRemoveChildFromRichtext(String instanceId, String ref, String parentRef, String richTextRef){ |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callRemoveChildFromRichtext arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRemoveChildFromRichtext", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callRemoveChildFromRichtext >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref).append(", parentRef:").append(parentRef).append(", richTextRef:").append(richTextRef); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionRemoveChildFromRichtext(instance, ref, parentRef, richTextRef); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callRemoveChildFromRichtext exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRemoveChildFromRichtext", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callUpdateRichtextStyle(String instanceId, String ref, HashMap<String, String> styles, String parentRef, String richTextRef){ |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextStyle arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextStyle", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callUpdateRichtextStyle >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref).append(", styles:").append(styles.toString()).append(", parentRef:") |
| .append(parentRef).append(", richTextRef:").append(richTextRef); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionUpdateRichtextStyle(instance, ref, styles, parentRef, richTextRef); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callUpdateRichtextStyle exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextStyle", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| public int callUpdateRichtextChildAttr(String instanceId, String ref, HashMap<String, String> attrs, String parentRef, String richTextRef){ |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callUpdateRichtextChildAttr arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callUpdateRichtextChildAttr", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callUpdateRichtextChildAttr >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref).append(", attrs:").append(attrs.toString()).append(", parentRef:") |
| .append(parentRef).append(", richTextRef:").append(richTextRef); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| final BasicGraphicAction action = new GraphicActionUpdateRichtextAttr(instance, ref, attrs, parentRef, richTextRef); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callUpdateRichtextChildAttr exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callUpdateRichtextChildAttr", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callLayout(String pageId, String ref, int top, int bottom, int left, int right, int height, int width, boolean isRTL, int index) { |
| |
| if (TextUtils.isEmpty(pageId) || TextUtils.isEmpty(ref)) { |
| if (WXEnvironment.isApkDebugable()){ |
| WXLogUtils.d("[WXBridgeManager] call callLayout arguments is null"); |
| } |
| |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callLayout", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callLayout >>>> instanceId:").append(pageId) |
| .append(", ref:").append(ref).append(", height:").append(height).append(", width:").append(width) |
| .append(", top:").append(top) |
| .append(", bottom:").append(bottom) |
| .append(", left:").append(left) |
| .append(", right:").append(right); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(pageId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(pageId); |
| if (instance != null) { |
| GraphicSize size = new GraphicSize(width, height); |
| GraphicPosition position = new GraphicPosition(left, top, right, bottom); |
| setExceedGPULimitComponentsInfo(pageId,ref,size); |
| GraphicActionAddElement addAction = instance.getInActiveAddElementAction(ref); |
| if(addAction!=null) { |
| addAction.setRTL(isRTL); |
| addAction.setSize(size); |
| addAction.setPosition(position); |
| if(!TextUtils.equals(ref, WXComponent.ROOT)) { |
| addAction.setIndex(index); |
| } |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(pageId, addAction); |
| instance.removeInActiveAddElmentAction(ref); |
| } |
| else { |
| final BasicGraphicAction action = new GraphicActionLayout(instance, ref, position, size, isRTL); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(action.getPageId(), action); |
| } |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callLayout exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(pageId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callLayout", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callAppendTreeCreateFinish(String instanceId, String ref) { |
| |
| if (TextUtils.isEmpty(instanceId) || TextUtils.isEmpty(ref)) { |
| WXLogUtils.d("[WXBridgeManager] call callAppendTreeCreateFinish arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callAppendTreeCreateFinish", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callAppendTreeCreateFinish >>>> instanceId:").append(instanceId) |
| .append(", ref:").append(ref); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| GraphicActionAppendTreeCreateFinish action = new GraphicActionAppendTreeCreateFinish(instance, ref); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action); |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callAppendTreeCreateFinish exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callAppendTreeCreateFinish", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callCreateFinish(String instanceId) { |
| |
| if (TextUtils.isEmpty(instanceId)) { |
| WXLogUtils.d("[WXBridgeManager] call callCreateFinish arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callCreateFinish", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callCreateFinish >>>> instanceId:").append(instanceId); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| long start = System.currentTimeMillis(); |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| instance.getApmForInstance().onStage("callCreateFinish"); |
| instance.firstScreenCreateInstanceTime(start); |
| GraphicActionCreateFinish action = new GraphicActionCreateFinish(instance); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callCreateFinish exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callCreateFinish", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public int callRenderSuccess(String instanceId) { |
| |
| if (TextUtils.isEmpty(instanceId)) { |
| WXLogUtils.d("[WXBridgeManager] call callRenderSuccess arguments is null"); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_RENDER_ERR_BRIDGE_ARG_NULL, "callRenderSuccess", |
| "arguments is empty, INSTANCE_RENDERING_ERROR will be set", null); |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| if (WXEnvironment.isApkDebugable() && BRIDGE_LOG_SWITCH) { |
| mLodBuilder.append("[WXBridgeManager] callRenderSuccess >>>> instanceId:").append(instanceId); |
| WXLogUtils.d(mLodBuilder.substring(0)); |
| mLodBuilder.setLength(0); |
| } |
| |
| if (mDestroyedInstanceId != null && mDestroyedInstanceId.contains(instanceId)) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| try { |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| instance.getApmForInstance().onStage("callRenderSuccess"); |
| GraphicActionRenderSuccess action = new GraphicActionRenderSuccess(instance); |
| WXSDKManager.getInstance().getWXRenderManager().postGraphicAction(instanceId, action); |
| } |
| } catch (Exception e) { |
| WXLogUtils.e("[WXBridgeManager] callRenderSuccess exception: ", e); |
| WXExceptionUtils.commitCriticalExceptionRT(instanceId, |
| WXErrorCode.WX_KEY_EXCEPTION_INVOKE_BRIDGE, "callRenderSuccess", |
| WXLogUtils.getStackTrace(e), null); |
| } |
| |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| |
| public ContentBoxMeasurement getMeasurementFunc(String instanceId, long renderObjectPtr) { |
| ContentBoxMeasurement contentBoxMeasurement = null; |
| WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId); |
| if (instance != null) { |
| contentBoxMeasurement = instance.getContentBoxMeasurement(renderObjectPtr); |
| } |
| return contentBoxMeasurement; |
| } |
| |
| public void bindMeasurementToRenderObject(long ptr){ |
| if (isJSFrameworkInit()) { |
| mWXBridge.bindMeasurementToRenderObject(ptr); |
| } |
| } |
| |
| |
| /** |
| * Native: Layout |
| * @param instanceId |
| * @return |
| */ |
| @UiThread |
| public boolean notifyLayout(String instanceId) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| return mWXBridge.notifyLayout(instanceId); |
| } |
| return false; |
| } |
| |
| @UiThread |
| public void forceLayout(String instanceId) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.forceLayout(instanceId); |
| } |
| } |
| |
| /** |
| * native: OnInstanceClose |
| * should be called on JSThread |
| * @param instanceId |
| */ |
| public void onInstanceClose(String instanceId) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.onInstanceClose(instanceId); |
| } |
| } |
| |
| /** |
| * native: SetDefaultHeightAndWidthIntoRootDom |
| * @param instanceId |
| * @param defaultWidth |
| * @param defaultHeight |
| */ |
| public void setDefaultRootSize(final String instanceId, final float defaultWidth, final float defaultHeight, final boolean isWidthWrapContent, final boolean isHeightWrapContent) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setDefaultHeightAndWidthIntoRootDom(instanceId, defaultWidth, defaultHeight, isWidthWrapContent, isHeightWrapContent); |
| } |
| } |
| |
| public void setRenderContentWrapContentToCore(boolean wrap, final String instanceId) { |
| if (isJSFrameworkInit()) { |
| mWXBridge.setRenderContainerWrapContent(wrap, instanceId); |
| } |
| } |
| |
| public void setStyleWidth(String instanceId, String ref, float value) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setStyleWidth(instanceId, ref, value); |
| } |
| } |
| |
| public void setStyleHeight(String instanceId, String ref, float value) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setStyleHeight(instanceId, ref, value); |
| } |
| } |
| |
| public long[] getFirstScreenRenderTime(String instanceId) { |
| if (isJSFrameworkInit()) { |
| return mWXBridge.getFirstScreenRenderTime(instanceId); |
| } |
| return new long[]{0, 0, 0}; |
| } |
| |
| public long[] getRenderFinishTime(String instanceId) { |
| if (isJSFrameworkInit()) { |
| return mWXBridge.getRenderFinishTime(instanceId); |
| } |
| return new long[]{0, 0, 0}; |
| } |
| |
| public void setDeviceDisplay(final String instanceId, final float deviceWidth, final float deviceHeight, final float scale) { |
| post(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.setDeviceDisplay(instanceId, deviceWidth, deviceHeight, scale); |
| } |
| }); |
| } |
| |
| public void updateInitDeviceParams(final String width, final String height, final String density, final String statusHeight){ |
| if(!isJSFrameworkInit()){ |
| return; |
| } |
| post(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.updateInitFrameworkParams(WXConfig.deviceWidth, width, WXConfig.deviceWidth); |
| } |
| }); |
| post(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.updateInitFrameworkParams(WXConfig.deviceHeight, height, WXConfig.deviceHeight); |
| } |
| }); |
| |
| post(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.updateInitFrameworkParams(WXConfig.scale, density, WXConfig.scale); |
| } |
| }); |
| |
| if(statusHeight != null){ |
| post(new Runnable() { |
| @Override |
| public void run() { |
| mWXBridge.updateInitFrameworkParams(WXConfig.androidStatusBarHeight, statusHeight, WXConfig.androidStatusBarHeight); |
| } |
| }); |
| } |
| } |
| |
| public void setMargin(String instanceId, String ref, CSSShorthand.EDGE edge, float value) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setMargin(instanceId, ref, edge, value); |
| } |
| } |
| |
| public void setPadding(String instanceId, String ref, CSSShorthand.EDGE edge, float value) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setPadding(instanceId, ref, edge, value); |
| } |
| } |
| |
| public void setPosition(String instanceId, String ref, CSSShorthand.EDGE edge, float value) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setPosition(instanceId, ref, edge, value); |
| } |
| } |
| |
| public void markDirty(String instanceId, String ref, boolean dirty) { |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.markDirty(instanceId, ref, dirty); |
| } |
| } |
| public void setViewPortWidth(String instanceId,float viewPortWidth){ |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setViewPortWidth(instanceId,viewPortWidth); |
| } |
| } |
| public void setPageArgument(String instanceId,String key,String value){ |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setPageArgument(instanceId,key,value); |
| } |
| } |
| public void reloadPageLayout(String instanceId){ |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.reloadPageLayout(instanceId); |
| } |
| } |
| |
| public void setDeviceDisplayOfPage(String instanceId,float width,float height){ |
| if (isSkipFrameworkInit(instanceId) || isJSFrameworkInit()) { |
| mWXBridge.setDeviceDisplayOfPage(instanceId,width,height); |
| } |
| } |
| |
| public int callHasTransitionPros(String instanceId, String ref, HashMap<String, String> styles) { |
| WXComponent component = WXSDKManager.getInstance().getWXRenderManager().getWXComponent(instanceId, ref); |
| if (null == component || null == component.getTransition() || null == component.getTransition().getProperties()) { |
| return IWXBridge.DESTROY_INSTANCE; |
| } |
| |
| for(String property : component.getTransition().getProperties()){ |
| if(styles.containsKey(property)){ |
| return IWXBridge.INSTANCE_RENDERING; |
| } |
| } |
| return IWXBridge.INSTANCE_RENDERING_ERROR; |
| } |
| |
| public void registerCoreEnv(String key, String value) { |
| if (isJSFrameworkInit()) |
| mWXBridge.registerCoreEnv(key, value); |
| else |
| mWeexCoreEnvOptions.put(key, value); |
| } |
| |
| private void onJsFrameWorkInitSuccees() { |
| for (Map.Entry<String, String> entry : mWeexCoreEnvOptions.entrySet()) { |
| mWXBridge.registerCoreEnv(entry.getKey(), entry.getValue()); |
| } |
| mWeexCoreEnvOptions.clear(); |
| } |
| |
| public String getWeexCoreThreadStackTrace(){ |
| if (null == mJSThread){ |
| return "null == mJSThread"; |
| } |
| StringBuilder stringBuilder = new StringBuilder(); |
| |
| try { |
| stringBuilder.append(String.format("Thread Name: '%s'\n", mJSThread.getName())); |
| stringBuilder.append(String.format(Locale.ENGLISH,"\"%s\" prio=%d tid=%d %s\n", mJSThread.getName(), mJSThread.getPriority(), mJSThread.getId(), mJSThread.getState())); |
| |
| for (StackTraceElement e: mJSThread.getStackTrace()){ |
| stringBuilder.append(String.format("\tat %s\n", e.toString())); |
| } |
| } catch (Exception var8) { |
| Log.e("weex", "getJSThreadStackTrace error:", var8); |
| } |
| return stringBuilder.toString(); |
| } |
| |
| } |