Release 4.9.0
This commit is contained in:
Родитель
4f6c0f610f
Коммит
9030d0ca27
|
@ -7,8 +7,8 @@ android {
|
|||
applicationId "com.unity3d.ads.example"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 33
|
||||
versionCode = 4800
|
||||
versionName = "4.8.0"
|
||||
versionCode = 4900
|
||||
versionName = "4.9.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
|
@ -18,11 +18,7 @@ import android.widget.EditText;
|
|||
import android.widget.RelativeLayout;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsInitializationListener;
|
||||
import com.unity3d.ads.IUnityAdsLoadListener;
|
||||
import com.unity3d.ads.IUnityAdsShowListener;
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.ads.UnityAdsShowOptions;
|
||||
import com.unity3d.ads.*;
|
||||
import com.unity3d.ads.example.R;
|
||||
import com.unity3d.ads.metadata.MediationMetaData;
|
||||
import com.unity3d.ads.metadata.MetaData;
|
||||
|
@ -68,6 +64,7 @@ public class UnityAdsFragment extends Fragment {
|
|||
@Override
|
||||
public void onBannerFailedToLoad(BannerView bannerAdView, BannerErrorInfo errorInfo) {
|
||||
Log.e(LOGTAG, "Unity Ads failed to load banner for " + bannerAdView.getPlacementId() + " with error: [" + errorInfo.errorCode + "] " + errorInfo.errorMessage);
|
||||
enableButton(showBannerButton);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -203,6 +200,7 @@ public class UnityAdsFragment extends Fragment {
|
|||
this.showBannerButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
disableButton(showBannerButton);
|
||||
bottomBanner = new BannerView((Activity)v.getContext(), "bannerads", new UnityBannerSize(320, 50));
|
||||
bottomBanner.setListener(bannerListener);
|
||||
bottomBanner.load();
|
||||
|
@ -213,11 +211,12 @@ public class UnityAdsFragment extends Fragment {
|
|||
hideBannerButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
bottomBanner.removeAllViews();
|
||||
if (bottomBanner != null) {
|
||||
bottomBanner.removeAllViews();
|
||||
bottomBanner = null;
|
||||
}
|
||||
showBannerButton.setEnabled(true);
|
||||
enableButton(showBannerButton);
|
||||
disableButton(hideBannerButton);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -30,8 +30,6 @@ project.tasks.whenTaskAdded { Task theTask ->
|
|||
}
|
||||
if (tasksDependentOnScar("${buildType}").any { theTask.name == it }) {
|
||||
theTask.dependsOn(":unity-scaradapter-common:copyJars${buildType}")
|
||||
theTask.dependsOn(":unity-scaradapter-1920:copyJars${buildType}")
|
||||
theTask.dependsOn(":unity-scaradapter-1950:copyJars${buildType}")
|
||||
theTask.dependsOn(":unity-scaradapter-2000:copyJars${buildType}")
|
||||
theTask.dependsOn(":unity-scaradapter-2100:copyJars${buildType}")
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
include ':unity-scaradapter-1920'
|
||||
include ':unity-scaradapter-1950'
|
||||
include ':unity-scaradapter-2000'
|
||||
include ':unity-scaradapter-2100'
|
||||
include ':unity-scaradapter-common'
|
||||
|
|
|
@ -13,14 +13,15 @@ if (project.rootProject.file('local.properties').exists()) {
|
|||
ext {
|
||||
GROUP_ID = "com.unity3d.ads"
|
||||
ARTIFACT_ID = "unity-ads"
|
||||
VERSION_ID = "4.8.0"
|
||||
VERSION_CODE = 4800
|
||||
VERSION_ID = "4.9.0"
|
||||
VERSION_CODE = 4900
|
||||
SIGN_AAR = properties.getProperty("SIGN_AAR") ?: false
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = GROUP_ID
|
||||
compileSdk 33
|
||||
compileSdkExtension 5
|
||||
DdmPreferences.setLogLevel("verbose")
|
||||
DdmPreferences.setTimeOut(10 * 60000)
|
||||
|
||||
|
@ -82,8 +83,6 @@ dependencies {
|
|||
implementation "com.google.android.gms:play-services-cronet:$play_services_cronet"
|
||||
androidTestCompileOnly project(':unity-scaradapter-2100')
|
||||
androidTestCompileOnly project(':unity-scaradapter-2000')
|
||||
androidTestCompileOnly project(':unity-scaradapter-1950')
|
||||
androidTestCompileOnly project(':unity-scaradapter-1920')
|
||||
androidTestCompileOnly project(':unity-scaradapter-common')
|
||||
androidTestImplementation 'junit:junit:4.13.2'
|
||||
androidTestImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
|
@ -98,8 +97,6 @@ dependencies {
|
|||
compileOnly 'com.google.ar:core:1.0.0'
|
||||
compileOnly project(':unity-scaradapter-2100')
|
||||
compileOnly project(':unity-scaradapter-2000')
|
||||
compileOnly project(':unity-scaradapter-1950')
|
||||
compileOnly project(':unity-scaradapter-1920')
|
||||
compileOnly project(':unity-scaradapter-common')
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib"
|
||||
|
|
|
@ -10,10 +10,13 @@ import static org.mockito.internal.verification.VerificationModeFactory.times;
|
|||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import android.widget.RelativeLayout;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.IScarBannerAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.common.scarads.UnityAdFormat;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
import com.unity3d.services.ads.gmascar.GMAScarAdapterBridge;
|
||||
import com.unity3d.services.ads.gmascar.adapters.ScarAdapterFactory;
|
||||
|
@ -64,19 +67,19 @@ public class GMAScarAdapterBridgeTest {
|
|||
private static final ScarAdapterVersion VERSION = ScarAdapterVersion.V21;
|
||||
private GMAScarAdapterBridge gmaScarAdapterBridge;
|
||||
private IScarAdapter scarAdapter;
|
||||
private boolean isBannerSignalEnabled = true;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
scarAdapter = new IScarAdapter() {
|
||||
@Override
|
||||
public void getSCARSignals(Context context, String[] strings,
|
||||
String[] strings1,
|
||||
ISignalCollectionListener iSignalCollectionListener) {
|
||||
public void getSCARSignal(Context context, String placementId, UnityAdFormat adFormat, ISignalCollectionListener signalCompletionListener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSCARBiddingSignals(Context context,
|
||||
boolean isBannerEnabled,
|
||||
ISignalCollectionListener iSignalCollectionListener) {
|
||||
iSignalCollectionListener.onSignalsCollected(SIGNAL);
|
||||
}
|
||||
|
@ -95,6 +98,11 @@ public class GMAScarAdapterBridgeTest {
|
|||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBannerAd(Context context, RelativeLayout bannerView, ScarAdMetadata scarAdMetadata, int width, int height, IScarBannerAdListenerWrapper adListener) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity, String s, String s1) {
|
||||
|
||||
|
@ -189,7 +197,7 @@ public class GMAScarAdapterBridgeTest {
|
|||
gmaEventSenderMock
|
||||
);
|
||||
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(handler);
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(isBannerSignalEnabled, handler);
|
||||
verify(handler, times(0)).onSignalsCollectionFailed(anyString());
|
||||
verify(handler, times(1)).onSignalsCollected(SIGNAL);
|
||||
}
|
||||
|
@ -208,7 +216,7 @@ public class GMAScarAdapterBridgeTest {
|
|||
gmaEventSenderMock
|
||||
);
|
||||
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(handler);
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(isBannerSignalEnabled, handler);
|
||||
verify(handler, times(0)).onSignalsCollected(anyString());
|
||||
verify(handler, times(1)).onSignalsCollectionFailed("SCAR bidding unsupported.");
|
||||
}
|
||||
|
@ -228,7 +236,7 @@ public class GMAScarAdapterBridgeTest {
|
|||
gmaEventSenderMock
|
||||
);
|
||||
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(handler);
|
||||
gmaScarAdapterBridge.getSCARBiddingSignals(isBannerSignalEnabled, handler);
|
||||
verify(handler, times(0)).onSignalsCollected(SIGNAL);
|
||||
verify(handler, times(1)).onSignalsCollectionFailed("Could not create SCAR adapter object.");
|
||||
}
|
||||
|
|
|
@ -19,18 +19,6 @@ public class ScarAdapterFactoryTest {
|
|||
|
||||
private final ScarAdapterFactory _scarAdapterFactory = new ScarAdapterFactory();
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory1920() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterVersion.V192, adsErrorHandlerMock);
|
||||
Assert.assertTrue(adapter instanceof com.unity3d.scar.adapter.v1920.ScarAdapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory1950() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterVersion.V195, adsErrorHandlerMock);
|
||||
Assert.assertTrue(adapter instanceof com.unity3d.scar.adapter.v1950.ScarAdapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory2000() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterVersion.V20, adsErrorHandlerMock);
|
||||
|
|
|
@ -34,27 +34,6 @@ public class MobileAdsBridgeLegacyTest {
|
|||
Assert.assertTrue(String.format("Minor version 223712000 is not found in %s", versionString), versionString.contains("223712000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAdapterVersionWhen192() {
|
||||
MobileAdsBridgeLegacy mobileAdsBridge = new MobileAdsBridgeLegacy();
|
||||
ScarAdapterVersion adapterVersion = mobileAdsBridge.getAdapterVersion(MobileAdsBridgeLegacy.CODE_19_2);
|
||||
Assert.assertEquals(ScarAdapterVersion.V192, adapterVersion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAdapterVersionWhen195() {
|
||||
MobileAdsBridgeLegacy mobileAdsBridge = new MobileAdsBridgeLegacy();
|
||||
ScarAdapterVersion adapterVersion = mobileAdsBridge.getAdapterVersion(MobileAdsBridgeLegacy.CODE_19_5);
|
||||
Assert.assertEquals(ScarAdapterVersion.V195, adapterVersion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAdapterVersionWhen198() {
|
||||
MobileAdsBridgeLegacy mobileAdsBridge = new MobileAdsBridgeLegacy();
|
||||
ScarAdapterVersion adapterVersion = mobileAdsBridge.getAdapterVersion(MobileAdsBridgeLegacy.CODE_19_8);
|
||||
Assert.assertEquals(ScarAdapterVersion.V195, adapterVersion);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAdapterVersionWhen20() {
|
||||
MobileAdsBridgeLegacy mobileAdsBridge = new MobileAdsBridgeLegacy();
|
||||
|
|
|
@ -38,10 +38,10 @@ public class ScarVersionFinderTest {
|
|||
public void testScarVersionFinderWithMobileAdsBridgeLegacy() {
|
||||
doCallRealMethod().when(mobileAdsBridgeMock).getVersionCodeIndex();
|
||||
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn("afma-sdk-a-v204890999.203404000.1");
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn("afma-sdk-a-v204890999.210402000.1");
|
||||
ScarVersionFinder scarVersionFinder = new ScarVersionFinder(mobileAdsBridgeMock, presenceDetector, gmaInitializer, new GMAEventSender());
|
||||
long versionCode = scarVersionFinder.getVersionCode();
|
||||
Assert.assertEquals(MobileAdsBridgeLegacy.CODE_19_5, versionCode);
|
||||
Assert.assertEquals(MobileAdsBridgeLegacy.CODE_20_0, versionCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -22,12 +22,13 @@ public class BiddingSignalsHandlerTest {
|
|||
|
||||
@Test
|
||||
public void testSignalsAreSetAfterOnSignalsCollectedWithValidMap() {
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\",\"gmaScarBiddingInterstitialSignal\": \"inSig\"}";
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\",\"gmaScarBiddingInterstitialSignal\": \"inSig\", \"gmaScarBiddingBannerSignal\": \"bnSig\"}";
|
||||
gmaScarBiddingSignalsListener = spy(new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
assertEquals("rvSig", signals.getRvSignal());
|
||||
assertEquals("inSig", signals.getInterstitialSignal());
|
||||
assertEquals("bnSig", signals.getBannerSignal());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -35,7 +36,7 @@ public class BiddingSignalsHandlerTest {
|
|||
fail();
|
||||
}
|
||||
});
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(gmaScarBiddingSignalsListener);
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(true, gmaScarBiddingSignalsListener);
|
||||
|
||||
biddingSignalsHandler.onSignalsCollected(map);
|
||||
verify(gmaScarBiddingSignalsListener, times(1)).onSignalsReady(
|
||||
|
@ -44,13 +45,14 @@ public class BiddingSignalsHandlerTest {
|
|||
|
||||
@Test
|
||||
public void testNoInterstitialSignalSetAfterOnSignalsCollectedWithMissingInterstitial() {
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\",\"asdfasdfasf\": \"inSig\"}";
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\", \"gmaScarBiddingBannerSignal\": \"bnSig\"}";
|
||||
|
||||
gmaScarBiddingSignalsListener = spy(new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
assertEquals("rvSig", signals.getRvSignal());
|
||||
assertEquals("", signals.getInterstitialSignal());
|
||||
assertEquals("bnSig", signals.getBannerSignal());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -58,7 +60,55 @@ public class BiddingSignalsHandlerTest {
|
|||
fail();
|
||||
}
|
||||
});
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(gmaScarBiddingSignalsListener);
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(true, gmaScarBiddingSignalsListener);
|
||||
|
||||
biddingSignalsHandler.onSignalsCollected(map);
|
||||
verify(gmaScarBiddingSignalsListener, times(1)).onSignalsReady(
|
||||
isA(BiddingSignals.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoBannerSignalSetAfterOnSignalsCollectedWithBannerDisabled() {
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\",\"gmaScarBiddingInterstitialSignal\": \"inSig\"}";
|
||||
|
||||
gmaScarBiddingSignalsListener = spy(new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
assertEquals("rvSig", signals.getRvSignal());
|
||||
assertEquals("inSig", signals.getInterstitialSignal());
|
||||
assertEquals("", signals.getBannerSignal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalsFailure(String msg) {
|
||||
fail();
|
||||
}
|
||||
});
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(false, gmaScarBiddingSignalsListener);
|
||||
|
||||
biddingSignalsHandler.onSignalsCollected(map);
|
||||
verify(gmaScarBiddingSignalsListener, times(1)).onSignalsReady(
|
||||
isA(BiddingSignals.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoBannerSignalSetAfterOnSignalsCollectedWithBannerPresent() {
|
||||
String map = "{\"gmaScarBiddingRewardedSignal\": \"rvSig\",\"gmaScarBiddingInterstitialSignal\": \"inSig\", \"gmaScarBiddingBannerSignal\": \"bnSig\"}";
|
||||
|
||||
gmaScarBiddingSignalsListener = spy(new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
assertEquals("rvSig", signals.getRvSignal());
|
||||
assertEquals("inSig", signals.getInterstitialSignal());
|
||||
assertEquals("", signals.getBannerSignal());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalsFailure(String msg) {
|
||||
fail();
|
||||
}
|
||||
});
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(false, gmaScarBiddingSignalsListener);
|
||||
|
||||
biddingSignalsHandler.onSignalsCollected(map);
|
||||
verify(gmaScarBiddingSignalsListener, times(1)).onSignalsReady(
|
||||
|
@ -80,7 +130,7 @@ public class BiddingSignalsHandlerTest {
|
|||
fail();
|
||||
}
|
||||
});
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(gmaScarBiddingSignalsListener);
|
||||
biddingSignalsHandler = new BiddingSignalsHandler(false, gmaScarBiddingSignalsListener);
|
||||
|
||||
biddingSignalsHandler.onSignalsCollected(map);
|
||||
verify(gmaScarBiddingSignalsListener, times(1)).onSignalsReady(
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.handlers.ScarBannerAdHandler;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ScarBannerAdHandlerTest {
|
||||
|
||||
@Mock
|
||||
WebViewApp mockWebViewApp;
|
||||
|
||||
private String testBannerId = "test-bannerId";
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
WebViewApp.setCurrentApp(mockWebViewApp);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdLoaded() {
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdLoaded();
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(eq(WebViewEventCategory.BANNER), eq(BannerBridge.BannerEvent.SCAR_BANNER_LOADED), eq(testBannerId));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdFailedToLoad() {
|
||||
int errorCode = 123;
|
||||
String errorString = "Test Error Message";
|
||||
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdFailedToLoad(errorCode, errorString);
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(
|
||||
eq(WebViewEventCategory.BANNER),
|
||||
eq(BannerBridge.BannerEvent.SCAR_BANNER_LOAD_FAILED),
|
||||
eq(testBannerId)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdOpened() {
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdOpened();
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(
|
||||
eq(WebViewEventCategory.BANNER),
|
||||
eq(BannerBridge.BannerEvent.SCAR_BANNER_OPENED),
|
||||
eq(testBannerId)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdClicked() {
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdClicked();
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(
|
||||
eq(WebViewEventCategory.BANNER),
|
||||
eq(BannerBridge.BannerEvent.SCAR_BANNER_CLICKED),
|
||||
eq(testBannerId)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdClosed() {
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdClosed();
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(
|
||||
eq(WebViewEventCategory.BANNER),
|
||||
eq(BannerBridge.BannerEvent.SCAR_BANNER_CLOSED),
|
||||
eq(testBannerId)
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnAdImpression() {
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(testBannerId);
|
||||
adHandler.onAdImpression();
|
||||
|
||||
Mockito.verify(mockWebViewApp, times(1)).sendEvent(
|
||||
eq(WebViewEventCategory.BANNER),
|
||||
eq(BannerBridge.BannerEvent.SCAR_BANNER_IMPRESSION),
|
||||
eq(testBannerId)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ public class BiddingBaseManagerTest {
|
|||
|
||||
private BiddingBaseManager managerWithTokenListener;
|
||||
private BiddingBaseManager managerWithNullListener;
|
||||
|
||||
private boolean isBannerEnabled = true;
|
||||
private String TEST_TOKEN = "token";
|
||||
private boolean isAsyncTokenCall = true;
|
||||
private boolean isNotAsyncTokenCall = false;
|
||||
|
@ -48,28 +48,18 @@ public class BiddingBaseManagerTest {
|
|||
public void setup() {
|
||||
ClientProperties.setApplication((Application) InstrumentationRegistry.getInstrumentation().getTargetContext().getApplicationContext());
|
||||
ClientProperties.setApplicationContext(InstrumentationRegistry.getInstrumentation().getTargetContext());
|
||||
managerWithTokenListener = Mockito.spy(new BiddingBaseManager(publisherListener) {
|
||||
managerWithTokenListener = Mockito.spy(new BiddingBaseManager(isBannerEnabled, publisherListener) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
managerWithNullListener = Mockito.spy(new BiddingBaseManager(null) {
|
||||
managerWithNullListener = Mockito.spy(new BiddingBaseManager(isBannerEnabled, null) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Mockito.when(managerWithTokenListener.getMetricSender()).thenReturn(_metricSenderMock);
|
||||
|
@ -115,16 +105,11 @@ public class BiddingBaseManagerTest {
|
|||
|
||||
@Test
|
||||
public void testSendsAsyncMetricWhenUploadStartsAndSucceedsWithAsyncTokenCall() throws InterruptedException {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(publisherListener, _scarRequestHandlerMock) {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(isBannerEnabled, publisherListener, _scarRequestHandlerMock) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
Mockito.when(managerWithScarRequestSender.getMetricSender()).thenReturn(_metricSenderMock);
|
||||
|
||||
|
@ -133,7 +118,7 @@ public class BiddingBaseManagerTest {
|
|||
final Metric secondDesiredMetric = ScarMetric.hbSignalsUploadSuccess(isAsyncTokenCall);
|
||||
|
||||
managerWithScarRequestSender.permitUpload();
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal"));
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal", "testBannerSignal"));
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
|
@ -170,21 +155,16 @@ public class BiddingBaseManagerTest {
|
|||
public void testSendsAsyncMetricWhenUploadRequestFailsWithMalformedUrlAndAsyncTokenCall() throws Exception {
|
||||
String errorMessage = "bad request";
|
||||
Mockito.doThrow(new Exception(errorMessage)).when(_scarRequestHandlerMock).makeUploadRequest(Mockito.<String>any(), Mockito.<BiddingSignals>any(), any(String.class));
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(publisherListener, _scarRequestHandlerMock) {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(isBannerEnabled, publisherListener, _scarRequestHandlerMock) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
Mockito.when(managerWithScarRequestSender.getMetricSender()).thenReturn(_metricSenderMock);
|
||||
|
||||
managerWithScarRequestSender.permitUpload();
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal"));
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal", "testBannerSignal"));
|
||||
|
||||
final ArgumentCaptor<Metric> metricsCaptor = ArgumentCaptor.forClass(Metric.class);
|
||||
final Metric firstDesiredMetric = ScarMetric.hbSignalsUploadStart(isAsyncTokenCall);
|
||||
|
@ -242,16 +222,11 @@ public class BiddingBaseManagerTest {
|
|||
|
||||
@Test
|
||||
public void testSendsSyncMetricWhenUploadStartsAndSucceedsWithSyncTokenCall() throws InterruptedException {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(null, _scarRequestHandlerMock) {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(isBannerEnabled, null, _scarRequestHandlerMock) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
Mockito.when(managerWithScarRequestSender.getMetricSender()).thenReturn(_metricSenderMock);
|
||||
|
||||
|
@ -260,7 +235,7 @@ public class BiddingBaseManagerTest {
|
|||
final Metric secondDesiredMetric = ScarMetric.hbSignalsUploadSuccess(isNotAsyncTokenCall);
|
||||
|
||||
managerWithScarRequestSender.permitUpload();
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal"));
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal", "testBannerSignal"));
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
|
@ -297,21 +272,16 @@ public class BiddingBaseManagerTest {
|
|||
public void testSendsSyncMetricWhenUploadRequestFailsWithMalformedUrlAndSyncTokenCall() throws Exception {
|
||||
String errorMessage = "bad request";
|
||||
Mockito.doThrow(new Exception(errorMessage)).when(_scarRequestHandlerMock).makeUploadRequest(Mockito.<String>any(), Mockito.<BiddingSignals>any(), any(String.class));
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(null, _scarRequestHandlerMock) {
|
||||
BiddingBaseManager managerWithScarRequestSender = Mockito.spy(new BiddingBaseManager(isBannerEnabled, null, _scarRequestHandlerMock) {
|
||||
@Override
|
||||
public void start() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
|
||||
}
|
||||
});
|
||||
Mockito.when(managerWithScarRequestSender.getMetricSender()).thenReturn(_metricSenderMock);
|
||||
|
||||
managerWithScarRequestSender.permitUpload();
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal"));
|
||||
managerWithScarRequestSender.onSignalsReady(new BiddingSignals("testRewardedSignal", "testInterstitialSignal", "testBannerSignal"));
|
||||
|
||||
final ArgumentCaptor<Metric> metricsCaptor = ArgumentCaptor.forClass(Metric.class);
|
||||
final Metric firstDesiredMetric = ScarMetric.hbSignalsUploadStart(isNotAsyncTokenCall);
|
||||
|
@ -336,29 +306,11 @@ public class BiddingBaseManagerTest {
|
|||
Mockito.verify(publisherListener, Mockito.times(1)).onUnityAdsTokenReady(TEST_TOKEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUnityTokenSuccessfullyFetchedAfterOnUnityAdsTokenReadyWithValidToken() {
|
||||
managerWithTokenListener.onUnityAdsTokenReady(TEST_TOKEN);
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(1)).onUnityTokenSuccessfullyFetched();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUnityTokenSuccessfullyFetchedAfterOnUnityAdsTokenReadyWithNullToken() {
|
||||
managerWithTokenListener.onUnityAdsTokenReady(null);
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(0)).onUnityTokenSuccessfullyFetched();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnUnityTokenSuccessfullyFetchedAfterOnUnityAdsTokenReadyWithEmptyToken() {
|
||||
managerWithTokenListener.onUnityAdsTokenReady("");
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(0)).onUnityTokenSuccessfullyFetched();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUploadSignalsAfterPermittedAndSignalsReady() throws InterruptedException {
|
||||
managerWithTokenListener.permitSignalsUpload();
|
||||
Thread.sleep(100);
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test", "test"));
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(1)).uploadSignals();
|
||||
}
|
||||
|
||||
|
@ -371,7 +323,7 @@ public class BiddingBaseManagerTest {
|
|||
|
||||
@Test
|
||||
public void testUploadSignalsAfterSignalsReadyButNotPermitted() throws InterruptedException {
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test", "test"));
|
||||
Thread.sleep(100);
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(0)).uploadSignals();
|
||||
}
|
||||
|
@ -381,9 +333,9 @@ public class BiddingBaseManagerTest {
|
|||
managerWithTokenListener.permitSignalsUpload();
|
||||
Thread.sleep(100);
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(0)).uploadSignals();
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test", "test"));
|
||||
managerWithTokenListener.onSignalsReady(new BiddingSignals("test", "test", "test"));
|
||||
Mockito.verify(managerWithTokenListener, Mockito.times(1)).uploadSignals();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,10 +17,11 @@ public class BiddingEagerManagerTest {
|
|||
IUnityAdsTokenListener callerListener;
|
||||
private BiddingEagerManager manager;
|
||||
private String TEST_TOKEN = "token";
|
||||
private boolean isBannerEnabled = true;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = Mockito.spy(new BiddingEagerManager(callerListener));
|
||||
manager = Mockito.spy(new BiddingEagerManager(isBannerEnabled, callerListener));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -30,13 +31,6 @@ public class BiddingEagerManagerTest {
|
|||
Mockito.verify(manager, Mockito.times(1)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoFetchAndUploadSignalsAfterOnUnityTokenSuccessfullyFetched() {
|
||||
manager.onUnityTokenSuccessfullyFetched();
|
||||
Mockito.verify(manager, Mockito.times(0)).fetchSignals();
|
||||
Mockito.verify(manager, Mockito.times(0)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerIsInvokedOnUnityAdsTokenReady() {
|
||||
manager.onUnityAdsTokenReady(TEST_TOKEN);
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.managers;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
import com.unity3d.services.ads.gmascar.managers.BiddingLazyManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BiddingLazyManagerTest {
|
||||
|
||||
@Mock
|
||||
IUnityAdsTokenListener callerListener;
|
||||
private BiddingLazyManager manager;
|
||||
private String TEST_TOKEN = "token";
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = Mockito.spy(new BiddingLazyManager(callerListener));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoActionAfterStartCalled() {
|
||||
manager.start();
|
||||
Mockito.verify(manager, Mockito.times(0)).fetchSignals();
|
||||
Mockito.verify(manager, Mockito.times(0)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPermitAndFetchSignalsAfterStartCalled() {
|
||||
manager.onUnityTokenSuccessfullyFetched();
|
||||
Mockito.verify(manager, Mockito.times(1)).fetchSignals();
|
||||
Mockito.verify(manager, Mockito.times(1)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerIsInvokedOnUnityAdsTokenReady() {
|
||||
manager.onUnityAdsTokenReady(TEST_TOKEN);
|
||||
Mockito.verify(callerListener, Mockito.times(1)).onUnityAdsTokenReady(TEST_TOKEN);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.managers;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
import com.unity3d.services.ads.gmascar.managers.BiddingOnDemandManager;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class BiddingOnDemandManagerTest {
|
||||
|
||||
@Mock
|
||||
IUnityAdsTokenListener callerListener;
|
||||
private BiddingOnDemandManager manager;
|
||||
private String TEST_TOKEN = "token";
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
manager = Mockito.spy(new BiddingOnDemandManager(callerListener));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyFetchSignalsCalledAfterStartCalled() {
|
||||
manager.start();
|
||||
Mockito.verify(manager, Mockito.times(1)).fetchSignals();
|
||||
Mockito.verify(manager, Mockito.times(0)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyPermitSignalsCalledAfterOnUnityTokenSuccessfullyFetched() {
|
||||
manager.onUnityTokenSuccessfullyFetched();
|
||||
Mockito.verify(manager, Mockito.times(0)).fetchSignals();
|
||||
Mockito.verify(manager, Mockito.times(1)).permitSignalsUpload();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListenerIsInvokedOnUnityAdsTokenReady() {
|
||||
manager.onUnityAdsTokenReady(TEST_TOKEN);
|
||||
Mockito.verify(callerListener, Mockito.times(1)).onUnityAdsTokenReady(TEST_TOKEN);
|
||||
}
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.managers;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.managers.SCARBiddingManagerType;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
public class ScarBiddingManagerEnumTest {
|
||||
|
||||
@Test
|
||||
public void testEnumToNameMappings() {
|
||||
assertEquals("dis", SCARBiddingManagerType.DISABLED.getName());
|
||||
assertEquals("hyb", SCARBiddingManagerType.HYBRID.getName());
|
||||
assertEquals("laz", SCARBiddingManagerType.LAZY.getName());
|
||||
assertEquals("eag", SCARBiddingManagerType.EAGER.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNameToEnumMappings() {
|
||||
assertEquals(SCARBiddingManagerType.DISABLED, SCARBiddingManagerType.fromName("dis"));
|
||||
assertEquals(SCARBiddingManagerType.HYBRID, SCARBiddingManagerType.fromName("hyb"));
|
||||
assertEquals(SCARBiddingManagerType.LAZY, SCARBiddingManagerType.fromName("laz"));
|
||||
assertEquals(SCARBiddingManagerType.EAGER, SCARBiddingManagerType.fromName("eag"));
|
||||
}
|
||||
}
|
|
@ -13,11 +13,12 @@ import com.unity3d.ads.test.TestUtilities;
|
|||
import com.unity3d.services.ads.operation.load.ILoadModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadModuleDecoratorTimeout;
|
||||
import com.unity3d.services.ads.operation.load.LoadOperationState;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentObjects;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
@ -35,23 +36,23 @@ public class LoadModuleDecoratorTimeoutTests {
|
|||
private IUnityAdsLoadListener loadListenerMock;
|
||||
private ILoadModule loadModuleMock;
|
||||
private SDKMetricsSender sdkMetricsMock;
|
||||
private ConfigurationReader configurationReaderMock;
|
||||
private ExperimentsReader experimentsReaderMock;
|
||||
|
||||
@Before
|
||||
public void beforeEachTest() {
|
||||
loadListenerMock = mock(IUnityAdsLoadListener.class);
|
||||
loadModuleMock = mock(ILoadModule.class);
|
||||
sdkMetricsMock = mock(SDKMetricsSender.class);
|
||||
configurationReaderMock = mock(ConfigurationReader.class);
|
||||
experimentsReaderMock = mock(ExperimentsReader.class);
|
||||
|
||||
Mockito.when(configurationReaderMock.getCurrentConfiguration()).thenReturn(new Configuration());
|
||||
Mockito.when(experimentsReaderMock.getCurrentlyActiveExperiments()).thenReturn(new ExperimentObjects(new JSONObject()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onUnityAdsFailedToLoadIsCalledWhenTimeoutIsReached() {
|
||||
Mockito.when(loadModuleMock.getMetricSender()).thenReturn(sdkMetricsMock);
|
||||
LoadOperationState loadOperationState = new LoadOperationState(placementId, loadListenerMock, loadOptions, OperationTestUtilities.createConfigurationWithLoadTimeout(loadTimeout));
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, configurationReaderMock);
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, experimentsReaderMock);
|
||||
|
||||
timeoutDecorator.executeAdOperation(mock(IWebViewBridgeInvoker.class), loadOperationState);
|
||||
Mockito.verify(loadListenerMock, timeout(maxWaitTime).times(1)).onUnityAdsFailedToLoad(placementId, UnityAds.UnityAdsLoadError.TIMEOUT, "[UnityAds] Timeout while loading " + placementId);
|
||||
|
@ -61,7 +62,7 @@ public class LoadModuleDecoratorTimeoutTests {
|
|||
public void onUnityAdsAdLoadedAndOnUnityAdsAdFailedToLoadIsNotCalledAgainWhenTimeoutHasBeenReached() {
|
||||
Mockito.when(loadModuleMock.getMetricSender()).thenReturn(sdkMetricsMock);
|
||||
LoadOperationState loadOperationState = new LoadOperationState(placementId, loadListenerMock, loadOptions, OperationTestUtilities.createConfigurationWithLoadTimeout(loadTimeout));
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, configurationReaderMock);
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, experimentsReaderMock);
|
||||
|
||||
timeoutDecorator.executeAdOperation(mock(IWebViewBridgeInvoker.class), loadOperationState);
|
||||
TestUtilities.SleepCurrentThread(loadTimeoutExpireMs);
|
||||
|
@ -76,7 +77,7 @@ public class LoadModuleDecoratorTimeoutTests {
|
|||
public void onUnityAdsAdFailedToLoadIsNotCalledWhenOnUnityAdsAdLoadedIsCalledBeforeTimeout() {
|
||||
Mockito.when(loadModuleMock.getMetricSender()).thenReturn(sdkMetricsMock);
|
||||
LoadOperationState loadOperationState = new LoadOperationState(placementId, loadListenerMock, loadOptions, OperationTestUtilities.createConfigurationWithLoadTimeout(loadTimeout));
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, configurationReaderMock);
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, experimentsReaderMock);
|
||||
|
||||
timeoutDecorator.executeAdOperation(mock(IWebViewBridgeInvoker.class), loadOperationState);
|
||||
TestUtilities.SleepCurrentThread(25);
|
||||
|
@ -88,14 +89,14 @@ public class LoadModuleDecoratorTimeoutTests {
|
|||
|
||||
@Test
|
||||
public void noNPEIsThrownWhenOnUnityAdsAdLoadedIsCalledWithoutCallingExecuteAdOperation() {
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, configurationReaderMock);
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, experimentsReaderMock);
|
||||
timeoutDecorator.onUnityAdsAdLoaded(placementId);
|
||||
Mockito.verify(loadModuleMock, times(0)).onUnityAdsFailedToLoad(anyString(), any(UnityAds.UnityAdsLoadError.class), anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void noNPEIsThrownWhenOnUnityAdsAdFailedToLoadIsCalledWithoutCallingExecuteAdOperation() {
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, configurationReaderMock);
|
||||
LoadModuleDecoratorTimeout timeoutDecorator = new LoadModuleDecoratorTimeout(loadModuleMock, experimentsReaderMock);
|
||||
timeoutDecorator.onUnityAdsFailedToLoad(placementId, loadError, loadErrorMessage);
|
||||
Mockito.verify(loadModuleMock, times(0)).onUnityAdsAdLoaded(anyString());
|
||||
}
|
||||
|
|
|
@ -17,8 +17,8 @@ import com.unity3d.services.ads.operation.show.IShowModule;
|
|||
import com.unity3d.services.ads.operation.show.ShowModule;
|
||||
import com.unity3d.services.ads.operation.show.ShowModuleDecoratorTimeout;
|
||||
import com.unity3d.services.ads.operation.show.ShowOperationState;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.Experiments;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
@ -41,7 +41,7 @@ public class ShowModuleDecoratorTimeoutTests {
|
|||
private IUnityAdsShowListener showListenerMock;
|
||||
private IShowModule showModule;
|
||||
private SDKMetricsSender sdkMetricsMock;
|
||||
private ConfigurationReader configurationReaderMock;
|
||||
private ExperimentsReader experimentsReaderMock;
|
||||
|
||||
@Rule
|
||||
public final ActivityTestRule<InstrumentationTestActivity> _activityRule = new ActivityTestRule<>(InstrumentationTestActivity.class);
|
||||
|
@ -50,16 +50,16 @@ public class ShowModuleDecoratorTimeoutTests {
|
|||
public void beforeEachTest() {
|
||||
showListenerMock = mock(IUnityAdsShowListener.class);
|
||||
sdkMetricsMock = mock(SDKMetricsSender.class);
|
||||
configurationReaderMock = mock(ConfigurationReader.class);
|
||||
experimentsReaderMock = mock(ExperimentsReader.class);
|
||||
// We need a real instance since ShowModule will create the Operation object (which holds the State with Listener ID)
|
||||
showModule = new ShowModule(sdkMetricsMock);
|
||||
|
||||
Mockito.when(configurationReaderMock.getCurrentConfiguration()).thenReturn(new Configuration());
|
||||
Mockito.when(experimentsReaderMock.getCurrentlyActiveExperiments()).thenReturn(new Experiments());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testShowModuleDecoratorTimeout() {
|
||||
ShowModuleDecoratorTimeout showModuleDecoratorTimeout = new ShowModuleDecoratorTimeout(showModule, configurationReaderMock);
|
||||
ShowModuleDecoratorTimeout showModuleDecoratorTimeout = new ShowModuleDecoratorTimeout(showModule, experimentsReaderMock);
|
||||
ShowOperationState showOperationState = new ShowOperationState(placementId, showListenerMock, _activityRule.getActivity(), showOptions, OperationTestUtilities.createConfigurationWithShowTimeout(showTimeout));
|
||||
showModuleDecoratorTimeout.executeAdOperation(mock(IWebViewBridgeInvoker.class), showOperationState);
|
||||
|
||||
|
@ -68,7 +68,7 @@ public class ShowModuleDecoratorTimeoutTests {
|
|||
|
||||
@Test
|
||||
public void testShowModuleDecoratorShowConsentNoTimeout() {
|
||||
ShowModuleDecoratorTimeout showModuleDecoratorTimeout = new ShowModuleDecoratorTimeout(showModule, configurationReaderMock);
|
||||
ShowModuleDecoratorTimeout showModuleDecoratorTimeout = new ShowModuleDecoratorTimeout(showModule, experimentsReaderMock);
|
||||
ShowOperationState showOperationState = new ShowOperationState(placementId, showListenerMock, _activityRule.getActivity(), showOptions, OperationTestUtilities.createConfigurationWithShowTimeout(showTimeout));
|
||||
IWebViewBridgeInvoker webViewBridgeInvoker = mock(IWebViewBridgeInvoker.class);
|
||||
when(webViewBridgeInvoker.invokeMethod(anyString(), anyString(), any(Method.class), any())).thenReturn(true);
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.banners;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.banners.BannerErrorCode;
|
||||
import com.unity3d.services.banners.BannerErrorInfo;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class BannerErrorInfoTest {
|
||||
|
||||
private String errorMessage = "BANNER ERROR MSG";
|
||||
|
||||
@Test
|
||||
public void testConvertNativeBannerErrorToLoadError() {
|
||||
BannerErrorInfo nativeError = new BannerErrorInfo(errorMessage, BannerErrorCode.NATIVE_ERROR);
|
||||
UnityAds.UnityAdsLoadError loadError = nativeError.toLoadError();
|
||||
assertEquals(UnityAds.UnityAdsLoadError.INVALID_ARGUMENT, loadError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertNoFillBannerErrorToLoadError() {
|
||||
BannerErrorInfo noFillError = new BannerErrorInfo(errorMessage, BannerErrorCode.NO_FILL);
|
||||
UnityAds.UnityAdsLoadError loadError = noFillError.toLoadError();
|
||||
assertEquals(UnityAds.UnityAdsLoadError.NO_FILL, loadError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertWebViewBannerErrorToLoadError() {
|
||||
BannerErrorInfo webViewError = new BannerErrorInfo(errorMessage, BannerErrorCode.WEBVIEW_ERROR);
|
||||
UnityAds.UnityAdsLoadError loadError = webViewError.toLoadError();
|
||||
assertEquals(UnityAds.UnityAdsLoadError.INTERNAL_ERROR, loadError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConvertUnknownBannerErrorToLoadError() {
|
||||
BannerErrorInfo unknownError = new BannerErrorInfo(errorMessage, BannerErrorCode.UNKNOWN);
|
||||
UnityAds.UnityAdsLoadError loadError = unknownError.toLoadError();
|
||||
assertEquals(UnityAds.UnityAdsLoadError.INTERNAL_ERROR, loadError);
|
||||
}
|
||||
}
|
|
@ -68,18 +68,28 @@ public class BannerViewCacheTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testTriggerBannerLoadEvent() throws InterruptedException {
|
||||
public void testTriggerBannerLoadEvent() throws InterruptedException, NoSuchFieldException, IllegalAccessException {
|
||||
BannerViewCache bannerViewCache = new BannerViewCache();
|
||||
final BannerView bannerView = new BannerView(_activityRule.getActivity(), "test", new UnityBannerSize(320, 50));
|
||||
String bannerAdId = bannerViewCache.addBannerView(bannerView);
|
||||
final Semaphore _loadedSemaphore = new Semaphore(0);
|
||||
|
||||
ILoadModule loadBannerModule = new LoadBannerModule(Mockito.mock(SDKMetricsSender.class));
|
||||
ILoadModule spy = Mockito.spy(loadBannerModule);
|
||||
|
||||
Field instance = LoadBannerModule.class.getDeclaredField("_instance");
|
||||
instance.setAccessible(true);
|
||||
instance.set(LoadBannerModule.class, spy);
|
||||
|
||||
bannerView.setListener(new BannerView.Listener() {
|
||||
@Override
|
||||
public void onBannerLoaded(BannerView bannerAdView) {
|
||||
assertEquals(bannerView, bannerAdView);
|
||||
Mockito.verify(spy).onUnityAdsAdLoaded(bannerAdId);
|
||||
_loadedSemaphore.release();
|
||||
}
|
||||
});
|
||||
|
||||
bannerViewCache.triggerBannerLoadEvent(bannerAdId);
|
||||
_loadedSemaphore.acquire();
|
||||
}
|
||||
|
@ -119,7 +129,7 @@ public class BannerViewCacheTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testTriggerBannerErrorEvent() throws InterruptedException, NoSuchFieldException, IllegalAccessException {
|
||||
public void testTriggerBannerErrorEventWithNativeError() throws InterruptedException, NoSuchFieldException, IllegalAccessException {
|
||||
BannerViewCache bannerViewCache = new BannerViewCache();
|
||||
final BannerView bannerView = new BannerView(_activityRule.getActivity(), "test", new UnityBannerSize(320, 50));
|
||||
final BannerErrorInfo bannerErrorInfo = new BannerErrorInfo("test error", BannerErrorCode.NATIVE_ERROR);
|
||||
|
@ -133,6 +143,52 @@ public class BannerViewCacheTests {
|
|||
ILoadOperation loadOperation = Mockito.mock(ILoadOperation.class);
|
||||
Mockito.when(loadOperation.getLoadOperationState()).thenReturn(loadOperationState);
|
||||
|
||||
ILoadModule loadBannerModule = new LoadBannerModule(Mockito.mock(SDKMetricsSender.class));
|
||||
ILoadModule spy = Mockito.spy(loadBannerModule);
|
||||
Mockito.when(spy.get(Mockito.anyString())).thenReturn(loadOperation);
|
||||
Mockito.doAnswer(invocation -> {
|
||||
Mockito.doAnswer(invocation1 -> {
|
||||
LoadOperationState state = invocation.getArgument(1);
|
||||
state.onUnityAdsFailedToLoad(UnityAds.UnityAdsLoadError.INVALID_ARGUMENT, "test error");
|
||||
return null;
|
||||
}).when(loadOperation).onUnityAdsFailedToLoad(Mockito.anyString(), Mockito.any(), Mockito.any());
|
||||
return null;
|
||||
}).when(spy).executeAdOperation(Mockito.any(), Mockito.any());
|
||||
|
||||
Field instance = LoadBannerModule.class.getDeclaredField("_instance");
|
||||
instance.setAccessible(true);
|
||||
instance.set(LoadBannerModule.class, spy);
|
||||
|
||||
final Semaphore _errorSemaphore = new Semaphore(0);
|
||||
bannerView.setListener(new BannerView.Listener() {
|
||||
@Override
|
||||
public void onBannerFailedToLoad(BannerView bannerAdView, BannerErrorInfo _bannerErrorInfo) {
|
||||
assertEquals(bannerView, bannerAdView);
|
||||
assertEquals(BannerErrorCode.NATIVE_ERROR, _bannerErrorInfo.errorCode);
|
||||
Mockito.verify(spy).onUnityAdsFailedToLoad(bannerAdId, UnityAds.UnityAdsLoadError.INVALID_ARGUMENT, "test error");
|
||||
_errorSemaphore.release();
|
||||
}
|
||||
});
|
||||
bannerView.load();
|
||||
bannerViewCache.triggerBannerErrorEvent(bannerAdId, bannerErrorInfo);
|
||||
_errorSemaphore.acquire();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTriggerBannerErrorEventWithWebViewError() throws InterruptedException, NoSuchFieldException, IllegalAccessException {
|
||||
BannerViewCache bannerViewCache = new BannerViewCache();
|
||||
final BannerView bannerView = new BannerView(_activityRule.getActivity(), "test", new UnityBannerSize(320, 50));
|
||||
final BannerErrorInfo bannerErrorInfo = new BannerErrorInfo("test error", BannerErrorCode.WEBVIEW_ERROR);
|
||||
String bannerAdId = bannerViewCache.addBannerView(bannerView);
|
||||
|
||||
LoadOperationState loadOperationState = Mockito.mock(LoadOperationState.class);
|
||||
Mockito.when(loadOperationState.isBanner()).thenReturn(true);
|
||||
Mockito.when(loadOperationState.duration()).thenReturn(Long.MAX_VALUE);
|
||||
loadOperationState.placementId = "test";
|
||||
|
||||
ILoadOperation loadOperation = Mockito.mock(ILoadOperation.class);
|
||||
Mockito.when(loadOperation.getLoadOperationState()).thenReturn(loadOperationState);
|
||||
|
||||
ILoadModule loadBannerModule = new LoadBannerModule(Mockito.mock(SDKMetricsSender.class));
|
||||
ILoadModule spy = Mockito.spy(loadBannerModule);
|
||||
Mockito.when(spy.get(Mockito.anyString())).thenReturn(loadOperation);
|
||||
|
@ -154,6 +210,7 @@ public class BannerViewCacheTests {
|
|||
@Override
|
||||
public void onBannerFailedToLoad(BannerView bannerAdView, BannerErrorInfo _bannerErrorInfo) {
|
||||
assertEquals(bannerView, bannerAdView);
|
||||
assertEquals(BannerErrorCode.WEBVIEW_ERROR, _bannerErrorInfo.errorCode);
|
||||
Mockito.verify(spy).onUnityAdsFailedToLoad(bannerAdId, UnityAds.UnityAdsLoadError.INTERNAL_ERROR, "test error");
|
||||
_errorSemaphore.release();
|
||||
}
|
||||
|
@ -179,5 +236,4 @@ public class BannerViewCacheTests {
|
|||
bannerViewCache.triggerBannerLeftApplicationEvent(bannerAdId);
|
||||
_leftApplicationSemaphore.acquire();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,9 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.core.webview;
|
||||
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.Experiments;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.webview.WebViewUrlBuilder;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -57,7 +54,7 @@ public class WebViewUrlBuilderTest {
|
|||
@Test
|
||||
public void testWebViewUrlBuilderWithMetricsEnabled() {
|
||||
Mockito.when(_configMock.getExperiments()).thenReturn(null);
|
||||
Mockito.when(_configMock.getMetricSampleRate()).thenReturn(100.0);
|
||||
Mockito.when(_configMock.areMetricsEnabledForCurrentSession()).thenReturn(Boolean.TRUE);
|
||||
Mockito.when(_configMock.getMetricsUrl()).thenReturn(TEST_BASE_URL);
|
||||
SDKMetrics.setConfiguration(_configMock);
|
||||
WebViewUrlBuilder webViewUrlBuilder = new WebViewUrlBuilder(TEST_BASE_URL, _configMock);
|
||||
|
|
|
@ -100,31 +100,6 @@ public class SDKMetricsTest {
|
|||
SDKMetrics.getInstance().sendEvent("test_event");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettingMsr100Then0() throws NoSuchFieldException, IllegalAccessException {
|
||||
validateAndTestChangingSampleRate("testUrl", 100.0, 0.0, MetricSender.class);
|
||||
Assert.assertTrue("Metrics expected to be enabled for session", SDKMetrics.getInstance().areMetricsEnabledForCurrentSession());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettingMsr0Then100() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
|
||||
Class expectedClass = Class.forName("com.unity3d.services.core.request.metrics.SDKMetrics$NullInstance");
|
||||
validateAndTestChangingSampleRate("testUrl", 0.0, 100.0, expectedClass);
|
||||
Assert.assertFalse("Metrics expected to be disabled for session", SDKMetrics.getInstance().areMetricsEnabledForCurrentSession());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettingMsrWithNullUrl() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
|
||||
Class expectedClass = Class.forName("com.unity3d.services.core.request.metrics.SDKMetrics$NullInstance");
|
||||
validateAndTestChangingSampleRate(null, 100.0, 100.0, expectedClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSettingMsrWithEmptyUrl() throws NoSuchFieldException, IllegalAccessException, ClassNotFoundException {
|
||||
Class expectedClass = Class.forName("com.unity3d.services.core.request.metrics.SDKMetrics$NullInstance");
|
||||
validateAndTestChangingSampleRate("", 100.0, 100.0, expectedClass);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMalformedUrlFromConfiguration() throws Exception {
|
||||
JSONObject json = new JSONObject();
|
||||
|
@ -159,20 +134,4 @@ public class SDKMetricsTest {
|
|||
Mockito.verify(_metricSenderMock).sendMetric(metricCapture.capture());
|
||||
Assert.assertEquals(TEST_STATE_TAGS, metricCapture.getValue().getTags());
|
||||
}
|
||||
|
||||
private void validateAndTestChangingSampleRate(String metricsUrl, double oldMsr, double newMsr, Class expectedMetricsClass) throws NoSuchFieldException, IllegalAccessException {
|
||||
Configuration mockConfiguration = Mockito.mock(Configuration.class);
|
||||
Mockito.when(mockConfiguration.getMetricsUrl()).thenReturn(metricsUrl);
|
||||
Mockito.when(mockConfiguration.getMetricSampleRate()).thenReturn(oldMsr);
|
||||
SDKMetrics.setConfiguration(mockConfiguration);
|
||||
SDKMetrics.getInstance();
|
||||
Field instanceField = SDKMetrics.class.getDeclaredField("_instance");
|
||||
instanceField.setAccessible(true);
|
||||
Object instanceFieldObj = instanceField.get(SDKMetricsSender.class);
|
||||
Assert.assertEquals(expectedMetricsClass, instanceFieldObj.getClass());
|
||||
Mockito.when(mockConfiguration.getMetricSampleRate()).thenReturn(newMsr);
|
||||
SDKMetrics.setConfiguration(mockConfiguration);
|
||||
instanceFieldObj = instanceField.get(SDKMetricsSender.class);
|
||||
Assert.assertEquals(expectedMetricsClass, instanceFieldObj.getClass());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,11 @@ public class DeviceTest {
|
|||
assertTrue("Expected SDK_INT should be > 9", Device.getApiLevel() >= 9);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionVersion () {
|
||||
assertTrue("Expected extension version should be > 4", Device.getExtensionVersion() >= -1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScreenLayout () {
|
||||
assertTrue("Expected screenLayout property be something else than undefined (0)", Device.getScreenLayout() > 0);
|
||||
|
|
|
@ -2,7 +2,6 @@ package com.unity3d.services
|
|||
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.request.metrics.Metric
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import java.lang.IllegalStateException
|
||||
|
@ -14,19 +13,19 @@ class SDKErrorHandler(private val dispatchers: ISDKDispatchers, private val sdkM
|
|||
override val key = CoroutineExceptionHandler.Key
|
||||
|
||||
override fun handleException(context: CoroutineContext, exception: Throwable) {
|
||||
val className: String = exception.stackTrace[0].fileName
|
||||
val line: Int = exception.stackTrace[0].lineNumber
|
||||
val className: String = exception.stackTrace[0]?.fileName ?: "unknown"
|
||||
val line: Int = exception.stackTrace[0]?.lineNumber ?: 0
|
||||
|
||||
val name: String = when (exception) {
|
||||
is NullPointerException -> "native_exception_npe"
|
||||
is OutOfMemoryError -> "native_exception_oom"
|
||||
is IllegalStateException -> "native_exception_ise"
|
||||
is RuntimeException -> "native_exception_re"
|
||||
is SecurityException -> "native_exception_se"
|
||||
is RuntimeException -> "native_exception_re"
|
||||
else -> "native_exception"
|
||||
}
|
||||
|
||||
sendMetric(Metric(name, "{$className}_$line"))
|
||||
sendMetric(Metric(name, "${className}_$line"))
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ import com.unity3d.services.core.log.DeviceLog;
|
|||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewBridgeInvoker;
|
||||
|
@ -203,7 +202,7 @@ public final class UnityAdsImplementation implements IUnityAds {
|
|||
}
|
||||
|
||||
Configuration config = configuration == null ? new ConfigurationReader().getCurrentConfiguration() : configuration;
|
||||
BiddingBaseManager manager = BiddingManagerFactory.getInstance().createManager(listener, config.getExperiments());
|
||||
BiddingBaseManager manager = BiddingManagerFactory.getInstance().createManager(null, config.getExperiments());
|
||||
manager.start();
|
||||
|
||||
asyncTokenStorage.getToken(manager);
|
||||
|
|
|
@ -75,9 +75,10 @@ public class AdUnitActivity extends Activity implements IAdUnitActivity {
|
|||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
if (_controller != null) {
|
||||
_controller.onDestroy();
|
||||
}
|
||||
super.onDestroy();
|
||||
|
||||
_controller.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.InputEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
|
@ -13,6 +19,7 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
private final ArrayList<AdUnitMotionEvent> _motionEvents = new ArrayList<>();
|
||||
private int _maxEvents = 10000;
|
||||
private boolean _shouldCapture = false;
|
||||
private InputEvent _lastInputEvent;
|
||||
|
||||
public AdUnitRelativeLayout(Context context) {
|
||||
super(context);
|
||||
|
@ -22,6 +29,13 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
public boolean onInterceptTouchEvent(MotionEvent e) {
|
||||
super.onInterceptTouchEvent(e);
|
||||
|
||||
if (e.getActionMasked() == ACTION_UP ||
|
||||
e.getActionMasked() == ACTION_DOWN ||
|
||||
e.getActionMasked() == ACTION_POINTER_UP ||
|
||||
e.getActionMasked() == ACTION_POINTER_DOWN) {
|
||||
_lastInputEvent = e;
|
||||
}
|
||||
|
||||
if (_shouldCapture) {
|
||||
if (_motionEvents.size() < _maxEvents) {
|
||||
boolean isObscured = (e.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0;
|
||||
|
@ -102,4 +116,8 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public InputEvent getLastInputEvent() {
|
||||
return _lastInputEvent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import com.unity3d.scar.adapter.common.scarads.UnityAdFormat;
|
||||
import com.unity3d.services.ads.gmascar.GMAScarAdapterBridge;
|
||||
import com.unity3d.services.ads.gmascar.GMA;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
|
@ -30,8 +31,8 @@ public class GMAScar {
|
|||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getSCARSignals(final JSONArray interstitialList, final JSONArray rewardedList, final WebViewCallback callback) throws JSONException {
|
||||
gmaScarAdapterBridge.getSCARSignals(getPlacementList(interstitialList), getPlacementList(rewardedList));
|
||||
public static void getSCARSignal(final String placementId, final String adFormatStr, final WebViewCallback callback) {
|
||||
gmaScarAdapterBridge.getSCARSignal(placementId, UnityAdFormat.valueOf(adFormatStr.toUpperCase()));
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
|
@ -46,13 +47,4 @@ public class GMAScar {
|
|||
gmaScarAdapterBridge.show(placementId, queryId, canSkip);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
private static String[] getPlacementList(JSONArray placements) throws JSONException {
|
||||
String[] placementIdList = new String[placements.length()];
|
||||
for (int placementIndex = 0; placementIndex < placements.length(); placementIndex++) {
|
||||
placementIdList[placementIndex] = placements.getString(placementIndex);
|
||||
}
|
||||
return placementIdList;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import android.view.InputEvent;
|
||||
|
||||
import com.unity3d.services.ads.measurements.MeasurementsErrors;
|
||||
import com.unity3d.services.ads.measurements.MeasurementsService;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
public class Measurements {
|
||||
private static final MeasurementsService measurementsService = Utilities.getService(MeasurementsService.class);
|
||||
|
||||
@WebViewExposed
|
||||
public static void checkAvailability(WebViewCallback callback) {
|
||||
measurementsService.checkAvailability();
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void registerView(final String url, WebViewCallback callback) {
|
||||
measurementsService.registerView(url);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void registerClick(final String url, WebViewCallback callback) {
|
||||
if (AdUnit.getAdUnitActivity() == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_AD_UNIT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AdUnit.getAdUnitActivity().getLayout() == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_LAYOUT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
InputEvent lastInputEvent = AdUnit.getAdUnitActivity().getLayout().getLastInputEvent();
|
||||
if (lastInputEvent == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_LAST_INPUT_EVENT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
measurementsService.registerClick(url, lastInputEvent);
|
||||
callback.invoke();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import com.unity3d.services.ads.topics.TopicsService;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
public class Topics {
|
||||
private static final TopicsService topicsService = Utilities.getService(TopicsService.class);
|
||||
|
||||
@WebViewExposed
|
||||
public static void checkAvailability(WebViewCallback callback) {
|
||||
callback.invoke(topicsService.checkAvailability());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getTopics(String adsSdkName, Boolean shouldRecordObservation, WebViewCallback callback) {
|
||||
topicsService.getTopics(adsSdkName, shouldRecordObservation);
|
||||
callback.invoke();
|
||||
}
|
||||
}
|
|
@ -30,7 +30,9 @@ public class AdsModuleConfiguration implements IAdsModuleConfiguration {
|
|||
com.unity3d.services.ads.api.Load.class,
|
||||
com.unity3d.services.ads.api.Show.class,
|
||||
com.unity3d.services.ads.api.Token.class,
|
||||
com.unity3d.services.ads.api.GMAScar.class
|
||||
com.unity3d.services.ads.api.GMAScar.class,
|
||||
com.unity3d.services.ads.api.Measurements.class,
|
||||
com.unity3d.services.ads.api.Topics.class,
|
||||
};
|
||||
|
||||
return list;
|
||||
|
|
|
@ -52,7 +52,7 @@ public class GMA {
|
|||
* @param listener {@link IBiddingSignalsListener} implementation, to be notified when
|
||||
* signals are ready.
|
||||
*/
|
||||
public void getSCARBiddingSignals(IBiddingSignalsListener listener) {
|
||||
_gmaScarAdapterBridge.getSCARBiddingSignals(new BiddingSignalsHandler(listener));
|
||||
public void getSCARBiddingSignals(boolean isBannerEnabled, IBiddingSignalsListener listener) {
|
||||
_gmaScarAdapterBridge.getSCARBiddingSignals(isBannerEnabled, new BiddingSignalsHandler(isBannerEnabled, listener));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package com.unity3d.services.ads.gmascar;
|
||||
|
||||
import android.content.Context;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.common.scarads.UnityAdFormat;
|
||||
import com.unity3d.services.ads.gmascar.adapters.ScarAdapterFactory;
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
|
@ -13,16 +15,17 @@ import com.unity3d.services.ads.gmascar.finder.GMAInitializer;
|
|||
import com.unity3d.services.ads.gmascar.finder.PresenceDetector;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarAdapterVersion;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarVersionFinder;
|
||||
import com.unity3d.services.ads.gmascar.handlers.BiddingSignalsHandler;
|
||||
import com.unity3d.services.ads.gmascar.handlers.ScarInterstitialAdHandler;
|
||||
import com.unity3d.services.ads.gmascar.handlers.ScarRewardedAdHandler;
|
||||
import com.unity3d.services.ads.gmascar.handlers.SignalsHandler;
|
||||
import com.unity3d.services.ads.gmascar.handlers.WebViewErrorHandler;
|
||||
import com.unity3d.services.ads.gmascar.handlers.*;
|
||||
import com.unity3d.services.ads.gmascar.utils.GMAEventSender;
|
||||
import com.unity3d.services.banners.BannerView;
|
||||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.misc.EventSubject;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.timer.DefaultIntervalTimerFactory;
|
||||
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayDeque;
|
||||
|
@ -81,12 +84,12 @@ public class GMAScarAdapterBridge {
|
|||
_scarVersionFinder.getVersion();
|
||||
}
|
||||
|
||||
public void getSCARSignals(String[] interstitialList, String[] rewardedList) {
|
||||
public void getSCARSignal(String placementId, UnityAdFormat adFormat) {
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
SignalsHandler signalListener = new SignalsHandler(_gmaEventSender);
|
||||
|
||||
if (_scarAdapter != null) {
|
||||
_scarAdapter.getSCARSignals(ClientProperties.getApplicationContext(), interstitialList, rewardedList, signalListener);
|
||||
_scarAdapter.getSCARSignal(ClientProperties.getApplicationContext(), placementId, adFormat, signalListener);
|
||||
} else {
|
||||
_webViewErrorHandler.handleError(GMAAdsError.InternalSignalsError("Could not create SCAR adapter object"));
|
||||
}
|
||||
|
@ -111,11 +114,11 @@ public class GMAScarAdapterBridge {
|
|||
*
|
||||
* @param handler {@link BiddingSignalsHandler} to be notified when signals are ready.
|
||||
*/
|
||||
public void getSCARBiddingSignals(BiddingSignalsHandler handler) {
|
||||
public void getSCARBiddingSignals(boolean isBannerEnabled, BiddingSignalsHandler handler) {
|
||||
if (_mobileAdsBridge != null && _mobileAdsBridge.hasSCARBiddingSupport()) {
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
if (_scarAdapter != null) {
|
||||
_scarAdapter.getSCARBiddingSignals(ClientProperties.getApplicationContext(), handler);
|
||||
_scarAdapter.getSCARBiddingSignals(ClientProperties.getApplicationContext(), isBannerEnabled, handler);
|
||||
} else {
|
||||
handler.onSignalsCollectionFailed("Could not create SCAR adapter object.");
|
||||
}
|
||||
|
@ -148,6 +151,16 @@ public class GMAScarAdapterBridge {
|
|||
_scarAdapter.loadRewardedAd(ClientProperties.getApplicationContext(), scarAdMetadata, adListener);
|
||||
}
|
||||
|
||||
public void loadBanner(final Context context, final BannerView bannerView, final String operationId, final ScarAdMetadata scarAdMetadata, final UnityBannerSize bannerSize) {
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
ScarBannerAdHandler adHandler = new ScarBannerAdHandler(operationId);
|
||||
if (_scarAdapter != null) {
|
||||
_scarAdapter.loadBannerAd(context, bannerView, scarAdMetadata, bannerSize.getWidth(), bannerSize.getHeight(), adHandler);
|
||||
} else {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_LOAD_FAILED, operationId);
|
||||
}
|
||||
}
|
||||
|
||||
public void show(final String placementId, final String queryId, final boolean canSkip) {
|
||||
ScarAdMetadata scarAdMetadata = new ScarAdMetadata(placementId, queryId);
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
|
|
|
@ -14,12 +14,6 @@ public class ScarAdapterFactory {
|
|||
IScarAdapter scarAdapter = null;
|
||||
|
||||
switch (adapterVersion) {
|
||||
case V192:
|
||||
scarAdapter = new com.unity3d.scar.adapter.v1920.ScarAdapter(adsErrorHandler);
|
||||
break;
|
||||
case V195:
|
||||
scarAdapter = new com.unity3d.scar.adapter.v1950.ScarAdapter(adsErrorHandler);
|
||||
break;
|
||||
case V20:
|
||||
scarAdapter = new com.unity3d.scar.adapter.v2000.ScarAdapter(adsErrorHandler);
|
||||
break;
|
||||
|
|
|
@ -12,9 +12,6 @@ public class MobileAdsBridgeLegacy extends MobileAdsBridgeBase {
|
|||
// Codes returned by getVersionString in V20 and below
|
||||
public static final int CODE_21_0 = 221310000;
|
||||
public static final int CODE_20_0 = 210402000;
|
||||
public static final int CODE_19_8 = 204890000;
|
||||
public static final int CODE_19_5 = 203404000;
|
||||
public static final int CODE_19_2 = 201604000;
|
||||
|
||||
// Deprecated in V21 - requires initialization and returns internal version (e.g., "afma-sdk-a-v<OTA services>.<SCAR version>.X")
|
||||
public static final String versionStringMethodName = "getVersionString";
|
||||
|
@ -44,11 +41,7 @@ public class MobileAdsBridgeLegacy extends MobileAdsBridgeBase {
|
|||
@Override
|
||||
public ScarAdapterVersion getAdapterVersion(int versionCode) {
|
||||
// Version codes in V20 and below are returned as internal nine digit numbers (e.g., "afma-sdk-a-vX.210402000.X)
|
||||
if (versionCode >= CODE_19_2 && versionCode < CODE_19_5) {
|
||||
return ScarAdapterVersion.V192;
|
||||
} else if (versionCode >= CODE_19_5 && versionCode <= CODE_19_8) {
|
||||
return ScarAdapterVersion.V195;
|
||||
} else if (versionCode >= CODE_20_0 && versionCode < CODE_21_0) {
|
||||
if (versionCode >= CODE_20_0 && versionCode < CODE_21_0) {
|
||||
return ScarAdapterVersion.V20;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package com.unity3d.services.ads.gmascar.finder;
|
||||
|
||||
public enum ScarAdapterVersion {
|
||||
V192,
|
||||
V195,
|
||||
V20,
|
||||
V21,
|
||||
NA
|
||||
|
|
|
@ -15,14 +15,16 @@ import org.json.JSONObject;
|
|||
public class BiddingSignalsHandler implements ISignalCollectionListener {
|
||||
|
||||
private final IBiddingSignalsListener listener;
|
||||
private final boolean isBannerEnabled;
|
||||
|
||||
/**
|
||||
* Constructor that initializes the handler with the passed listener.
|
||||
*
|
||||
* @param listener {@link IBiddingSignalsListener} implementation to notify sender.
|
||||
*/
|
||||
public BiddingSignalsHandler(IBiddingSignalsListener listener) {
|
||||
public BiddingSignalsHandler(boolean isBannerEnabled, IBiddingSignalsListener listener) {
|
||||
this.listener = listener;
|
||||
this.isBannerEnabled = isBannerEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,6 +41,14 @@ public class BiddingSignalsHandler implements ISignalCollectionListener {
|
|||
private BiddingSignals getSignals(String signalsMap) {
|
||||
try {
|
||||
JSONObject signalsJson = new JSONObject(signalsMap);
|
||||
|
||||
if (isBannerEnabled) {
|
||||
return new BiddingSignals(
|
||||
getSignalFromJson(signalsJson, SignalsCollectorBase.SCAR_RV_SIGNAL),
|
||||
getSignalFromJson(signalsJson, SignalsCollectorBase.SCAR_INT_SIGNAL),
|
||||
getSignalFromJson(signalsJson, SignalsCollectorBase.SCAR_BAN_SIGNAL)
|
||||
);
|
||||
}
|
||||
return new BiddingSignals(
|
||||
getSignalFromJson(signalsJson, SignalsCollectorBase.SCAR_RV_SIGNAL),
|
||||
getSignalFromJson(signalsJson, SignalsCollectorBase.SCAR_INT_SIGNAL)
|
||||
|
|
|
@ -46,11 +46,6 @@ public abstract class ScarAdHandlerBase implements IScarAdListenerWrapper {
|
|||
_gmaEventSender.send(GMAEvent.AD_CLICKED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdSkipped() {
|
||||
_gmaEventSender.send(GMAEvent.AD_SKIPPED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
_gmaEventSender.send(GMAEvent.AD_CLOSED);
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package com.unity3d.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IScarBannerAdListenerWrapper;
|
||||
import com.unity3d.services.banners.BannerViewCache;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
public class ScarBannerAdHandler implements IScarBannerAdListenerWrapper {
|
||||
|
||||
private String _operationId;
|
||||
|
||||
public ScarBannerAdHandler(String operationId) {
|
||||
_operationId = operationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
BannerViewCache.getInstance().addScarContainer(_operationId);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_LOADED, _operationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(int errorCode, String errorString) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_LOAD_FAILED, _operationId, errorCode, errorString);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdOpened() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_OPENED, _operationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClicked() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_CLICKED, _operationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
// Code to be executed when the user is about to return to the app after tapping on an ad.
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_CLOSED, _operationId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdImpression() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.BANNER, BannerBridge.BannerEvent.SCAR_BANNER_IMPRESSION, _operationId);
|
||||
}
|
||||
}
|
|
@ -17,10 +17,15 @@ public class ScarInterstitialAdHandler extends ScarAdHandlerBase implements ISca
|
|||
_gmaEventSender.send(GMAEvent.INTERSTITIAL_SHOW_ERROR, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId(), errorString, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdSkipped() {
|
||||
_gmaEventSender.send(GMAEvent.AD_SKIPPED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
if (!_eventSubject.eventQueueIsEmpty()) {
|
||||
super.onAdSkipped();
|
||||
onAdSkipped();
|
||||
}
|
||||
super.onAdClosed();
|
||||
}
|
||||
|
|
|
@ -25,10 +25,15 @@ public class ScarRewardedAdHandler extends ScarAdHandlerBase implements IScarRew
|
|||
_gmaEventSender.send(GMAEvent.AD_EARNED_REWARD);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdSkipped() {
|
||||
_gmaEventSender.send(GMAEvent.AD_SKIPPED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
if (!_hasEarnedReward) {
|
||||
super.onAdSkipped();
|
||||
onAdSkipped();
|
||||
}
|
||||
super.onAdClosed();
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ import com.unity3d.services.ads.gmascar.utils.ScarRequestHandler;
|
|||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.ScarMetric;
|
||||
|
||||
import java.util.UUID;
|
||||
|
@ -25,16 +24,17 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
private final IUnityAdsTokenListener unityAdsTokenListener;
|
||||
private final ScarRequestHandler _scarRequestHandler;
|
||||
private final boolean _isAsyncTokenCall;
|
||||
|
||||
private final boolean _isBannerEnabled;
|
||||
|
||||
private final AtomicReference<BiddingSignals> signals = new AtomicReference<>();
|
||||
|
||||
public BiddingBaseManager(IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
this(unityAdsTokenListener, new ScarRequestHandler());
|
||||
public BiddingBaseManager(boolean isBannerEnabled, IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
this(isBannerEnabled, unityAdsTokenListener, new ScarRequestHandler());
|
||||
}
|
||||
|
||||
public BiddingBaseManager(IUnityAdsTokenListener unityAdsTokenListener, ScarRequestHandler requestSender) {
|
||||
public BiddingBaseManager(boolean isBannerEnabled, IUnityAdsTokenListener unityAdsTokenListener, ScarRequestHandler requestSender) {
|
||||
this.tokenIdentifier = UUID.randomUUID().toString();
|
||||
this._isBannerEnabled = isBannerEnabled;
|
||||
this.unityAdsTokenListener = unityAdsTokenListener;
|
||||
this._isAsyncTokenCall = unityAdsTokenListener != null;
|
||||
this._scarRequestHandler = requestSender;
|
||||
|
@ -42,8 +42,6 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
|
||||
public abstract void start();
|
||||
|
||||
public abstract void onUnityTokenSuccessfullyFetched();
|
||||
|
||||
@Override
|
||||
public String getTokenIdentifier() {
|
||||
return tokenIdentifier;
|
||||
|
@ -53,7 +51,7 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
public String getFormattedToken(String unityToken) {
|
||||
if (unityToken == null || unityToken.isEmpty()) return null;
|
||||
String tokenIdentifier = getTokenIdentifier();
|
||||
if (tokenIdentifier == null || (tokenIdentifier != null && tokenIdentifier.isEmpty())) return unityToken;
|
||||
if (tokenIdentifier == null || tokenIdentifier.isEmpty()) return unityToken;
|
||||
else return String.format(TOKEN_WITH_SCAR_FORMAT, tokenIdentifier, unityToken);
|
||||
}
|
||||
|
||||
|
@ -62,10 +60,6 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
if (unityAdsTokenListener != null) {
|
||||
wrapCustomerListener(() -> unityAdsTokenListener.onUnityAdsTokenReady(token));
|
||||
}
|
||||
|
||||
if (token != null && !token.isEmpty()) {
|
||||
onUnityTokenSuccessfullyFetched();
|
||||
}
|
||||
}
|
||||
|
||||
public void permitUpload() {
|
||||
|
@ -80,23 +74,18 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
public void fetchSignals() {
|
||||
getMetricSender().sendMetric(ScarMetric.hbSignalsFetchStart(_isAsyncTokenCall));
|
||||
|
||||
new Thread(new Runnable() {
|
||||
new Thread(() -> GMA.getInstance().getSCARBiddingSignals(this._isBannerEnabled, new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void run() {
|
||||
GMA.getInstance().getSCARBiddingSignals(new IBiddingSignalsListener() {
|
||||
@Override
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
BiddingBaseManager.this.onSignalsReady(signals);
|
||||
sendFetchResult("");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalsFailure(String msg) {
|
||||
sendFetchResult(msg);
|
||||
}
|
||||
});
|
||||
public void onSignalsReady(BiddingSignals signals) {
|
||||
BiddingBaseManager.this.onSignalsReady(signals);
|
||||
sendFetchResult("");
|
||||
}
|
||||
}).start();
|
||||
|
||||
@Override
|
||||
public void onSignalsFailure(String msg) {
|
||||
sendFetchResult(msg);
|
||||
}
|
||||
})).start();
|
||||
}
|
||||
|
||||
public void sendFetchResult(String errorMsg) {
|
||||
|
@ -129,17 +118,14 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
return;
|
||||
}
|
||||
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
// Since there are potential side effects of file read in the
|
||||
// getCurrentConfiguration call, we don't want this to be called in the constructor.
|
||||
_scarRequestHandler.makeUploadRequest(tokenIdentifier, signals, new ConfigurationReader().getCurrentConfiguration().getScarBiddingUrl());
|
||||
getMetricSender().sendMetric(ScarMetric.hbSignalsUploadSuccess(_isAsyncTokenCall));
|
||||
} catch (Exception e) {
|
||||
getMetricSender().sendMetric(ScarMetric.hbSignalsUploadFailure(_isAsyncTokenCall, e.getLocalizedMessage()));
|
||||
}
|
||||
new Thread(() -> {
|
||||
try {
|
||||
// Since there are potential side effects of file read in the
|
||||
// getCurrentConfiguration call, we don't want this to be called in the constructor.
|
||||
_scarRequestHandler.makeUploadRequest(tokenIdentifier, signals, new ConfigurationReader().getCurrentConfiguration().getScarBiddingUrl());
|
||||
getMetricSender().sendMetric(ScarMetric.hbSignalsUploadSuccess(_isAsyncTokenCall));
|
||||
} catch (Exception e) {
|
||||
getMetricSender().sendMetric(ScarMetric.hbSignalsUploadFailure(_isAsyncTokenCall, e.getLocalizedMessage()));
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import com.unity3d.ads.IUnityAdsTokenListener;
|
|||
public class BiddingDisabledManager extends BiddingBaseManager {
|
||||
|
||||
public BiddingDisabledManager(IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
super(unityAdsTokenListener);
|
||||
super(false, unityAdsTokenListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -18,9 +18,4 @@ public class BiddingDisabledManager extends BiddingBaseManager {
|
|||
public void start() {
|
||||
// SCAR bidding signals collection should be blocked.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
// SCAR bidding signals collection should be blocked.
|
||||
}
|
||||
}
|
||||
}
|
|
@ -4,8 +4,8 @@ import com.unity3d.ads.IUnityAdsTokenListener;
|
|||
|
||||
public class BiddingEagerManager extends BiddingBaseManager {
|
||||
|
||||
public BiddingEagerManager(IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
super(unityAdsTokenListener);
|
||||
public BiddingEagerManager(boolean isBannerEnabled, IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
super(isBannerEnabled, unityAdsTokenListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -13,12 +13,4 @@ public class BiddingEagerManager extends BiddingBaseManager {
|
|||
permitSignalsUpload();
|
||||
fetchSignals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
// Not relevant.
|
||||
//
|
||||
// Signals upload will be start once scar signals are ready regardless of unityToken
|
||||
// validity.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
package com.unity3d.services.ads.gmascar.managers;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
|
||||
public class BiddingLazyManager extends BiddingBaseManager {
|
||||
|
||||
public BiddingLazyManager(IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
super(unityAdsTokenListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
// Not relevant.
|
||||
//
|
||||
// Signals fetch will be start once valid unity token is fetched.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
permitSignalsUpload();
|
||||
fetchSignals();
|
||||
}
|
||||
}
|
|
@ -21,40 +21,10 @@ public class BiddingManagerFactory {
|
|||
public BiddingBaseManager createManager(IUnityAdsTokenListener unityAdsTokenListener,
|
||||
IExperiments experiments) {
|
||||
if (GMA.getInstance().hasSCARBiddingSupport()) {
|
||||
return getExperiment(unityAdsTokenListener, experiments);
|
||||
boolean isBannerEnabled = experiments != null && experiments.isScarBannerHbEnabled();
|
||||
return new BiddingEagerManager(isBannerEnabled, unityAdsTokenListener);
|
||||
}
|
||||
|
||||
return new BiddingDisabledManager(unityAdsTokenListener);
|
||||
}
|
||||
|
||||
private BiddingBaseManager getExperiment(IUnityAdsTokenListener unityAdsTokenListener,
|
||||
IExperiments experiments) {
|
||||
if (experiments == null || experiments.getScarBiddingManager() == null) {
|
||||
return new BiddingDisabledManager(unityAdsTokenListener);
|
||||
}
|
||||
|
||||
String biddingManager = experiments.getScarBiddingManager();
|
||||
SCARBiddingManagerType biddingManagerType = SCARBiddingManagerType.fromName(biddingManager);
|
||||
|
||||
/*
|
||||
If unityAdsTokenListener is null it is a synchronous getToken call and we should use
|
||||
the EAGER bidding manager if part of any of the enabled experiment types since we do not
|
||||
have to listen for a token fetch result
|
||||
*/
|
||||
if (unityAdsTokenListener == null && biddingManagerType != SCARBiddingManagerType.DISABLED) {
|
||||
return new BiddingEagerManager(null);
|
||||
}
|
||||
|
||||
switch (biddingManagerType) {
|
||||
case EAGER:
|
||||
return new BiddingEagerManager(unityAdsTokenListener);
|
||||
case LAZY:
|
||||
return new BiddingLazyManager(unityAdsTokenListener);
|
||||
case HYBRID:
|
||||
return new BiddingOnDemandManager(unityAdsTokenListener);
|
||||
case DISABLED:
|
||||
default:
|
||||
return new BiddingDisabledManager(unityAdsTokenListener);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
package com.unity3d.services.ads.gmascar.managers;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
|
||||
public class BiddingOnDemandManager extends BiddingBaseManager {
|
||||
|
||||
public BiddingOnDemandManager(IUnityAdsTokenListener unityAdsTokenListener) {
|
||||
super(unityAdsTokenListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() {
|
||||
fetchSignals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityTokenSuccessfullyFetched() {
|
||||
permitSignalsUpload();
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
package com.unity3d.services.ads.gmascar.managers;
|
||||
|
||||
public enum SCARBiddingManagerType {
|
||||
DISABLED(Constants.DIS),
|
||||
EAGER(Constants.EAG),
|
||||
LAZY(Constants.LAZ),
|
||||
HYBRID(Constants.HYB);
|
||||
|
||||
private final String name;
|
||||
|
||||
SCARBiddingManagerType(final String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public static SCARBiddingManagerType fromName(final String name) {
|
||||
switch(name) {
|
||||
case Constants.EAG:
|
||||
return EAGER;
|
||||
case Constants.LAZ:
|
||||
return LAZY;
|
||||
case Constants.HYB:
|
||||
return HYBRID;
|
||||
case Constants.DIS:
|
||||
default:
|
||||
return DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Constants {
|
||||
private static final String LAZ = "laz";
|
||||
private static final String EAG = "eag";
|
||||
private static final String HYB = "hyb";
|
||||
private static final String DIS = "dis";
|
||||
}
|
||||
}
|
|
@ -7,8 +7,7 @@ import org.jetbrains.annotations.Nullable;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.unity3d.services.ads.gmascar.utils.ScarConstants.IN_SIGNAL_KEY;
|
||||
import static com.unity3d.services.ads.gmascar.utils.ScarConstants.RV_SIGNAL_KEY;
|
||||
import static com.unity3d.services.ads.gmascar.utils.ScarConstants.*;
|
||||
|
||||
/**
|
||||
* Data structure for GMA bidding signals.
|
||||
|
@ -17,6 +16,7 @@ public class BiddingSignals {
|
|||
|
||||
private final String rvSignal;
|
||||
private final String interstitialSignal;
|
||||
private final String bannerSignal;
|
||||
|
||||
/**
|
||||
* Constructor that initialized the object with passed GMA bidding signals.
|
||||
|
@ -24,9 +24,16 @@ public class BiddingSignals {
|
|||
* @param rvSignal rewarded video GMA Scar bidding signal.
|
||||
* @param interstitialSignal interstitial GMA Scar bidding signal.
|
||||
*/
|
||||
public BiddingSignals(String rvSignal, String interstitialSignal, String bannerSignal) {
|
||||
this.rvSignal = rvSignal;
|
||||
this.interstitialSignal = interstitialSignal;
|
||||
this.bannerSignal = bannerSignal;
|
||||
}
|
||||
|
||||
public BiddingSignals(String rvSignal, String interstitialSignal) {
|
||||
this.rvSignal = rvSignal;
|
||||
this.interstitialSignal = interstitialSignal;
|
||||
this.bannerSignal = "";
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -50,12 +57,22 @@ public class BiddingSignals {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks if both bidding signals are empty in which case they should not be uploaded
|
||||
* Getter for banner GMA SCAR signal.
|
||||
*
|
||||
* @return true if both signals are empty, false otherwise
|
||||
* @return banner bidding signal
|
||||
*/
|
||||
@Nullable
|
||||
public String getBannerSignal() {
|
||||
return bannerSignal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if all bidding signals are empty in which case they should not be uploaded
|
||||
*
|
||||
* @return true if all signals are empty, false otherwise
|
||||
*/
|
||||
public boolean isEmpty () {
|
||||
return TextUtils.isEmpty(getRvSignal()) && TextUtils.isEmpty(getInterstitialSignal());
|
||||
return TextUtils.isEmpty(getRvSignal()) && TextUtils.isEmpty(getInterstitialSignal()) && TextUtils.isEmpty(getBannerSignal());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -74,6 +91,10 @@ public class BiddingSignals {
|
|||
signalsMap.put(IN_SIGNAL_KEY, getInterstitialSignal());
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(getBannerSignal())) {
|
||||
signalsMap.put(BN_SIGNAL_KEY, getBannerSignal());
|
||||
}
|
||||
|
||||
return signalsMap;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@ public class ScarConstants {
|
|||
public static final String TOKEN_ID_KEY = "tid";
|
||||
public static final String RV_SIGNAL_KEY = "rv";
|
||||
public static final String IN_SIGNAL_KEY = "in";
|
||||
public static final String BN_SIGNAL_KEY = "bn";
|
||||
|
||||
public static final String SCAR_TOKEN_IDENTIFIER_KEY = "scarId";
|
||||
public static final String TOKEN_WITH_SCAR_FORMAT = "%s:%s";
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
enum class MeasurementsErrors {
|
||||
ERROR_AD_SERVICES_DISABLED,
|
||||
ERROR_EXTENSION_BELOW_4,
|
||||
ERROR_API_BELOW_33,
|
||||
ERROR_MANAGER_NULL,
|
||||
ERROR_EXCEPTION,
|
||||
ERROR_AD_UNIT_NULL,
|
||||
ERROR_LAYOUT_NULL,
|
||||
ERROR_LAST_INPUT_EVENT_NULL,
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
enum class MeasurementsEvents {
|
||||
NOT_AVAILABLE,
|
||||
AVAILABLE,
|
||||
VIEW_SUCCESSFUL,
|
||||
VIEW_ERROR,
|
||||
CLICK_SUCCESSFUL,
|
||||
CLICK_ERROR,
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsReceiver(
|
||||
private val eventSender: IEventSender,
|
||||
private val successEvent: MeasurementsEvents,
|
||||
private val errorEvent: MeasurementsEvents,
|
||||
): OutcomeReceiver<Any, Exception> {
|
||||
override fun onResult(p0: Any) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, successEvent)
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, errorEvent, error.toString())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.adservices.AdServicesState
|
||||
import android.adservices.measurement.MeasurementManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.OutcomeReceiver
|
||||
import android.os.ext.SdkExtensions
|
||||
import android.view.InputEvent
|
||||
import com.unity3d.services.core.device.Device
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import kotlinx.coroutines.asExecutor
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsService(context: Context, private val dispatchers: ISDKDispatchers, private val eventSender: IEventSender) {
|
||||
private val measurementManager: MeasurementManager? = getMeasurementManager(context)
|
||||
|
||||
fun checkAvailability() {
|
||||
if (Device.getApiLevel() < 33) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_API_BELOW_33)
|
||||
return
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_EXTENSION_BELOW_4)
|
||||
return
|
||||
}
|
||||
|
||||
if (measurementManager == null) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_MANAGER_NULL)
|
||||
return
|
||||
}
|
||||
|
||||
if (!AdServicesState.isAdServicesStateEnabled()) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_AD_SERVICES_DISABLED)
|
||||
return
|
||||
}
|
||||
|
||||
measurementManager.getMeasurementApiStatus(dispatchers.default.asExecutor(), MeasurementsStatusReceiver(eventSender))
|
||||
}
|
||||
|
||||
fun registerView(url: String) {
|
||||
measurementManager?.registerSource(
|
||||
Uri.parse(url),
|
||||
null,
|
||||
dispatchers.default.asExecutor(),
|
||||
MeasurementsReceiver(eventSender, MeasurementsEvents.VIEW_SUCCESSFUL, MeasurementsEvents.VIEW_ERROR)
|
||||
)
|
||||
}
|
||||
|
||||
fun registerClick(url: String, inputEvent: InputEvent) {
|
||||
measurementManager?.registerSource(
|
||||
Uri.parse(url),
|
||||
inputEvent,
|
||||
dispatchers.default.asExecutor(),
|
||||
MeasurementsReceiver(eventSender, MeasurementsEvents.CLICK_SUCCESSFUL, MeasurementsEvents.CLICK_ERROR)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMeasurementManager(context: Context): MeasurementManager? {
|
||||
// accessing MeasurementManager without API level and extension version checks can crash old Android devices
|
||||
// also accessing SdkExtensions below API level 30 causes exception so check API level first
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return null
|
||||
}
|
||||
|
||||
return context.getSystemService(MeasurementManager::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsStatusReceiver(private val eventSender: IEventSender) : OutcomeReceiver<Int, Exception> {
|
||||
override fun onResult(status: Int) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.AVAILABLE, status)
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_EXCEPTION, error.toString())
|
||||
}
|
||||
}
|
|
@ -1,13 +1,9 @@
|
|||
package com.unity3d.services.ads.operation.load;
|
||||
|
||||
import com.unity3d.services.banners.BannerViewCache;
|
||||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.configuration.InitializationNotificationCenter;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -20,7 +16,7 @@ public class LoadBannerModule extends BaseLoadModule {
|
|||
if (_instance == null) {
|
||||
LoadBannerModule loadModule = new LoadBannerModule(Utilities.getService(SDKMetricsSender.class));
|
||||
LoadModuleDecoratorInitializationBuffer bufferedLoadModule = new LoadModuleDecoratorInitializationBuffer(loadModule, InitializationNotificationCenter.getInstance());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ConfigurationReader());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ExperimentsReader());
|
||||
_instance = timedLoadModule;
|
||||
}
|
||||
return _instance;
|
||||
|
@ -37,20 +33,4 @@ public class LoadBannerModule extends BaseLoadModule {
|
|||
parameters.put("height", ((LoadBannerOperationState) state).getSize().getHeight());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUnityAdsAdLoaded(String operationId) {
|
||||
final ILoadOperation loadOperation = get(operationId);
|
||||
if (loadOperation == null || loadOperation.getLoadOperationState() == null) return;
|
||||
final LoadOperationState state = loadOperation.getLoadOperationState();
|
||||
if (state instanceof LoadBannerOperationState) {
|
||||
String bannerAdId = state.getId();
|
||||
UnityBannerSize size = ((LoadBannerOperationState) state).getSize();
|
||||
boolean successfullyLoaded = BannerViewCache.getInstance().loadWebPlayer(bannerAdId, size);
|
||||
if (successfullyLoaded) {
|
||||
BannerBridge.didLoad(operationId);
|
||||
}
|
||||
super.onUnityAdsAdLoaded(operationId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,11 +2,13 @@ package com.unity3d.services.ads.operation.load;
|
|||
|
||||
import com.unity3d.ads.IUnityAdsLoadListener;
|
||||
import com.unity3d.ads.UnityAdsLoadOptions;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
|
||||
public class LoadBannerOperationState extends LoadOperationState {
|
||||
private UnityBannerSize _size;
|
||||
private ScarAdMetadata _scarAdMetadata;
|
||||
|
||||
public LoadBannerOperationState(String placementId, String bannerAdId, UnityBannerSize size, IUnityAdsLoadListener listener, UnityAdsLoadOptions loadOptions, Configuration configuration) {
|
||||
super(placementId, listener, loadOptions, configuration);
|
||||
|
@ -21,4 +23,16 @@ public class LoadBannerOperationState extends LoadOperationState {
|
|||
public void setSize(UnityBannerSize size) {
|
||||
_size = size;
|
||||
}
|
||||
|
||||
public void setScarAdMetadata(ScarAdMetadata scarAdMetadata) {
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
}
|
||||
|
||||
public ScarAdMetadata getScarAdMetadata() {
|
||||
return _scarAdMetadata;
|
||||
}
|
||||
|
||||
public boolean isScarAd() {
|
||||
return _scarAdMetadata != null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,11 @@
|
|||
package com.unity3d.services.ads.operation.load;
|
||||
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.configuration.InitializationNotificationCenter;
|
||||
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
public class LoadModule extends BaseLoadModule {
|
||||
|
@ -18,7 +16,7 @@ public class LoadModule extends BaseLoadModule {
|
|||
if (_instance == null) {
|
||||
LoadModule loadModule = new LoadModule(Utilities.getService(SDKMetricsSender.class));
|
||||
LoadModuleDecoratorInitializationBuffer bufferedLoadModule = new LoadModuleDecoratorInitializationBuffer(loadModule, InitializationNotificationCenter.getInstance());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ConfigurationReader());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ExperimentsReader());
|
||||
_instance = timedLoadModule;
|
||||
}
|
||||
return _instance;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.load;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.timer.BaseTimer;
|
||||
|
@ -13,15 +13,20 @@ import java.util.concurrent.Executors;
|
|||
public class LoadModuleDecoratorTimeout extends LoadModuleDecorator {
|
||||
private static final String errorMsgTimeoutLoading = "[UnityAds] Timeout while loading ";
|
||||
|
||||
public LoadModuleDecoratorTimeout(ILoadModule loadModule, ConfigurationReader configurationReader) {
|
||||
private final ExperimentsReader _experimentsReader;
|
||||
|
||||
public LoadModuleDecoratorTimeout(ILoadModule loadModule, ExperimentsReader experimentsReader) {
|
||||
super(loadModule);
|
||||
this._experimentsReader = experimentsReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeAdOperation(IWebViewBridgeInvoker webViewBridgeInvoker, LoadOperationState state) {
|
||||
getMetricSender().sendMetricWithInitState(AdOperationMetric.newAdLoadStart());
|
||||
state.start();
|
||||
startLoadTimeout(state);
|
||||
if (!_experimentsReader.getCurrentlyActiveExperiments().isNativeLoadTimeoutDisabled()) {
|
||||
startLoadTimeout(state);
|
||||
}
|
||||
super.executeAdOperation(webViewBridgeInvoker, state);
|
||||
}
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ import android.view.WindowManager;
|
|||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.ads.operation.AdModule;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.device.Device;
|
||||
import com.unity3d.services.core.device.reader.HdrInfoReader;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
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.IWebViewBridgeInvocationCallback;
|
||||
|
@ -34,7 +34,7 @@ public class ShowModule extends AdModule<IShowOperation, ShowOperationState> imp
|
|||
|
||||
public static IShowModule getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ShowModuleDecoratorTimeout(new ShowModule(Utilities.getService(SDKMetricsSender.class)), new ConfigurationReader());
|
||||
instance = new ShowModuleDecoratorTimeout(new ShowModule(Utilities.getService(SDKMetricsSender.class)), new ExperimentsReader());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ public class ShowModule extends AdModule<IShowOperation, ShowOperationState> imp
|
|||
|
||||
set(showOperation);
|
||||
showOperation.invoke(state.configuration.getWebViewBridgeTimeout(), parameters);
|
||||
HdrInfoReader.getInstance().captureHDRCapabilityMetrics(activity, new ExperimentsReader());
|
||||
}
|
||||
|
||||
public void onUnityAdsShowFailure(String id, UnityAds.UnityAdsShowError error, String message) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.show;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.timer.BaseTimer;
|
||||
|
@ -13,15 +13,20 @@ import java.util.concurrent.Executors;
|
|||
public class ShowModuleDecoratorTimeout extends ShowModuleDecorator {
|
||||
private static final String errorMsgTimeout = "[UnityAds] Timeout while trying to show ";
|
||||
|
||||
public ShowModuleDecoratorTimeout(IShowModule showModule, ConfigurationReader configurationReader) {
|
||||
private final ExperimentsReader _experimentsReader;
|
||||
|
||||
public ShowModuleDecoratorTimeout(IShowModule showModule, ExperimentsReader experimentsReader) {
|
||||
super(showModule);
|
||||
this._experimentsReader = experimentsReader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeAdOperation(IWebViewBridgeInvoker webViewBridgeInvoker, ShowOperationState state) {
|
||||
getMetricSender().sendMetricWithInitState(AdOperationMetric.newAdShowStart());
|
||||
state.start();
|
||||
startShowTimeout(state);
|
||||
if (!_experimentsReader.getCurrentlyActiveExperiments().isNativeShowTimeoutDisabled()) {
|
||||
startShowTimeout(state);
|
||||
}
|
||||
super.executeAdOperation(webViewBridgeInvoker, state);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsErrors {
|
||||
ERROR_EXCEPTION,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsEvents {
|
||||
NOT_AVAILABLE,
|
||||
TOPICS_AVAILABLE,
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
import android.adservices.topics.GetTopicsResponse
|
||||
import android.adservices.topics.Topic
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class TopicsReceiver(private val eventSender: IEventSender) : OutcomeReceiver<GetTopicsResponse, Exception> {
|
||||
override fun onResult(result: GetTopicsResponse) {
|
||||
val resultArray = JSONArray()
|
||||
result.topics.forEach {
|
||||
resultArray.put(formatTopic(it))
|
||||
}
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.TOPICS_AVAILABLE, resultArray.toString())
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
DeviceLog.debug("GetTopics exception: $error")
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.NOT_AVAILABLE, TopicsErrors.ERROR_EXCEPTION, error.toString())
|
||||
}
|
||||
|
||||
fun formatTopic(topic: Topic): JSONObject {
|
||||
val resultObject = JSONObject()
|
||||
resultObject.put("taxonomyVersion", topic.taxonomyVersion)
|
||||
resultObject.put("modelVersion", topic.modelVersion)
|
||||
resultObject.put("topicId", topic.topicId)
|
||||
return resultObject
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
import android.adservices.AdServicesState
|
||||
import android.adservices.topics.GetTopicsRequest
|
||||
import android.adservices.topics.TopicsManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.ext.SdkExtensions
|
||||
import com.unity3d.services.core.device.Device
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import kotlinx.coroutines.asExecutor
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class TopicsService(context: Context, private val dispatchers: ISDKDispatchers, private val eventSender: IEventSender) {
|
||||
private val topicsManager: TopicsManager? = getTopicsManager(context)
|
||||
|
||||
fun checkAvailability(): TopicsStatus {
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return TopicsStatus.ERROR_API_BELOW_33
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return TopicsStatus.ERROR_EXTENSION_BELOW_4
|
||||
}
|
||||
|
||||
if (topicsManager == null) {
|
||||
return TopicsStatus.ERROR_TOPICSMANAGER_NULL
|
||||
}
|
||||
|
||||
if (!AdServicesState.isAdServicesStateEnabled()) {
|
||||
return TopicsStatus.ERROR_AD_SERVICES_DISABLED
|
||||
}
|
||||
|
||||
return TopicsStatus.TOPICS_AVAILABLE
|
||||
}
|
||||
|
||||
fun getTopics(adsSdkName: String, shouldRecordObservation: Boolean) {
|
||||
val callback = TopicsReceiver(eventSender)
|
||||
val topicsRequest = GetTopicsRequest.Builder().setAdsSdkName(adsSdkName).setShouldRecordObservation(shouldRecordObservation).build()
|
||||
try {
|
||||
topicsManager?.getTopics(topicsRequest, dispatchers.default.asExecutor(), callback)
|
||||
} catch (error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.NOT_AVAILABLE, TopicsErrors.ERROR_EXCEPTION, error.toString())
|
||||
DeviceLog.debug("Failed to get topics with error: $error")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTopicsManager(context: Context): TopicsManager? {
|
||||
// accessing TopicsManager without API level and extension version checks can crash old Android devices
|
||||
// also accessing SdkExtensions below API level 30 causes exception so check API level first
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return null
|
||||
}
|
||||
|
||||
return context.getSystemService(TopicsManager::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsStatus {
|
||||
TOPICS_AVAILABLE,
|
||||
ERROR_TOPICSMANAGER_NULL,
|
||||
ERROR_API_BELOW_33,
|
||||
ERROR_EXTENSION_BELOW_4,
|
||||
ERROR_AD_SERVICES_DISABLED,
|
||||
}
|
|
@ -11,6 +11,18 @@ public class BannerErrorInfo {
|
|||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
public UnityAds.UnityAdsLoadError toLoadError() {
|
||||
switch (errorCode) {
|
||||
case NATIVE_ERROR:
|
||||
return UnityAds.UnityAdsLoadError.INVALID_ARGUMENT;
|
||||
case NO_FILL:
|
||||
return UnityAds.UnityAdsLoadError.NO_FILL;
|
||||
case WEBVIEW_ERROR:
|
||||
return UnityAds.UnityAdsLoadError.INTERNAL_ERROR;
|
||||
}
|
||||
return UnityAds.UnityAdsLoadError.INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
public static BannerErrorInfo fromLoadError(UnityAds.UnityAdsLoadError error, String message) {
|
||||
switch (error) {
|
||||
case INITIALIZE_FAILED:
|
||||
|
@ -19,6 +31,8 @@ public class BannerErrorInfo {
|
|||
return new BannerErrorInfo(message, BannerErrorCode.NATIVE_ERROR);
|
||||
case INTERNAL_ERROR:
|
||||
return new BannerErrorInfo(message, BannerErrorCode.WEBVIEW_ERROR);
|
||||
case NO_FILL:
|
||||
return new BannerErrorInfo(message, BannerErrorCode.NO_FILL);
|
||||
default:
|
||||
return new BannerErrorInfo(message, BannerErrorCode.UNKNOWN);
|
||||
}
|
||||
|
|
|
@ -7,9 +7,13 @@ import android.view.ViewParent;
|
|||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.unity3d.ads.UnityAdsLoadOptions;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.services.ads.gmascar.GMA;
|
||||
import com.unity3d.services.ads.gmascar.GMAScarAdapterBridge;
|
||||
import com.unity3d.services.ads.webplayer.WebPlayerSettingsCache;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.banners.view.BannerWebPlayerContainer;
|
||||
import com.unity3d.services.banners.view.ScarBannerContainer;
|
||||
import com.unity3d.services.core.configuration.ErrorState;
|
||||
import com.unity3d.services.core.configuration.IInitializationListener;
|
||||
import com.unity3d.services.core.configuration.InitializationNotificationCenter;
|
||||
|
@ -29,7 +33,9 @@ public class BannerView extends RelativeLayout {
|
|||
private UnityBannerSize size;
|
||||
private IListener listener;
|
||||
private BannerWebPlayerContainer bannerWebPlayerContainer;
|
||||
private ScarBannerContainer scarBannerContainer;
|
||||
private IInitializationListener initializationListener;
|
||||
private final GMAScarAdapterBridge gmaScarAdapterBridge = GMA.getInstance().getBridge();
|
||||
|
||||
// Public
|
||||
|
||||
|
@ -95,6 +101,10 @@ public class BannerView extends RelativeLayout {
|
|||
bannerWebPlayerContainer.destroy();
|
||||
}
|
||||
|
||||
if (scarBannerContainer != null) {
|
||||
scarBannerContainer.destroy();
|
||||
}
|
||||
|
||||
// Log the banner was destroyed
|
||||
DeviceLog.info("Banner [" + this.placementId + "] was destroyed");
|
||||
|
||||
|
@ -139,6 +149,15 @@ public class BannerView extends RelativeLayout {
|
|||
|
||||
// Module Private
|
||||
|
||||
void loadScarPlayer(String operationId, ScarAdMetadata scarAdMetadata, UnityBannerSize size) {
|
||||
gmaScarAdapterBridge.loadBanner(getContext(), this, operationId, scarAdMetadata, size);
|
||||
}
|
||||
|
||||
public void addScarContainer() {
|
||||
scarBannerContainer = new ScarBannerContainer(getContext(), viewId);
|
||||
Utilities.runOnUiThread(() -> addView(scarBannerContainer));
|
||||
}
|
||||
|
||||
void loadWebPlayer(final UnityBannerSize unityBannerSize) {
|
||||
final BannerView self = this;
|
||||
Utilities.runOnUiThread(new Runnable() {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package com.unity3d.services.banners;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.ads.operation.load.ILoadModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerModule;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.services.ads.operation.load.*;
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -44,6 +45,37 @@ public class BannerViewCache {
|
|||
_bannerViews.remove(bannerAdId);
|
||||
}
|
||||
|
||||
public synchronized void loadBanner(LoadBannerOperationState state) {
|
||||
String bannerAdId = state.getId();
|
||||
UnityBannerSize size = state.getSize();
|
||||
|
||||
if (state.isScarAd()) {
|
||||
ScarAdMetadata scarAdMetadata = state.getScarAdMetadata();
|
||||
loadScarPlayer(bannerAdId, scarAdMetadata, size);
|
||||
} else {
|
||||
boolean successfullyLoaded = loadWebPlayer(bannerAdId, size);
|
||||
if (successfullyLoaded) {
|
||||
BannerBridge.didLoad(bannerAdId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void loadScarPlayer(String bannerAdId, ScarAdMetadata scarAdMetadata, UnityBannerSize size) {
|
||||
BannerView bannerView = this.getBannerView(bannerAdId);
|
||||
|
||||
if (bannerView != null) {
|
||||
bannerView.loadScarPlayer(bannerAdId, scarAdMetadata, size);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void addScarContainer(String bannerAdId) {
|
||||
BannerView bannerView = this.getBannerView(bannerAdId);
|
||||
|
||||
if (bannerView != null) {
|
||||
bannerView.addScarContainer();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized boolean loadWebPlayer(String bannerAdId, UnityBannerSize size) {
|
||||
BannerView bannerView = this.getBannerView(bannerAdId);
|
||||
if (bannerView != null) {
|
||||
|
@ -57,6 +89,8 @@ public class BannerViewCache {
|
|||
public synchronized void triggerBannerLoadEvent(String bannerAdId) {
|
||||
final BannerView bannerView = this.getBannerView(bannerAdId);
|
||||
if (bannerView != null && bannerView.getListener() != null) {
|
||||
LoadBannerModule.getInstance().onUnityAdsAdLoaded(bannerAdId);
|
||||
|
||||
final BannerView.IListener listener = bannerView.getListener();
|
||||
Utilities.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
|
@ -100,7 +134,8 @@ public class BannerViewCache {
|
|||
}
|
||||
|
||||
public synchronized void triggerBannerErrorEvent(String bannerAdId, final BannerErrorInfo bannerErrorInfo) {
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, UnityAds.UnityAdsLoadError.INTERNAL_ERROR, bannerErrorInfo.errorMessage);
|
||||
final UnityAds.UnityAdsLoadError unityAdsLoadError = bannerErrorInfo.toLoadError();
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, unityAdsLoadError, bannerErrorInfo.errorMessage);
|
||||
}
|
||||
|
||||
public synchronized void triggerBannerLeftApplicationEvent(String bannerAdId) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.banners.api;
|
|||
|
||||
import static com.unity3d.ads.UnityAds.UnityAdsLoadError.INTERNAL_ERROR;
|
||||
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.services.ads.operation.load.ILoadOperation;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerOperationState;
|
||||
|
@ -33,11 +34,13 @@ public class Banner {
|
|||
final BannerViewType bannerViewType = BannerViewType.fromString(bannerViewTypeString);
|
||||
switch (bannerViewType) {
|
||||
case WEB_PLAYER:
|
||||
ILoadOperation operationState = LoadBannerModule.getInstance().get(bannerAdId);
|
||||
if (operationState instanceof LoadBannerOperationState) {
|
||||
((LoadBannerOperationState) operationState).setSize(new UnityBannerSize(width, height));
|
||||
final LoadBannerOperationState state = getBannerOperationState(bannerAdId);
|
||||
if (state == null) {
|
||||
break;
|
||||
}
|
||||
LoadBannerModule.getInstance().onUnityAdsAdLoaded(bannerAdId);
|
||||
|
||||
state.setSize(new UnityBannerSize(width, height));
|
||||
BannerViewCache.getInstance().loadBanner(state);
|
||||
break;
|
||||
case UNKNOWN:
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, INTERNAL_ERROR, "Unknown banner type");
|
||||
|
@ -47,6 +50,24 @@ public class Banner {
|
|||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void loadScar(final String bannerAdId, final String placementId, final String queryId, final String adUnitId, final String adString, final Integer width, final Integer height, final WebViewCallback callback) {
|
||||
final LoadBannerOperationState state = getBannerOperationState(bannerAdId);
|
||||
if (state == null) {
|
||||
callback.invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
state.setSize(new UnityBannerSize(width, height));
|
||||
|
||||
ScarAdMetadata scarAdMetadata = new ScarAdMetadata(placementId, queryId, adUnitId, adString, 0);
|
||||
state.setScarAdMetadata(scarAdMetadata);
|
||||
|
||||
BannerViewCache.getInstance().loadBanner(state);
|
||||
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void setRefreshRate(final String placementId, final Integer refreshRate, WebViewCallback callback) {
|
||||
if (placementId != null && refreshRate != null) {
|
||||
|
@ -55,4 +76,20 @@ public class Banner {
|
|||
callback.invoke();
|
||||
}
|
||||
|
||||
private static LoadBannerOperationState getBannerOperationState(String bannerAdId) {
|
||||
ILoadOperation operationState = LoadBannerModule.getInstance().get(bannerAdId);
|
||||
if (operationState == null || operationState.getLoadOperationState() == null) {
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, INTERNAL_ERROR, "No operation found for requested banner");
|
||||
return null;
|
||||
}
|
||||
|
||||
LoadOperationState state = operationState.getLoadOperationState();
|
||||
if (state instanceof LoadBannerOperationState) {
|
||||
return (LoadBannerOperationState) state;
|
||||
}
|
||||
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, INTERNAL_ERROR, "Operation state found is not for banner ad");
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -104,6 +104,20 @@ public class BannerBridge {
|
|||
}
|
||||
}
|
||||
|
||||
public static void didAttachScarBanner(String bannerAdId) {
|
||||
WebViewApp webViewApp = WebViewApp.getCurrentApp();
|
||||
if (webViewApp != null) {
|
||||
webViewApp.sendEvent(WebViewEventCategory.BANNER, BannerEvent.SCAR_BANNER_ATTACHED, bannerAdId);
|
||||
}
|
||||
}
|
||||
|
||||
public static void didDetachScarBanner(String bannerAdId) {
|
||||
WebViewApp webViewApp = WebViewApp.getCurrentApp();
|
||||
if (webViewApp != null) {
|
||||
webViewApp.sendEvent(WebViewEventCategory.BANNER, BannerEvent.SCAR_BANNER_DETACHED, bannerAdId);
|
||||
}
|
||||
}
|
||||
|
||||
public enum BannerEvent {
|
||||
BANNER_VISIBILITY_CHANGED,
|
||||
BANNER_RESIZED,
|
||||
|
@ -112,6 +126,15 @@ public class BannerBridge {
|
|||
BANNER_ATTACHED,
|
||||
BANNER_DETACHED,
|
||||
BANNER_LOAD_PLACEMENT,
|
||||
BANNER_DESTROY_BANNER
|
||||
BANNER_DESTROY_BANNER,
|
||||
// Used for SCAR banners only
|
||||
SCAR_BANNER_LOADED,
|
||||
SCAR_BANNER_LOAD_FAILED,
|
||||
SCAR_BANNER_ATTACHED,
|
||||
SCAR_BANNER_DETACHED,
|
||||
SCAR_BANNER_OPENED,
|
||||
SCAR_BANNER_CLOSED,
|
||||
SCAR_BANNER_IMPRESSION,
|
||||
SCAR_BANNER_CLICKED
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
package com.unity3d.services.banners.view;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewParent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
|
||||
public class ScarBannerContainer extends RelativeLayout {
|
||||
|
||||
private String _bannerAdId;
|
||||
|
||||
public ScarBannerContainer(Context context, String bannerAdId) {
|
||||
super(context);
|
||||
_bannerAdId = bannerAdId;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
final ScarBannerContainer self = this;
|
||||
Utilities.runOnUiThread(() -> {
|
||||
self.removeAllViews();
|
||||
ViewParent parent = self.getParent();
|
||||
if (parent instanceof ViewGroup) {
|
||||
((ViewGroup) parent).removeView(self);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
BannerBridge.didAttachScarBanner(_bannerAdId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
BannerBridge.didDetachScarBanner(_bannerAdId);
|
||||
}
|
||||
}
|
|
@ -53,6 +53,11 @@ public class DeviceInfo {
|
|||
callback.invoke(Device.getApiLevel());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getExtensionVersion (WebViewCallback callback) {
|
||||
callback.invoke(Device.getExtensionVersion());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getOsVersion (WebViewCallback callback) {
|
||||
callback.invoke(Device.getOsVersion());
|
||||
|
@ -521,5 +526,20 @@ public class DeviceInfo {
|
|||
public static void getBuildVersionIncremental(WebViewCallback callback) {
|
||||
callback.invoke(Device.getBuildVersionIncremental());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void hasX264HWDecoder(WebViewCallback callback) {
|
||||
callback.invoke(Device.hasX264Decoder());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void hasX265HWDecoder(WebViewCallback callback) {
|
||||
callback.invoke(Device.hasX265Decoder());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void hasAV1HWDecoder(WebViewCallback callback) {
|
||||
callback.invoke(Device.hasAV1Decoder());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ import java.util.HashMap;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
|
||||
public class Configuration {
|
||||
private String _webViewUrl;
|
||||
|
@ -49,6 +50,7 @@ public class Configuration {
|
|||
private double _metricSampleRate;
|
||||
private long _webViewAppCreateTimeout;
|
||||
private String _scarBiddingUrl;
|
||||
private Boolean _metricsEnabled;
|
||||
|
||||
private String _filteredJsonString;
|
||||
private JSONObject _rawJsonData;
|
||||
|
@ -276,6 +278,7 @@ public class Configuration {
|
|||
_privacyRequestWaitTimeout = configData.optInt("prwto", 3000);
|
||||
_src = configData.optString("src", null);
|
||||
_scarBiddingUrl = configData.optString("scurl", SCAR_PRD_BIDDING_ENDPOINT);
|
||||
_metricsEnabled = _metricSampleRate >= new Random().nextInt(99) + 1;
|
||||
|
||||
IExperiments experiments;
|
||||
if (configData.has("expo")) {
|
||||
|
@ -322,4 +325,8 @@ public class Configuration {
|
|||
return filteredConfig;
|
||||
}
|
||||
|
||||
public Boolean areMetricsEnabledForCurrentSession() {
|
||||
return _metricsEnabled;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.unity3d.services.core.configuration;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.pm.PackageManager;
|
||||
|
||||
import androidx.startup.AppInitializer;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
|
@ -106,11 +109,14 @@ public class CoreModuleConfiguration implements IModuleConfiguration {
|
|||
List<Metric> metrics = new ArrayList<>();
|
||||
int hasX264 = Device.hasX264Decoder() ? 1 : 0;
|
||||
int hasX265 = Device.hasX265Decoder() ? 1 : 0;
|
||||
int hasAV1 = Device.hasAV1Decoder() ? 1 : 0;
|
||||
metrics.add(new Metric("native_device_decoder_x264", hasX264));
|
||||
metrics.add(new Metric("native_device_decoder_x265", hasX265));
|
||||
metrics.add(new Metric("native_device_decoder_av1", hasAV1));
|
||||
SDKMetricsSender sdkMetricsSender = Utilities.getService(SDKMetricsSender.class);
|
||||
sdkMetricsSender.sendMetrics(metrics);
|
||||
checkForCronet(configuration);
|
||||
checkForPC(configuration, sdkMetricsSender);
|
||||
}
|
||||
|
||||
private void checkForCronet(Configuration configuration) {
|
||||
|
@ -119,4 +125,14 @@ public class CoreModuleConfiguration implements IModuleConfiguration {
|
|||
.initializeComponent(CronetInitializer.class);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkForPC(Configuration configuration, SDKMetricsSender sdkMetricsSender) {
|
||||
if (configuration.getExperiments().isPCCheckEnabled()) {
|
||||
Context context = ClientProperties.getApplicationContext();
|
||||
if (context == null) return;
|
||||
PackageManager pm = context.getPackageManager();
|
||||
boolean isPC = pm.hasSystemFeature("com.google.android.play.feature.HPE_EXPERIENCE");
|
||||
sdkMetricsSender.sendMetric(new Metric("native_device_is_pc", isPC ? 1 : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
package com.unity3d.services.core.configuration;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.managers.SCARBiddingManagerType;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
@ -53,11 +51,6 @@ public class ExperimentObjects extends ExperimentsBase {
|
|||
return getExperimentValueOrDefault(EXP_TAG_SCAR_INIT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getScarBiddingManager() {
|
||||
return getExperimentValue(EXP_TAG_SCAR_BIDDING_MANAGER, SCARBiddingManagerType.DISABLED.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isJetpackLifecycle() {
|
||||
return getExperimentValueOrDefault(EXP_TAG_JETPACK_LIFECYCLE);
|
||||
|
@ -83,6 +76,27 @@ public class ExperimentObjects extends ExperimentsBase {
|
|||
return getExperimentValueOrDefault(EXP_TAG_CRONET_CHECK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeShowTimeoutDisabled() {
|
||||
return getExperimentValueOrDefault(EXP_TAG_SHOW_TIMEOUT_DISABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeLoadTimeoutDisabled() {
|
||||
return getExperimentValueOrDefault(EXP_TAG_LOAD_TIMEOUT_DISABLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaptureHDRCapabilitiesEnabled() {
|
||||
return getExperimentValueOrDefault(EXP_TAG_HDR_CAPABILITIES);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScarBannerHbEnabled() { return getExperimentValueOrDefault(EXP_TAG_SCAR_HB_BN); }
|
||||
|
||||
@Override
|
||||
public boolean isPCCheckEnabled() { return getExperimentValueOrDefault(EXP_TAG_IS_PC_CHECK_ENABLED); }
|
||||
|
||||
private String getExperimentValue(String experimentName, String defaultValue) {
|
||||
ExperimentObject expo = getExperimentObject(experimentName);
|
||||
return (expo != null) ? expo.getStringValue() : defaultValue;
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package com.unity3d.services.core.configuration;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.managers.SCARBiddingManagerType;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -56,8 +53,8 @@ public class Experiments extends ExperimentsBase {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getScarBiddingManager() {
|
||||
return _experimentData.optString(EXP_TAG_SCAR_BIDDING_MANAGER, SCARBiddingManagerType.DISABLED.getName());
|
||||
public boolean isScarBannerHbEnabled() {
|
||||
return _experimentData.optBoolean(EXP_TAG_SCAR_HB_BN, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -85,6 +82,26 @@ public class Experiments extends ExperimentsBase {
|
|||
return _experimentData.optBoolean(EXP_TAG_CRONET_CHECK, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeShowTimeoutDisabled() {
|
||||
return _experimentData.optBoolean(EXP_TAG_SHOW_TIMEOUT_DISABLED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNativeLoadTimeoutDisabled() {
|
||||
return _experimentData.optBoolean(EXP_TAG_LOAD_TIMEOUT_DISABLED, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCaptureHDRCapabilitiesEnabled() {
|
||||
return _experimentData.optBoolean(EXP_TAG_HDR_CAPABILITIES, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPCCheckEnabled() {
|
||||
return _experimentData.optBoolean(EXP_TAG_IS_PC_CHECK_ENABLED, false);
|
||||
}
|
||||
|
||||
public JSONObject getExperimentsAsJson() {
|
||||
return _experimentData;
|
||||
}
|
||||
|
|
|
@ -6,12 +6,15 @@ public abstract class ExperimentsBase implements IExperiments {
|
|||
static final String EXP_TAG_WEB_AD_ASSET_CACHING = "wac";
|
||||
static final String EXP_TAG_WEB_GESTURE_NOT_REQUIRED = "wgr";
|
||||
static final String EXP_TAG_SCAR_INIT = "scar_init";
|
||||
static final String EXP_TAG_SCAR_BIDDING_MANAGER = "scar_bm";
|
||||
static final String EXP_TAG_JETPACK_LIFECYCLE = "gjl";
|
||||
static final String EXP_TAG_OK_HTTP = "okhttp";
|
||||
static final String EXP_TAG_WEB_MESSAGE = "jwm";
|
||||
static final String EXP_TAG_WEBVIEW_ASYNC_DOWNLOAD = "wad";
|
||||
static final String EXP_TAG_CRONET_CHECK = "cce";
|
||||
|
||||
static final String EXP_TAG_SHOW_TIMEOUT_DISABLED = "nstd";
|
||||
static final String EXP_TAG_LOAD_TIMEOUT_DISABLED = "nltd";
|
||||
static final String EXP_TAG_HDR_CAPABILITIES = "hdrc";
|
||||
static final String EXP_TAG_SCAR_HB_BN = "scar_bn";
|
||||
static final String EXP_TAG_IS_PC_CHECK_ENABLED = "pc_check";
|
||||
static final boolean EXP_DEFAULT_VALUE = false;
|
||||
}
|
||||
|
|
|
@ -10,12 +10,16 @@ public interface IExperiments {
|
|||
boolean isWebAssetAdCaching();
|
||||
boolean isWebGestureNotRequired();
|
||||
boolean isScarInitEnabled();
|
||||
String getScarBiddingManager();
|
||||
boolean isJetpackLifecycle();
|
||||
boolean isOkHttpEnabled();
|
||||
boolean isWebMessageEnabled();
|
||||
boolean isWebViewAsyncDownloadEnabled();
|
||||
boolean isCronetCheckEnabled();
|
||||
boolean isNativeShowTimeoutDisabled();
|
||||
boolean isNativeLoadTimeoutDisabled();
|
||||
boolean isCaptureHDRCapabilitiesEnabled();
|
||||
boolean isScarBannerHbEnabled();
|
||||
boolean isPCCheckEnabled();
|
||||
|
||||
JSONObject getCurrentSessionExperiments();
|
||||
JSONObject getNextSessionExperiments();
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.unity3d.services.core.device;
|
||||
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
|
@ -19,6 +20,7 @@ import android.net.NetworkInfo;
|
|||
import android.os.BatteryManager;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.os.ext.SdkExtensions;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.TelephonyManager;
|
||||
|
||||
|
@ -61,6 +63,14 @@ public class Device {
|
|||
return Build.VERSION.SDK_INT;
|
||||
}
|
||||
|
||||
public static int getExtensionVersion() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
|
||||
return SdkExtensions.getExtensionVersion(Build.VERSION_CODES.R);
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getOsVersion() {
|
||||
return Build.VERSION.RELEASE;
|
||||
}
|
||||
|
@ -699,6 +709,10 @@ public class Device {
|
|||
return Device.selectAllDecodeCodecs(MimeTypes.VIDEO_H265).size() > 0;
|
||||
}
|
||||
|
||||
public static boolean hasAV1Decoder() {
|
||||
return Device.selectAllDecodeCodecs(MimeTypes.VIDEO_AV1).size() > 0;
|
||||
}
|
||||
|
||||
public static List<MediaCodecInfo> selectAllDecodeCodecs(String mimeType) {
|
||||
List<MediaCodecInfo> result = new ArrayList<>();
|
||||
int numCodecs = MediaCodecList.getCodecCount();
|
||||
|
|
|
@ -7,4 +7,5 @@ public class MimeTypes {
|
|||
public static final String VIDEO_WEBM = BASE_TYPE_VIDEO + "/webm";
|
||||
public static final String VIDEO_H264 = BASE_TYPE_VIDEO + "/avc";
|
||||
public static final String VIDEO_H265 = BASE_TYPE_VIDEO + "/hevc";
|
||||
public static final String VIDEO_AV1 = BASE_TYPE_VIDEO + "/av01";
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
package com.unity3d.services.core.device.reader;
|
||||
|
||||
import static android.view.Display.HdrCapabilities.HDR_TYPE_DOLBY_VISION;
|
||||
import static android.view.Display.HdrCapabilities.HDR_TYPE_HDR10;
|
||||
import static android.view.Display.HdrCapabilities.HDR_TYPE_HDR10_PLUS;
|
||||
import static android.view.Display.HdrCapabilities.HDR_TYPE_HLG;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.res.Configuration;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
public class HdrInfoReader implements IHdrInfoReader {
|
||||
|
||||
private final SDKMetricsSender _sdkMetricsSender = Utilities.getService(SDKMetricsSender.class);
|
||||
private static final AtomicBoolean _hdrMetricsCaptured = new AtomicBoolean(false);
|
||||
|
||||
private static volatile HdrInfoReader _instance;
|
||||
|
||||
private HdrInfoReader() {}
|
||||
|
||||
public static HdrInfoReader getInstance() {
|
||||
if (_instance == null) {
|
||||
synchronized (HdrInfoReader.class) {
|
||||
if (_instance == null) {
|
||||
_instance = new HdrInfoReader();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void captureHDRCapabilityMetrics(Activity activity, ExperimentsReader experimentsReader) {
|
||||
if (activity == null) return;
|
||||
|
||||
if (!experimentsReader.getCurrentlyActiveExperiments().isCaptureHDRCapabilitiesEnabled()) return;
|
||||
|
||||
if (_hdrMetricsCaptured.compareAndSet(false, true)) {
|
||||
|
||||
List<Metric> hdrMetrics = new ArrayList<>(5);
|
||||
|
||||
int hasDolbyVision = 0;
|
||||
int hasHDR10 = 0;
|
||||
int hasHDR10Plus = 0;
|
||||
int hasHLG = 0;
|
||||
int isScreenHDR = 0;
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
|
||||
Display display = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
Display.HdrCapabilities hdrCapabilities = display.getHdrCapabilities();
|
||||
|
||||
int[] types = hdrCapabilities.getSupportedHdrTypes();
|
||||
for (int type : types) {
|
||||
switch (type) {
|
||||
case HDR_TYPE_DOLBY_VISION:
|
||||
hasDolbyVision = 1;
|
||||
break;
|
||||
case HDR_TYPE_HDR10:
|
||||
hasHDR10 = 1;
|
||||
break;
|
||||
case HDR_TYPE_HLG:
|
||||
hasHLG = 1;
|
||||
break;
|
||||
case HDR_TYPE_HDR10_PLUS:
|
||||
hasHDR10Plus = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
long maxAverage = Math.round(hdrCapabilities.getDesiredMaxAverageLuminance());
|
||||
long maxLum = Math.round(hdrCapabilities.getDesiredMaxLuminance());
|
||||
long minLum = Math.round(hdrCapabilities.getDesiredMinLuminance());
|
||||
|
||||
hdrMetrics.add(new Metric("native_device_hdr_lum_max_average", maxAverage));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_lum_max", maxLum));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_lum_min", minLum));
|
||||
|
||||
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
|
||||
Configuration configuration = activity.getResources().getConfiguration();
|
||||
isScreenHDR = configuration.isScreenHdr() ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
hdrMetrics.add(new Metric("native_device_hdr_dolby_vision", hasDolbyVision));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_hdr10", hasHDR10));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_hdr10_plus", hasHDR10Plus));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_hlg", hasHLG));
|
||||
hdrMetrics.add(new Metric("native_device_hdr_screen_hdr", isScreenHDR));
|
||||
|
||||
_sdkMetricsSender.sendMetrics(hdrMetrics);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.unity3d.services.core.device.reader;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.unity3d.services.core.configuration.ExperimentsReader;
|
||||
|
||||
public interface IHdrInfoReader {
|
||||
void captureHDRCapabilityMetrics(Activity activity, ExperimentsReader experimentsReader);
|
||||
}
|
|
@ -3,10 +3,12 @@ package com.unity3d.services.core.di
|
|||
import android.os.Handler
|
||||
import android.os.Looper
|
||||
import com.unity3d.services.SDKErrorHandler
|
||||
import com.unity3d.services.ads.measurements.MeasurementsService
|
||||
import com.unity3d.services.ads.token.AsyncTokenStorage
|
||||
import com.unity3d.services.ads.token.InMemoryAsyncTokenStorage
|
||||
import com.unity3d.services.ads.token.InMemoryTokenStorage
|
||||
import com.unity3d.services.ads.token.TokenStorage
|
||||
import com.unity3d.services.ads.topics.TopicsService
|
||||
import com.unity3d.services.core.device.VolumeChange
|
||||
import com.unity3d.services.core.device.VolumeChangeContentObserver
|
||||
import com.unity3d.services.core.device.VolumeChangeMonitor
|
||||
|
@ -15,6 +17,7 @@ import com.unity3d.services.core.domain.SDKDispatchers
|
|||
import com.unity3d.services.core.domain.task.*
|
||||
import com.unity3d.services.core.network.core.LegacyHttpClient
|
||||
import com.unity3d.services.core.network.core.HttpClient
|
||||
import com.unity3d.services.core.properties.ClientProperties
|
||||
import com.unity3d.services.core.network.core.OkHttp3Client
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender
|
||||
|
@ -84,6 +87,9 @@ object ServiceProvider : IServiceProvider {
|
|||
single<VolumeChange> { VolumeChangeContentObserver() }
|
||||
single { VolumeChangeMonitor(SharedInstances.webViewEventSender, get()) }
|
||||
|
||||
// android privacy sandbox
|
||||
single { MeasurementsService(ClientProperties.getApplicationContext(), get(), SharedInstances.webViewEventSender) }
|
||||
single { TopicsService(ClientProperties.getApplicationContext(), get(), SharedInstances.webViewEventSender) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -125,7 +131,7 @@ object ServiceProvider : IServiceProvider {
|
|||
*/
|
||||
private fun provideHttpClient(dispatchers: ISDKDispatchers, configFileFromLocalStorage: ConfigFileFromLocalStorage): HttpClient {
|
||||
val config = runBlocking {
|
||||
runCatching { configFileFromLocalStorage(ConfigFileFromLocalStorage.Params()) }.getOrNull()
|
||||
configFileFromLocalStorage(ConfigFileFromLocalStorage.Params()).getOrNull()
|
||||
}
|
||||
|
||||
if (config?.experiments?.isOkHttpEnabled == true) {
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.unity3d.services.core.di.IServiceComponent
|
|||
*/
|
||||
interface BaseTask<in P: BaseParams, R>: IServiceComponent {
|
||||
|
||||
suspend operator fun invoke(params: P): R = doWork(params)
|
||||
suspend operator fun invoke(params: P): Result<R> = doWork(params)
|
||||
|
||||
suspend fun doWork(params: P): R
|
||||
suspend fun doWork(params: P): Result<R>
|
||||
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.core.domain.task
|
|||
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.properties.SdkProperties
|
||||
import kotlinx.coroutines.withContext
|
||||
import org.json.JSONObject
|
||||
|
@ -20,12 +21,14 @@ class ConfigFileFromLocalStorage(
|
|||
return getMetricNameForInitializeTask("read_local_config")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Configuration =
|
||||
override suspend fun doWork(params: Params): Result<Configuration> =
|
||||
withContext(dispatchers.io) {
|
||||
val configFile = File(SdkProperties.getLocalConfigurationFilepath())
|
||||
val fileContent = configFile.readText()
|
||||
val loadedJson = JSONObject(fileContent)
|
||||
Configuration(loadedJson)
|
||||
runReturnSuspendCatching {
|
||||
val configFile = File(SdkProperties.getLocalConfigurationFilepath())
|
||||
val fileContent = configFile.readText()
|
||||
val loadedJson = JSONObject(fileContent)
|
||||
Configuration(loadedJson)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.unity3d.services.core.configuration.ErrorState
|
|||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.domain.getInitializationExceptionOrThrow
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.lifecycle.CachedLifecycle
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import kotlinx.coroutines.CoroutineName
|
||||
|
@ -31,80 +32,82 @@ class InitializeSDK(
|
|||
return getMetricNameForInitializeTask("initialize")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: EmptyParams) =
|
||||
override suspend fun doWork(params: EmptyParams) : Result<Unit> =
|
||||
withContext(dispatchers.default) {
|
||||
InitializeEventsMetricSender.getInstance().didInitStart()
|
||||
CachedLifecycle.register()
|
||||
runReturnSuspendCatching {
|
||||
InitializeEventsMetricSender.getInstance().didInitStart()
|
||||
CachedLifecycle.register()
|
||||
|
||||
// check if we have a configuration cached
|
||||
DeviceLog.debug("Unity Ads Init: Loading Config File From Local Storage")
|
||||
val configuration = runCatching { configFileFromLocalStorage(ConfigFileFromLocalStorage.Params()) }
|
||||
.onFailure { DeviceLog.debug("Unity Ads Init: Could not load config file from local storage: ${it.message}") }
|
||||
.getOrDefault(Configuration())
|
||||
// check if we have a configuration cached
|
||||
DeviceLog.debug("Unity Ads Init: Loading Config File From Local Storage")
|
||||
val configuration = configFileFromLocalStorage(ConfigFileFromLocalStorage.Params())
|
||||
.onFailure { DeviceLog.debug("Unity Ads Init: Could not load config file from local storage: ${it.message}") }
|
||||
.getOrDefault(Configuration())
|
||||
|
||||
// reset modules
|
||||
val resetResult = runCatching { initializeStateReset(InitializeStateReset.Params(configuration)) }
|
||||
if (resetResult.isFailure) {
|
||||
executeErrorState(ErrorState.ResetWebApp, resetResult.exceptionOrNull(), configuration)
|
||||
throw resetResult.exceptionOrNull() ?: Exception(ErrorState.ResetWebApp.toString())
|
||||
}
|
||||
// reset modules
|
||||
val resetResult = initializeStateReset(InitializeStateReset.Params(configuration))
|
||||
if (resetResult.isFailure) {
|
||||
executeErrorState(ErrorState.ResetWebApp, resetResult.exceptionOrNull(), configuration)
|
||||
throw resetResult.exceptionOrNull() ?: Exception(ErrorState.ResetWebApp.toString())
|
||||
}
|
||||
|
||||
// get native config
|
||||
val configResult = runCatching { initializeStateConfig(InitializeStateConfig.Params(configuration)) }
|
||||
if (configResult.isFailure) {
|
||||
handleInitializationException(configResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
// get native config
|
||||
val configResult = initializeStateConfig(InitializeStateConfig.Params(configuration))
|
||||
if (configResult.isFailure) {
|
||||
handleInitializationException(configResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
|
||||
if (configuration.experiments.isNativeWebViewCacheEnabled) {
|
||||
// load webview from remote url
|
||||
val createWithRemoteResult = runCatching {
|
||||
initializeStateCreateWithRemote(
|
||||
InitializeStateCreateWithRemote.Params(configResult.getOrThrow())
|
||||
if (configuration.experiments.isNativeWebViewCacheEnabled) {
|
||||
// load webview from remote url
|
||||
val createWithRemoteResult = initializeStateCreateWithRemote(
|
||||
InitializeStateCreateWithRemote.Params(configResult.getOrThrow())
|
||||
)
|
||||
}
|
||||
if (createWithRemoteResult.isSuccess) {
|
||||
initializeStateComplete(InitializeStateComplete.Params(configResult.getOrThrow()))
|
||||
return@withContext
|
||||
} else {
|
||||
handleInitializationException(createWithRemoteResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
}
|
||||
|
||||
// load WebView from cache if available and correct, if not fetch and load
|
||||
val loadCacheResult =
|
||||
runCatching { initializeStateLoadCache(InitializeStateLoadCache.Params(configResult.getOrThrow())) }
|
||||
if (loadCacheResult.isFailure) {
|
||||
executeErrorState(ErrorState.LoadCache, loadCacheResult.exceptionOrNull(), configuration)
|
||||
throw loadCacheResult.exceptionOrNull() ?: Exception(ErrorState.LoadCache.toString())
|
||||
}
|
||||
|
||||
val loadCacheResultData = loadCacheResult.getOrThrow()
|
||||
val webViewData: String = if (loadCacheResultData.hasHashMismatch) {
|
||||
// cached data has mismatch on checksum
|
||||
if (configuration.experiments.isWebViewAsyncDownloadEnabled && loadCacheResultData.webViewData != null) {
|
||||
// Fire and forget webView download, will be used in next session.
|
||||
launch(CoroutineName("LaunchLoadWeb")) { runCatching { initializeStateLoadWeb(InitializeStateLoadWeb.Params(configResult.getOrThrow())) }}
|
||||
loadCacheResultData.webViewData
|
||||
} else {
|
||||
// We don't have any cached WebView, we must wait for download to complete to continue init
|
||||
val loadWebResult = runCatching { initializeStateLoadWeb(InitializeStateLoadWeb.Params(configResult.getOrThrow())) }
|
||||
if (loadWebResult.isFailure) {
|
||||
handleInitializationException(loadWebResult.getInitializationExceptionOrThrow())
|
||||
if (createWithRemoteResult.isSuccess) {
|
||||
initializeStateComplete(InitializeStateComplete.Params(configResult.getOrThrow())).getOrThrow()
|
||||
return@runReturnSuspendCatching
|
||||
} else {
|
||||
handleInitializationException(createWithRemoteResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
loadWebResult.getOrThrow().webViewDataString
|
||||
}
|
||||
} else {
|
||||
checkNotNull(loadCacheResultData.webViewData) { "WebView is missing." }
|
||||
}
|
||||
|
||||
val createResult =
|
||||
runCatching { initializeStateCreate(InitializeStateCreate.Params(configResult.getOrThrow(), webViewData)) }
|
||||
if (createResult.isFailure) {
|
||||
handleInitializationException(createResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
// load WebView from cache if available and correct, if not fetch and load
|
||||
val loadCacheResult = initializeStateLoadCache(InitializeStateLoadCache.Params(configResult.getOrThrow()))
|
||||
|
||||
initializeStateComplete(InitializeStateComplete.Params(configResult.getOrThrow()))
|
||||
return@withContext
|
||||
if (loadCacheResult.isFailure) {
|
||||
executeErrorState(ErrorState.LoadCache, loadCacheResult.exceptionOrNull(), configuration)
|
||||
throw loadCacheResult.exceptionOrNull() ?: Exception(ErrorState.LoadCache.toString())
|
||||
}
|
||||
|
||||
val loadCacheResultData = loadCacheResult.getOrThrow()
|
||||
val webViewData: String = if (loadCacheResultData.hasHashMismatch) {
|
||||
// cached data has mismatch on checksum
|
||||
if (configuration.experiments.isWebViewAsyncDownloadEnabled && loadCacheResultData.webViewData != null) {
|
||||
// Fire and forget webView download, will be used in next session.
|
||||
launch(CoroutineName("LaunchLoadWeb")) {
|
||||
initializeStateLoadWeb(InitializeStateLoadWeb.Params(configResult.getOrThrow()))
|
||||
}
|
||||
loadCacheResultData.webViewData
|
||||
} else {
|
||||
// We don't have any cached WebView, we must wait for download to complete to continue init
|
||||
val loadWebResult = initializeStateLoadWeb(InitializeStateLoadWeb.Params(configResult.getOrThrow()))
|
||||
|
||||
if (loadWebResult.isFailure) {
|
||||
handleInitializationException(loadWebResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
loadWebResult.getOrThrow().webViewDataString
|
||||
}
|
||||
} else {
|
||||
checkNotNull(loadCacheResultData.webViewData) { "WebView is missing." }
|
||||
}
|
||||
|
||||
val createResult = initializeStateCreate(InitializeStateCreate.Params(configResult.getOrThrow(), webViewData))
|
||||
|
||||
if (createResult.isFailure) {
|
||||
handleInitializationException(createResult.getInitializationExceptionOrThrow())
|
||||
}
|
||||
|
||||
initializeStateComplete(InitializeStateComplete.Params(configResult.getOrThrow())).getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun handleInitializationException(exception: InitializationException) {
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.core.domain.task
|
|||
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class InitializeStateComplete(
|
||||
|
@ -12,9 +13,11 @@ class InitializeStateComplete(
|
|||
return getMetricNameForInitializeTask("completion")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Unit = withContext(dispatchers.default) {
|
||||
for (moduleName in params.config.moduleConfigurationList) {
|
||||
params.config.getModuleConfiguration(moduleName)?.initCompleteState(params.config)
|
||||
override suspend fun doWork(params: Params): Result<Unit> = withContext(dispatchers.default) {
|
||||
runReturnSuspendCatching {
|
||||
for (moduleName in params.config.moduleConfigurationList) {
|
||||
params.config.getModuleConfiguration(moduleName)?.initCompleteState(params.config)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.core.domain.task
|
|||
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.properties.SdkProperties
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -15,15 +16,17 @@ class InitializeStateConfig(
|
|||
return getMetricNameForInitializeTask("config_fetch")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Configuration =
|
||||
override suspend fun doWork(params: Params): Result<Configuration> =
|
||||
withContext(dispatchers.default) {
|
||||
DeviceLog.info("Unity Ads init: load configuration from " + SdkProperties.getConfigUrl())
|
||||
val configuration = Configuration(
|
||||
SdkProperties.getConfigUrl(),
|
||||
params.config.experimentsReader
|
||||
)
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.info("Unity Ads init: load configuration from " + SdkProperties.getConfigUrl())
|
||||
val configuration = Configuration(
|
||||
SdkProperties.getConfigUrl(),
|
||||
params.config.experimentsReader
|
||||
)
|
||||
|
||||
initializeStateConfigWithLoader(InitializeStateConfigWithLoader.Params(configuration))
|
||||
initializeStateConfigWithLoader(InitializeStateConfigWithLoader.Params(configuration)).getOrThrow()
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val config: Configuration) : BaseParams
|
||||
|
|
|
@ -6,8 +6,8 @@ import com.unity3d.services.core.device.reader.DeviceInfoDataFactory
|
|||
import com.unity3d.services.core.di.get
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.AbortRetryException
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.extensions.withRetry
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender
|
||||
import com.unity3d.services.core.request.metrics.TSIMetric
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -27,105 +27,114 @@ class InitializeStateConfigWithLoader(
|
|||
private val sdkMetricsSender: SDKMetricsSender
|
||||
) : BaseTask<InitializeStateConfigWithLoader.Params, Configuration> {
|
||||
|
||||
override suspend fun doWork(params: Params) =
|
||||
override suspend fun doWork(params: Params) : Result<Configuration> =
|
||||
withContext(dispatchers.default) {
|
||||
val privacyConfigStorage = PrivacyConfigStorage.getInstance()
|
||||
val deviceInfoDataFactory = DeviceInfoDataFactory()
|
||||
runReturnSuspendCatching {
|
||||
val privacyConfigStorage = PrivacyConfigStorage.getInstance()
|
||||
val deviceInfoDataFactory = DeviceInfoDataFactory()
|
||||
|
||||
var configurationLoader: IConfigurationLoader = ConfigurationLoader(
|
||||
ConfigurationRequestFactory(
|
||||
params.config,
|
||||
deviceInfoDataFactory.getDeviceInfoData(InitRequestType.TOKEN)
|
||||
), get()
|
||||
)
|
||||
configurationLoader = PrivacyConfigurationLoader(
|
||||
configurationLoader,
|
||||
ConfigurationRequestFactory(
|
||||
params.config,
|
||||
deviceInfoDataFactory.getDeviceInfoData(InitRequestType.PRIVACY)
|
||||
),
|
||||
privacyConfigStorage
|
||||
)
|
||||
var config = Configuration()
|
||||
|
||||
val configResult = runCatching {
|
||||
withRetry(
|
||||
retries = params.config.maxRetries,
|
||||
scalingFactor = params.config.retryScalingFactor,
|
||||
retryDelay = params.config.retryDelay,
|
||||
fallbackException = InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception(),
|
||||
params.config
|
||||
var configurationLoader: IConfigurationLoader = ConfigurationLoader(
|
||||
ConfigurationRequestFactory(
|
||||
params.config,
|
||||
deviceInfoDataFactory.getDeviceInfoData(InitRequestType.TOKEN)
|
||||
), get()
|
||||
)
|
||||
configurationLoader = PrivacyConfigurationLoader(
|
||||
configurationLoader,
|
||||
ConfigurationRequestFactory(
|
||||
params.config,
|
||||
deviceInfoDataFactory.getDeviceInfoData(InitRequestType.PRIVACY)
|
||||
),
|
||||
) {
|
||||
if (it > 0) InitializeEventsMetricSender.getInstance().onRetryConfig()
|
||||
withContext(dispatchers.io) {
|
||||
configurationLoader.loadConfiguration(object :
|
||||
IConfigurationLoaderListener {
|
||||
override fun onSuccess(configuration: Configuration) {
|
||||
config = configuration
|
||||
config.saveToDisk()
|
||||
tokenStorage.setInitToken(config.unifiedAuctionToken)
|
||||
}
|
||||
privacyConfigStorage
|
||||
)
|
||||
var config = Configuration()
|
||||
|
||||
override fun onError(errorMsg: String) {
|
||||
sdkMetricsSender.sendMetric(TSIMetric.newEmergencySwitchOff())
|
||||
// Shall return with error and stop retries
|
||||
throw AbortRetryException(errorMsg)
|
||||
}
|
||||
})
|
||||
val configResult = runCatching {
|
||||
withRetry(
|
||||
retries = params.config.maxRetries,
|
||||
scalingFactor = params.config.retryScalingFactor,
|
||||
retryDelay = params.config.retryDelay,
|
||||
fallbackException = InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception(),
|
||||
params.config
|
||||
),
|
||||
) {
|
||||
if (it > 0) InitializeEventsMetricSender.getInstance().onRetryConfig()
|
||||
withContext(dispatchers.io) {
|
||||
configurationLoader.loadConfiguration(object :
|
||||
IConfigurationLoaderListener {
|
||||
override fun onSuccess(configuration: Configuration) {
|
||||
config = configuration
|
||||
config.saveToDisk()
|
||||
tokenStorage.setInitToken(config.unifiedAuctionToken)
|
||||
}
|
||||
|
||||
override fun onError(errorMsg: String) {
|
||||
sdkMetricsSender.sendMetric(TSIMetric.newEmergencySwitchOff())
|
||||
// Shall return with error and stop retries
|
||||
throw AbortRetryException(errorMsg)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config = if (configResult.isFailure) {
|
||||
// Check if it as an aborted exception
|
||||
val configResultException = configResult.exceptionOrNull()
|
||||
if (configResultException is AbortRetryException) {
|
||||
// Abort init!
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
configResultException,
|
||||
params.config
|
||||
)
|
||||
}
|
||||
val haveNetwork =
|
||||
runCatching { initializeStateNetworkError(InitializeStateNetworkError.Params(params.config)) }
|
||||
if (haveNetwork.isSuccess) {
|
||||
InitializeEventsMetricSender.getInstance().onRetryConfig()
|
||||
withContext(dispatchers.io) {
|
||||
configurationLoader.loadConfiguration(object : IConfigurationLoaderListener {
|
||||
override fun onSuccess(configuration: Configuration) {
|
||||
config = configuration
|
||||
config.saveToDisk()
|
||||
tokenStorage.setInitToken(config.unifiedAuctionToken)
|
||||
}
|
||||
|
||||
override fun onError(errorMsg: String) {
|
||||
sdkMetricsSender.sendMetric(TSIMetric.newEmergencySwitchOff())
|
||||
// Shall return with an error
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception(errorMsg),
|
||||
config = if (configResult.isFailure) {
|
||||
// Check if it as an aborted exception
|
||||
val configResultException = configResult.exceptionOrNull()
|
||||
if (configResultException is AbortRetryException) {
|
||||
// Abort init!
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
configResultException,
|
||||
params.config
|
||||
)
|
||||
}
|
||||
val haveNetwork =
|
||||
runCatching {
|
||||
initializeStateNetworkError(
|
||||
InitializeStateNetworkError.Params(
|
||||
params.config
|
||||
)
|
||||
}
|
||||
})
|
||||
)
|
||||
}
|
||||
if (haveNetwork.isSuccess) {
|
||||
InitializeEventsMetricSender.getInstance().onRetryConfig()
|
||||
withContext(dispatchers.io) {
|
||||
configurationLoader.loadConfiguration(object :
|
||||
IConfigurationLoaderListener {
|
||||
override fun onSuccess(configuration: Configuration) {
|
||||
config = configuration
|
||||
config.saveToDisk()
|
||||
tokenStorage.setInitToken(config.unifiedAuctionToken)
|
||||
}
|
||||
|
||||
override fun onError(errorMsg: String) {
|
||||
sdkMetricsSender.sendMetric(TSIMetric.newEmergencySwitchOff())
|
||||
// Shall return with an error
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception(errorMsg),
|
||||
params.config
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
config
|
||||
} else {
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception("No connected events within the timeout!"),
|
||||
params.config
|
||||
)
|
||||
}
|
||||
config
|
||||
} else {
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkConfigRequest,
|
||||
Exception("No connected events within the timeout!"),
|
||||
params.config
|
||||
)
|
||||
config
|
||||
}
|
||||
} else {
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
config
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.unity3d.services.core.domain.task
|
|||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.configuration.ErrorState
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewApp
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -22,28 +23,34 @@ class InitializeStateCreate(
|
|||
return getMetricNameForInitializeTask("create_web_view")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Configuration = withContext(dispatchers.default) {
|
||||
DeviceLog.debug("Unity Ads init: creating webapp")
|
||||
override suspend fun doWork(params: Params): Result<Configuration> = withContext(dispatchers.default) {
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.debug("Unity Ads init: creating webapp")
|
||||
|
||||
val configuration: Configuration = params.config
|
||||
configuration.webViewData = params.webViewData
|
||||
val configuration: Configuration = params.config
|
||||
configuration.webViewData = params.webViewData
|
||||
|
||||
val createErrorState: ErrorState? = try {
|
||||
WebViewApp.create(configuration, false)
|
||||
} catch (e: IllegalThreadStateException) {
|
||||
DeviceLog.exception("Illegal Thread", e)
|
||||
throw InitializationException(ErrorState.CreateWebApp, e, configuration)
|
||||
}
|
||||
|
||||
if (createErrorState == null) {
|
||||
configuration
|
||||
} else {
|
||||
var errorMessage: String? = "Unity Ads WebApp creation failed"
|
||||
if (WebViewApp.getCurrentApp().webAppFailureMessage != null) {
|
||||
errorMessage = WebViewApp.getCurrentApp().webAppFailureMessage
|
||||
val createErrorState: ErrorState? = try {
|
||||
WebViewApp.create(configuration, false)
|
||||
} catch (e: IllegalThreadStateException) {
|
||||
DeviceLog.exception("Illegal Thread", e)
|
||||
throw InitializationException(ErrorState.CreateWebApp, e, configuration)
|
||||
}
|
||||
|
||||
if (createErrorState == null) {
|
||||
configuration
|
||||
} else {
|
||||
var errorMessage: String? = "Unity Ads WebApp creation failed"
|
||||
if (WebViewApp.getCurrentApp().webAppFailureMessage != null) {
|
||||
errorMessage = WebViewApp.getCurrentApp().webAppFailureMessage
|
||||
}
|
||||
DeviceLog.error(errorMessage)
|
||||
throw InitializationException(
|
||||
createErrorState,
|
||||
Exception(errorMessage),
|
||||
configuration
|
||||
)
|
||||
}
|
||||
DeviceLog.error(errorMessage)
|
||||
throw InitializationException(createErrorState, Exception(errorMessage), configuration)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.unity3d.services.core.domain.task
|
|||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.configuration.ErrorState
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewApp
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -22,28 +23,34 @@ class InitializeStateCreateWithRemote(
|
|||
return getMetricNameForInitializeTask("create_web_view")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Configuration =
|
||||
override suspend fun doWork(params: Params): Result<Configuration> =
|
||||
withContext(dispatchers.default) {
|
||||
DeviceLog.debug("Unity Ads init: creating webapp")
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.debug("Unity Ads init: creating webapp")
|
||||
|
||||
val configuration: Configuration = params.config
|
||||
val configuration: Configuration = params.config
|
||||
|
||||
val createErrorState: ErrorState? = try {
|
||||
WebViewApp.create(configuration, true)
|
||||
} catch (e: IllegalThreadStateException) {
|
||||
DeviceLog.exception("Illegal Thread", e)
|
||||
throw InitializationException(ErrorState.CreateWebApp, e, configuration)
|
||||
}
|
||||
|
||||
if (createErrorState == null) {
|
||||
configuration
|
||||
} else {
|
||||
var errorMessage: String? = "Unity Ads WebApp creation failed"
|
||||
if (WebViewApp.getCurrentApp().webAppFailureMessage != null) {
|
||||
errorMessage = WebViewApp.getCurrentApp().webAppFailureMessage
|
||||
val createErrorState: ErrorState? = try {
|
||||
WebViewApp.create(configuration, true)
|
||||
} catch (e: IllegalThreadStateException) {
|
||||
DeviceLog.exception("Illegal Thread", e)
|
||||
throw InitializationException(ErrorState.CreateWebApp, e, configuration)
|
||||
}
|
||||
|
||||
if (createErrorState == null) {
|
||||
configuration
|
||||
} else {
|
||||
var errorMessage: String? = "Unity Ads WebApp creation failed"
|
||||
if (WebViewApp.getCurrentApp().webAppFailureMessage != null) {
|
||||
errorMessage = WebViewApp.getCurrentApp().webAppFailureMessage
|
||||
}
|
||||
DeviceLog.error(errorMessage)
|
||||
throw InitializationException(
|
||||
createErrorState,
|
||||
Exception(errorMessage),
|
||||
configuration
|
||||
)
|
||||
}
|
||||
DeviceLog.error(errorMessage)
|
||||
throw InitializationException(createErrorState, Exception(errorMessage), configuration)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.unity3d.services.core.domain.task
|
|||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.configuration.ErrorState
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
|
@ -22,14 +23,16 @@ class InitializeStateError(
|
|||
|
||||
override suspend fun doWork(params: Params) =
|
||||
withContext(dispatchers.default) {
|
||||
DeviceLog.error("Unity Ads init: halting init in " + params.errorState.metricName + ": " + params.exception.message)
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.error("Unity Ads init: halting init in " + params.errorState.metricName + ": " + params.exception.message)
|
||||
|
||||
for (moduleName in params.config.moduleConfigurationList ?: emptyArray()) {
|
||||
params.config.getModuleConfiguration(moduleName)?.initErrorState(
|
||||
params.config,
|
||||
params.errorState,
|
||||
params.exception.message
|
||||
)
|
||||
for (moduleName in params.config.moduleConfigurationList ?: emptyArray()) {
|
||||
params.config.getModuleConfiguration(moduleName)?.initErrorState(
|
||||
params.config,
|
||||
params.errorState,
|
||||
params.exception.message
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.core.domain.task
|
|||
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.misc.Utilities
|
||||
import com.unity3d.services.core.properties.SdkProperties
|
||||
|
@ -25,23 +26,27 @@ class InitializeStateLoadCache(
|
|||
return getMetricNameForInitializeTask("read_local_webview")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): LoadCacheResult =
|
||||
override suspend fun doWork(params: Params): Result<LoadCacheResult> =
|
||||
withContext(dispatchers.default) {
|
||||
DeviceLog.debug("Unity Ads init: check if webapp can be loaded from local cache")
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.debug("Unity Ads init: check if webapp can be loaded from local cache")
|
||||
|
||||
val localWebViewData: ByteArray = getWebViewData() ?: return@withContext LoadCacheResult(hasHashMismatch = true)
|
||||
val localWebViewHash: String? = Utilities.Sha256(localWebViewData)
|
||||
val localWebViewData: ByteArray =
|
||||
getWebViewData() ?: return@runReturnSuspendCatching LoadCacheResult(hasHashMismatch = true)
|
||||
val localWebViewHash: String? = Utilities.Sha256(localWebViewData)
|
||||
|
||||
// If charset isn't supported on device, might throw an exception (result.isFailure)
|
||||
val webViewDataString = String(localWebViewData, Charset.forName("UTF-8"))
|
||||
// If charset isn't supported on device, might throw an exception (result.isFailure)
|
||||
val webViewDataString = String(localWebViewData, Charset.forName("UTF-8"))
|
||||
|
||||
val hashMismatch = localWebViewHash == null || localWebViewHash != params.config.webViewHash
|
||||
val hashMismatch =
|
||||
localWebViewHash == null || localWebViewHash != params.config.webViewHash
|
||||
|
||||
if (!hashMismatch) {
|
||||
DeviceLog.info("Unity Ads init: webapp loaded from local cache")
|
||||
if (!hashMismatch) {
|
||||
DeviceLog.info("Unity Ads init: webapp loaded from local cache")
|
||||
}
|
||||
|
||||
LoadCacheResult(hashMismatch, webViewDataString)
|
||||
}
|
||||
|
||||
LoadCacheResult(hashMismatch, webViewDataString)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,7 @@ import com.unity3d.services.core.configuration.ErrorState
|
|||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.domain.task.InitializeStateLoadWeb.LoadWebResult
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.extensions.withRetry
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.misc.Utilities
|
||||
|
@ -33,53 +34,65 @@ class InitializeStateLoadWeb(
|
|||
return getMetricNameForInitializeTask("download_web_view")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): LoadWebResult = withContext(dispatchers.default) {
|
||||
DeviceLog.info("Unity Ads init: loading webapp from " + params.config.webViewUrl)
|
||||
override suspend fun doWork(params: Params): Result<LoadWebResult> = withContext(dispatchers.default) {
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.info("Unity Ads init: loading webapp from " + params.config.webViewUrl)
|
||||
|
||||
val request = HttpRequest(baseURL = params.config.webViewUrl, method = RequestType.GET)
|
||||
val request = HttpRequest(baseURL = params.config.webViewUrl, method = RequestType.GET)
|
||||
|
||||
val webViewDataResult = runCatching {
|
||||
withRetry(
|
||||
retries = params.config.maxRetries,
|
||||
scalingFactor = params.config.retryScalingFactor,
|
||||
retryDelay = params.config.retryDelay,
|
||||
fallbackException = InitializationException(
|
||||
ErrorState.NetworkWebviewRequest,
|
||||
Exception(),
|
||||
params.config
|
||||
),
|
||||
) {
|
||||
if (it > 0) InitializeEventsMetricSender.getInstance().onRetryWebview()
|
||||
withContext(dispatchers.io) { httpClient.execute(request) }
|
||||
val webViewDataResult = runCatching {
|
||||
withRetry(
|
||||
retries = params.config.maxRetries,
|
||||
scalingFactor = params.config.retryScalingFactor,
|
||||
retryDelay = params.config.retryDelay,
|
||||
fallbackException = InitializationException(
|
||||
ErrorState.NetworkWebviewRequest,
|
||||
Exception(),
|
||||
params.config
|
||||
),
|
||||
) {
|
||||
if (it > 0) InitializeEventsMetricSender.getInstance().onRetryWebview()
|
||||
withContext(dispatchers.io) { httpClient.execute(request) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val webViewData: String = if (webViewDataResult.isFailure) {
|
||||
val haveNetwork =
|
||||
runCatching { initializeStateNetworkError(InitializeStateNetworkError.Params(params.config)) }
|
||||
if (haveNetwork.isSuccess) {
|
||||
withContext(dispatchers.io) { httpClient.execute(request).body.toString() }
|
||||
val webViewData: String = if (webViewDataResult.isFailure) {
|
||||
val haveNetwork =
|
||||
runCatching {
|
||||
initializeStateNetworkError(
|
||||
InitializeStateNetworkError.Params(
|
||||
params.config
|
||||
)
|
||||
)
|
||||
}
|
||||
if (haveNetwork.isSuccess) {
|
||||
withContext(dispatchers.io) { httpClient.execute(request).body.toString() }
|
||||
} else {
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkWebviewRequest,
|
||||
Exception("No connected events within the timeout!"),
|
||||
params.config
|
||||
)
|
||||
}
|
||||
} else {
|
||||
webViewDataResult.getOrThrow().body.toString()
|
||||
}
|
||||
|
||||
val webViewHash: String? = params.config.webViewHash
|
||||
if (webViewHash != null && Utilities.Sha256(webViewData) != webViewHash) {
|
||||
throw InitializationException(
|
||||
ErrorState.NetworkWebviewRequest,
|
||||
Exception("No connected events within the timeout!"),
|
||||
ErrorState.InvalidHash,
|
||||
Exception("Invalid webViewHash"),
|
||||
params.config
|
||||
)
|
||||
}
|
||||
} else {
|
||||
webViewDataResult.getOrThrow().body.toString()
|
||||
}
|
||||
|
||||
val webViewHash: String? = params.config.webViewHash
|
||||
if (webViewHash != null && Utilities.Sha256(webViewData) != webViewHash) {
|
||||
throw InitializationException(ErrorState.InvalidHash, Exception("Invalid webViewHash"), params.config)
|
||||
}
|
||||
if (webViewHash != null) {
|
||||
Utilities.writeFile(File(SdkProperties.getLocalWebViewFile()), webViewData)
|
||||
}
|
||||
|
||||
if (webViewHash != null) {
|
||||
Utilities.writeFile(File(SdkProperties.getLocalWebViewFile()), webViewData)
|
||||
LoadWebResult(params.config, webViewData)
|
||||
}
|
||||
|
||||
LoadWebResult(params.config, webViewData)
|
||||
}
|
||||
|
||||
data class Params(val config: Configuration) : BaseParams
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.unity3d.services.core.configuration.Configuration
|
|||
import com.unity3d.services.core.connectivity.ConnectivityMonitor
|
||||
import com.unity3d.services.core.connectivity.IConnectivityListener
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -30,20 +31,22 @@ class InitializeStateNetworkError(
|
|||
}
|
||||
|
||||
override suspend fun doWork(params: Params) = withContext(dispatchers.default) {
|
||||
DeviceLog.error("Unity Ads init: network error, waiting for connection events")
|
||||
maximumConnectedEvents = params.config.maximumConnectedEvents
|
||||
connectedEventThreshold = params.config.connectedEventThreshold
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.error("Unity Ads init: network error, waiting for connection events")
|
||||
maximumConnectedEvents = params.config.maximumConnectedEvents
|
||||
connectedEventThreshold = params.config.connectedEventThreshold
|
||||
|
||||
val success = withTimeoutOrNull(params.config.networkErrorTimeout) {
|
||||
suspendCancellableCoroutine<Unit> { cont ->
|
||||
startListening(cont)
|
||||
val success = withTimeoutOrNull(params.config.networkErrorTimeout) {
|
||||
suspendCancellableCoroutine<Unit> { cont ->
|
||||
startListening(cont)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We timed out
|
||||
if (success == null) {
|
||||
ConnectivityMonitor.removeListener(this@InitializeStateNetworkError)
|
||||
throw Exception("No connected events within the timeout!")
|
||||
// We timed out
|
||||
if (success == null) {
|
||||
ConnectivityMonitor.removeListener(this@InitializeStateNetworkError)
|
||||
throw Exception("No connected events within the timeout!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package com.unity3d.services.core.domain.task
|
|||
import com.unity3d.services.core.api.Lifecycle
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.properties.ClientProperties
|
||||
import com.unity3d.services.core.properties.SdkProperties
|
||||
|
@ -26,37 +27,39 @@ open class InitializeStateReset(
|
|||
return getMetricNameForInitializeTask("reset")
|
||||
}
|
||||
|
||||
override suspend fun doWork(params: Params): Configuration =
|
||||
override suspend fun doWork(params: Params): Result<Configuration> =
|
||||
withContext(dispatchers.default) {
|
||||
DeviceLog.debug("Unity Ads init: starting init")
|
||||
runReturnSuspendCatching {
|
||||
DeviceLog.debug("Unity Ads init: starting init")
|
||||
|
||||
val currentApp: WebViewApp? = WebViewApp.getCurrentApp()
|
||||
val currentApp: WebViewApp? = WebViewApp.getCurrentApp()
|
||||
|
||||
currentApp?.resetWebViewAppInitialization()
|
||||
if (currentApp?.webView != null) {
|
||||
val success = withTimeoutOrNull(params.config.webViewAppCreateTimeout) {
|
||||
withContext(dispatchers.main) {
|
||||
currentApp.webView?.destroy()
|
||||
currentApp.webView = null
|
||||
currentApp?.resetWebViewAppInitialization()
|
||||
if (currentApp?.webView != null) {
|
||||
val success = withTimeoutOrNull(params.config.webViewAppCreateTimeout) {
|
||||
withContext(dispatchers.main) {
|
||||
currentApp.webView?.destroy()
|
||||
currentApp.webView = null
|
||||
}
|
||||
}
|
||||
}
|
||||
if (success == null) {
|
||||
throw Exception("Reset failed on opening ConditionVariable")
|
||||
if (success == null) {
|
||||
throw Exception("Reset failed on opening ConditionVariable")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unregisterLifecycleCallbacks()
|
||||
|
||||
SdkProperties.setCacheDirectory(null)
|
||||
SdkProperties.getCacheDirectory() ?: throw Exception("Cache directory is NULL")
|
||||
|
||||
SdkProperties.setInitialized(false)
|
||||
|
||||
for (moduleName in params.config.moduleConfigurationList ?: emptyArray()) {
|
||||
params.config.getModuleConfiguration(moduleName)?.resetState(params.config)
|
||||
}
|
||||
params.config
|
||||
}
|
||||
|
||||
unregisterLifecycleCallbacks()
|
||||
|
||||
SdkProperties.setCacheDirectory(null)
|
||||
SdkProperties.getCacheDirectory() ?: throw Exception("Cache directory is NULL")
|
||||
|
||||
SdkProperties.setInitialized(false)
|
||||
|
||||
for (moduleName in params.config.moduleConfigurationList ?: emptyArray()) {
|
||||
params.config.getModuleConfiguration(moduleName)?.resetState(params.config)
|
||||
}
|
||||
params.config
|
||||
}
|
||||
|
||||
private fun unregisterLifecycleCallbacks() {
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
package com.unity3d.services.core.domain.task
|
||||
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.extensions.runReturnSuspendCatching
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class InitializeStateRetry(
|
||||
private val dispatchers: ISDKDispatchers,
|
||||
) : BaseTask<InitializeStateRetry.Params, Result<Unit>> {
|
||||
|
||||
override suspend fun doWork(params: Params): Result<Unit> = withContext(dispatchers.default) {
|
||||
runReturnSuspendCatching {
|
||||
// interactor logic
|
||||
}
|
||||
}
|
||||
|
||||
data class Params(val config: Configuration) : BaseParams
|
||||
}
|
|
@ -17,8 +17,8 @@ abstract class MetricTask<in P : BaseParams, R> : BaseTask<P, R> {
|
|||
var duration: Long = 0L
|
||||
var taskStatus: String = "unknown"
|
||||
|
||||
override suspend fun invoke(params: P): R {
|
||||
var result: R
|
||||
override suspend fun invoke(params: P): Result<R> {
|
||||
var result: Result<R>
|
||||
duration = TimeUnit.NANOSECONDS.toMillis(
|
||||
measureNanoTime {
|
||||
result = super.invoke(params)
|
||||
|
@ -27,12 +27,8 @@ abstract class MetricTask<in P : BaseParams, R> : BaseTask<P, R> {
|
|||
return result
|
||||
}
|
||||
|
||||
private fun captureMetric(result: R) {
|
||||
taskStatus = if (result is Result<*>) {
|
||||
if (result.isSuccess) "success" else "failure"
|
||||
} else {
|
||||
"success"
|
||||
}
|
||||
private fun captureMetric(result: Result<R>) {
|
||||
taskStatus = if (result.isSuccess) "success" else "failure"
|
||||
sendMetric()
|
||||
}
|
||||
|
||||
|
|
|
@ -28,10 +28,6 @@ open class MetricSender(
|
|||
|
||||
override val metricEndPoint: String? = configuration.metricsUrl
|
||||
|
||||
override fun areMetricsEnabledForCurrentSession(): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
override fun sendEvent(event: String, value: String?, tags: Map<String, String>) {
|
||||
if (event.isEmpty()) {
|
||||
DeviceLog.debug("Metric event not sent due to being null or empty: $event")
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче