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);
}
}
}
}