TickAdsLite v3.1版本的 MD5 值为:7ff5236e2d7beb37efeddcb8fe8d4660

以下内容为反编译后的 WebViewApp.java 源代码,内容仅作参考


package com.unity3d.services.core.webview;

import android.os.Build;
import android.os.ConditionVariable;
import android.os.Looper;
import android.webkit.RenderProcessGoneDetail;
import android.webkit.WebChromeClient;
import android.webkit.WebResourceError;
import android.webkit.WebResourceRequest;
import android.webkit.WebViewClient;
import com.unity3d.services.ads.api.AdUnit;
import com.unity3d.services.core.configuration.Configuration;
import com.unity3d.services.core.configuration.ErrorState;
import com.unity3d.services.core.configuration.InitializeThread;
import com.unity3d.services.core.log.DeviceLog;
import com.unity3d.services.core.misc.Utilities;
import com.unity3d.services.core.misc.ViewUtilities;
import com.unity3d.services.core.properties.ClientProperties;
import com.unity3d.services.core.properties.SdkProperties;
import com.unity3d.services.core.request.metrics.SDKMetrics;
import com.unity3d.services.core.webview.bridge.CallbackStatus;
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
import com.unity3d.services.core.webview.bridge.Invocation;
import com.unity3d.services.core.webview.bridge.NativeCallback;
import com.unity3d.services.core.webview.bridge.WebViewBridge;
import java.io.File;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.http.protocol.HTTP;
import org.json.JSONArray;
public class WebViewApp implements IWebViewBridgeInvoker {
    private static final int INVOKE_JS_CHARS_LENGTH = 22;
    private static ConditionVariable _conditionVariable;
    private static WebViewApp _currentApp;
    private Configuration _configuration;
    private WebView _webView;
    private static final AtomicReference<Boolean> _initialized = new AtomicReference<>(false);
    private static final AtomicReference<String> _webAppFailureMessage = new AtomicReference<>();
    private static final AtomicReference<Integer> _webAppFailureCode = new AtomicReference<>();
    private boolean _webAppLoaded = false;
    private final HashMap<String, NativeCallback> _nativeCallbacks = new HashMap<>();

    public WebViewApp(Configuration configuration, boolean useWebViewWithCache, boolean shouldNotRequireGesturePlayback) {
        setConfiguration(configuration);
        WebViewBridge.setClassTable(getConfiguration().getWebAppApiClassList());
        this._webView = useWebViewWithCache ? new WebViewWithCache(ClientProperties.getApplicationContext(), shouldNotRequireGesturePlayback) : new WebView(ClientProperties.getApplicationContext(), shouldNotRequireGesturePlayback);
        this._webView.setWebViewClient(new WebAppClient());
    }

    public WebViewApp() {
    }

    public void setWebAppLoaded(boolean loaded) {
        this._webAppLoaded = loaded;
    }

    public boolean isWebAppLoaded() {
        return this._webAppLoaded;
    }

    public void setWebAppFailureMessage(String message) {
        _webAppFailureMessage.set(message);
    }

    public void setWebAppFailureCode(int code) {
        _webAppFailureCode.set(Integer.valueOf(code));
    }

    public String getWebAppFailureMessage() {
        return _webAppFailureMessage.get();
    }

    public int getWebAppFailureCode() {
        return _webAppFailureCode.get().intValue();
    }

    public void setWebAppInitialized(boolean initialized) {
        _initialized.set(Boolean.valueOf(initialized));
        _conditionVariable.open();
    }

    public void resetWebViewAppInitialization() {
        this._webAppLoaded = false;
        _webAppFailureCode.set(-1);
        _webAppFailureMessage.set("");
        _initialized.set(false);
    }

    public boolean isWebAppInitialized() {
        return _initialized.get().booleanValue();
    }

    public WebView getWebView() {
        return this._webView;
    }

    public void setWebView(WebView webView) {
        this._webView = webView;
    }

    public Configuration getConfiguration() {
        return this._configuration;
    }

    public void setConfiguration(Configuration configuration) {
        this._configuration = configuration;
    }

    private void invokeJavascriptMethod(String className, String methodName, JSONArray params) {
        String javaScript = buildInvokeJavascript(className, methodName, params);
        DeviceLog.debug("Invoking javascript: %s", javaScript);
        getWebView().invokeJavascript(javaScript);
    }

    private String buildInvokeJavascript(String className, String methodName, JSONArray params) {
        String paramsString = params.toString();
        int stringLength = className.length() + 22 + methodName.length() + paramsString.length();
        StringBuilder sb = new StringBuilder(stringLength);
        sb.append("javascript:window.");
        sb.append(className);
        sb.append(".");
        sb.append(methodName);
        sb.append("(");
        sb.append(paramsString);
        sb.append(");");
        return sb.toString();
    }

    public boolean sendEvent(Enum eventCategory, Enum eventId, Object... params) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("sendEvent ignored because web app is not loaded");
            return false;
        }
        JSONArray paramList = new JSONArray();
        paramList.put(eventCategory.name());
        paramList.put(eventId.name());
        for (Object o : params) {
            paramList.put(o);
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleEvent", paramList);
            return true;
        } catch (Exception e) {
            DeviceLog.exception("Error while sending event to WebView", e);
            return false;
        }
    }

    @Override
    public boolean invokeMethod(String className, String methodName, Method callback, Object... params) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("invokeMethod ignored because web app is not loaded");
            return false;
        }
        JSONArray paramList = new JSONArray();
        paramList.put(className);
        paramList.put(methodName);
        if (callback != null) {
            NativeCallback nativeCallback = new NativeCallback(callback);
            addCallback(nativeCallback);
            paramList.put(nativeCallback.getId());
        } else {
            paramList.put((Object) null);
        }
        if (params != null) {
            for (Object o : params) {
                paramList.put(o);
            }
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleInvocation", paramList);
            return true;
        } catch (Exception e) {
            DeviceLog.exception("Error invoking javascript method", e);
            return false;
        }
    }

    public boolean invokeCallback(Invocation invocation) {
        if (!isWebAppLoaded()) {
            DeviceLog.debug("invokeBatchCallback ignored because web app is not loaded");
            return false;
        }
        JSONArray responseList = new JSONArray();
        ArrayList<ArrayList<Object>> responses = invocation.getResponses();
        if (responses != null && !responses.isEmpty()) {
            Iterator<ArrayList<Object>> it = responses.iterator();
            while (it.hasNext()) {
                ArrayList<Object> response = it.next();
                CallbackStatus status = (CallbackStatus) response.get(0);
                Enum error = (Enum) response.get(1);
                Object[] params = (Object[]) response.get(2);
                Object callbackId = (String) params[0];
                Object[] params2 = Arrays.copyOfRange(params, 1, params.length);
                ArrayList<Object> tmp = new ArrayList<>();
                tmp.add(callbackId);
                tmp.add(status.toString());
                JSONArray paramArray = new JSONArray();
                if (error != null) {
                    paramArray.put(error.name());
                }
                for (Object o : params2) {
                    paramArray.put(o);
                }
                tmp.add(paramArray);
                JSONArray paramList = new JSONArray();
                Iterator<Object> it2 = tmp.iterator();
                while (it2.hasNext()) {
                    Object o2 = it2.next();
                    paramList.put(o2);
                }
                responseList.put(paramList);
            }
        }
        try {
            invokeJavascriptMethod("nativebridge", "handleCallback", responseList);
        } catch (Exception e) {
            DeviceLog.exception("Error while invoking batch response for WebView", e);
        }
        return true;
    }

    public void addCallback(NativeCallback callback) {
        synchronized (this._nativeCallbacks) {
            this._nativeCallbacks.put(callback.getId(), callback);
        }
    }

    public void removeCallback(NativeCallback callback) {
        synchronized (this._nativeCallbacks) {
            this._nativeCallbacks.remove(callback.getId());
        }
    }

    public NativeCallback getCallback(String callbackId) {
        NativeCallback nativeCallback;
        synchronized (this._nativeCallbacks) {
            nativeCallback = this._nativeCallbacks.get(callbackId);
        }
        return nativeCallback;
    }

    public static WebViewApp getCurrentApp() {
        return _currentApp;
    }

    public static void setCurrentApp(WebViewApp app) {
        _currentApp = app;
    }

    public static ErrorState create(Configuration configuration) throws IllegalThreadStateException {
        return create(configuration, false);
    }

    public static ErrorState create(final Configuration configuration, boolean useRemoteUrl) throws IllegalThreadStateException {
        boolean createdSuccessfully = true;
        DeviceLog.entered();
        if (useRemoteUrl) {
            return createWithRemoteUrl(configuration);
        }
        if (Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
            throw new IllegalThreadStateException("Cannot call create() from main thread!");
        }
        Utilities.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    WebViewApp webViewApp = new WebViewApp(Configuration.this, Configuration.this.getExperiments().isWebAssetAdCaching(), Configuration.this.getExperiments().isWebGestureNotRequired());
                    WebViewUrlBuilder webViewUrlBuilder = new WebViewUrlBuilder("file://" + SdkProperties.getLocalWebViewFile(), Configuration.this);
                    String baseUrl = webViewUrlBuilder.getUrlWithQueryString();
                    webViewApp.getWebView().loadDataWithBaseURL(baseUrl, Configuration.this.getWebViewData(), "text/html", HTTP.UTF_8, null);
                    WebViewApp.setCurrentApp(webViewApp);
                } catch (Exception e) {
                    DeviceLog.error("Unity Ads SDK unable to create WebViewApp");
                    WebViewApp._conditionVariable.open();
                }
            }
        });
        _conditionVariable = new ConditionVariable();
        boolean webViewCreateDidNotTimeout = _conditionVariable.block(configuration.getWebViewAppCreateTimeout());
        boolean webAppDefined = getCurrentApp() != null;
        boolean webAppInitialized = webAppDefined && getCurrentApp().isWebAppInitialized();
        if (!webViewCreateDidNotTimeout || !webAppDefined || !webAppInitialized) {
            createdSuccessfully = false;
        }
        if (!createdSuccessfully) {
            if (!webViewCreateDidNotTimeout) {
                return ErrorState.CreateWebviewTimeout;
            }
            if (getCurrentApp() == null) {
                return ErrorState.CreateWebview;
            }
            return getCurrentApp().getErrorStateFromWebAppCode();
        }
        return null;
    }

    private static ErrorState createWithRemoteUrl(final Configuration configuration) {
        boolean createdSuccessfully = true;
        if (Thread.currentThread().equals(Looper.getMainLooper().getThread())) {
            throw new IllegalThreadStateException("Cannot call create() from main thread!");
        }
        Utilities.runOnUiThread(new Runnable() {
            @Override
            public void run() {
                try {
                    WebViewApp webViewApp = new WebViewApp(Configuration.this, true, Configuration.this.getExperiments().isWebGestureNotRequired());
                    WebViewUrlBuilder webViewUrlBuilder = new WebViewUrlBuilder(Configuration.this.getWebViewUrl(), Configuration.this);
                    String baseUrl = webViewUrlBuilder.getUrlWithQueryString();
                    webViewApp.getWebView().loadUrl(baseUrl);
                    WebViewApp.setCurrentApp(webViewApp);
                } catch (Exception e) {
                    DeviceLog.error("Unity Ads SDK unable to create WebViewApp");
                    WebViewApp._conditionVariable.open();
                }
            }
        });
        _conditionVariable = new ConditionVariable();
        boolean webViewCreateDidNotTimeout = _conditionVariable.block(configuration.getWebViewAppCreateTimeout());
        boolean webAppDefined = getCurrentApp() != null;
        boolean webAppInitialized = webAppDefined && getCurrentApp().isWebAppInitialized();
        if (!webViewCreateDidNotTimeout || !webAppDefined || !webAppInitialized) {
            createdSuccessfully = false;
        }
        if (!createdSuccessfully) {
            if (!webViewCreateDidNotTimeout) {
                return ErrorState.CreateWebviewTimeout;
            }
            if (getCurrentApp() == null) {
                return ErrorState.CreateWebview;
            }
            return getCurrentApp().getErrorStateFromWebAppCode();
        }
        return null;
    }

    public ErrorState getErrorStateFromWebAppCode() {
        int failureCode = getWebAppFailureCode();
        if (failureCode == 1) {
            return ErrorState.CreateWebviewGameIdDisabled;
        }
        if (failureCode == 2) {
            return ErrorState.CreateWebviewConfigError;
        }
        if (failureCode == 3) {
            return ErrorState.CreateWebviewInvalidArgument;
        }
        return ErrorState.CreateWebview;
    }

    private static class WebAppClient extends WebViewClient {
        private WebAppClient() {
        }

        @Override
        public boolean onRenderProcessGone(android.webkit.WebView view, final RenderProcessGoneDetail detail) {
            Utilities.runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    if (AdUnit.getAdUnitActivity() != null) {
                        AdUnit.getAdUnitActivity().finish();
                    }
                    if (WebViewApp.getCurrentApp() != null && WebViewApp.getCurrentApp().getWebView() != null) {
                        ViewUtilities.removeViewFromParent(WebViewApp.getCurrentApp().getWebView());
                    }
                    InitializeThread.reset();
                }
            });
            DeviceLog.error("UnityAds SDK WebView render process gone with following reason : " + detail.toString());
            SDKMetrics.getInstance().sendEvent("native_webview_render_process_gone", new HashMap<String, String>() {
                {
                    if (Build.VERSION.SDK_INT >= 26) {
                        put("dc", "" + detail.didCrash());
                        put("pae", "" + detail.rendererPriorityAtExit());
                    }
                }
            });
            return true;
        }

        @Override
        public void onPageFinished(android.webkit.WebView webview, String url) {
            super.onPageFinished(webview, url);
            DeviceLog.debug("Unity Ads SDK finished loading URL inside WebView: " + url);
        }

        @Override
        public boolean shouldOverrideUrlLoading(android.webkit.WebView view, String url) {
            DeviceLog.debug("Unity Ads SDK attempts to load URL inside WebView: " + url);
            return false;
        }

        @Override
        public void onReceivedError(android.webkit.WebView view, WebResourceRequest request, WebResourceError error) {
            super.onReceivedError(view, request, error);
            if (Build.VERSION.SDK_INT >= 23 && request != null && error != null) {
                DeviceLog.error("Unity Ads SDK encountered an error (code: " + error.getErrorCode() + ")  in WebView while loading a resource " + request.getUrl());
            } else if (Build.VERSION.SDK_INT >= 21 && request != null) {
                DeviceLog.error("Unity Ads SDK encountered an error in WebView while loading a resource " + request.getUrl());
            } else {
                DeviceLog.error("Unity Ads SDK encountered an error in WebView while loading a resource");
            }
        }
    }

    private class WebAppChromeClient extends WebChromeClient {
        private WebAppChromeClient() {
        }

        @Override
        public void onConsoleMessage(String message, int lineNumber, String sourceID) {
            String sourceFile = sourceID;
            File tmp = null;
            try {
                File tmp2 = new File(sourceID);
                tmp = tmp2;
            } catch (Exception e) {
                DeviceLog.exception("Could not handle sourceId", e);
            }
            if (tmp != null) {
                sourceFile = tmp.getName();
            }
            if (Build.VERSION.SDK_INT < 19) {
                DeviceLog.debug("JavaScript (sourceId=" + sourceFile + ", line=" + lineNumber + "): " + message);
            }
        }
    }
}