Release 3.7.4
This commit is contained in:
Родитель
618ce50538
Коммит
73eee20f1e
|
@ -7,6 +7,7 @@ captures
|
|||
testServerAddress.txt
|
||||
app/bin
|
||||
unity-ads/bin
|
||||
libs
|
||||
javadoc
|
||||
.settings
|
||||
.project
|
||||
|
|
8
Makefile
8
Makefile
|
@ -37,16 +37,16 @@ test-local-staging-localhost: device-connected wake-up-device push-test-server-a
|
|||
run-all-tests: test-instrumentation test-legacy test-integration
|
||||
|
||||
test-ci:
|
||||
./gradlew connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.InstrumentationTestSuite,com.unity3d.ads.test.LegacyTestSuite
|
||||
./gradlew unity-ads:connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.InstrumentationTestSuite,com.unity3d.ads.test.LegacyTestSuite
|
||||
|
||||
test-instrumentation:
|
||||
./gradlew connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.InstrumentationTestSuite
|
||||
./gradlew unity-ads:connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.InstrumentationTestSuite
|
||||
|
||||
test-legacy:
|
||||
./gradlew connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.LegacyTestSuite
|
||||
./gradlew unity-ads:connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.LegacyTestSuite
|
||||
|
||||
test-integration:
|
||||
./gradlew connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.IntegrationTestSuite
|
||||
./gradlew unity-ads:connectedDebugAndroidTest -i -w --stacktrace -Pandroid.testInstrumentationRunnerArguments.class=com.unity3d.ads.test.IntegrationTestSuite
|
||||
|
||||
push-test-server-address-ip:
|
||||
echo http://$(shell ifconfig |grep "inet" |grep -E -o "([0-9]{1,3}[\.]){3}[0-9]{1,3}" |grep -v -E "^0|^127" -m 1):8080 > testServerAddress.txt
|
||||
|
|
|
@ -7,8 +7,8 @@ android {
|
|||
applicationId "com.unity3d.ads.example"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 30
|
||||
versionCode = 3720
|
||||
versionName = "3.7.2"
|
||||
versionCode = 3740
|
||||
versionName = "3.7.4"
|
||||
}
|
||||
|
||||
flavorDimensions "arEnabled"
|
||||
|
@ -27,18 +27,13 @@ android {
|
|||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(include: ['*.jar'], dir: 'libs')
|
||||
implementation 'androidx.appcompat:appcompat:1.0.0'
|
||||
implementation 'com.google.android.material:material:1.0.0'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
|
||||
implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
|
||||
implementation "com.google.android.material:material:1.3.0"
|
||||
implementation "androidx.appcompat:appcompat:1.3.0"
|
||||
implementation "androidx.coordinatorlayout:coordinatorlayout:1.1.0"
|
||||
arImplementation 'com.google.ar:core:1.4.0'
|
||||
implementation 'androidx.transition:transition:1.4.1'
|
||||
implementation project(':unity-ads')
|
||||
}
|
||||
|
|
Двоичные данные
app/src/main/res/drawable/unityads_logo.png
Двоичные данные
app/src/main/res/drawable/unityads_logo.png
Двоичный файл не отображается.
До Ширина: | Высота: | Размер: 6.5 KiB После Ширина: | Высота: | Размер: 2.3 KiB |
|
@ -1,19 +1,18 @@
|
|||
allprojects {
|
||||
repositories {
|
||||
google()
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
gradlePluginPortal()
|
||||
google()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:4.1.3'
|
||||
classpath 'com.android.tools.build:gradle:4.2.1'
|
||||
classpath 'org.jacoco:org.jacoco.core:0.8.1'
|
||||
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.20.0'
|
||||
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
|
||||
|
|
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7.1-all.zip
|
||||
|
|
|
@ -1 +1,5 @@
|
|||
include ':unity-scaradapter-1920'
|
||||
include ':unity-scaradapter-1950'
|
||||
include ':unity-scaradapter-2000'
|
||||
include ':unity-scaradapter-common'
|
||||
include ':app', ':unity-ads'
|
|
@ -19,8 +19,8 @@ dependencies {
|
|||
ext {
|
||||
GROUP_ID = "com.unity3d.ads"
|
||||
ARTIFACT_ID = "unity-ads"
|
||||
VERSION_ID = "3.7.2"
|
||||
VERSION_CODE = 3720
|
||||
VERSION_ID = "3.7.4"
|
||||
VERSION_CODE = 3740
|
||||
SIGN_AAR = properties.getProperty("SIGN_AAR") ?: false
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,7 @@ android {
|
|||
buildConfigField('int', 'VERSION_CODE', "$versionCode")
|
||||
buildConfigField('String', 'VERSION_NAME', "\"$versionName\"")
|
||||
testBuildType "debug"
|
||||
multiDexEnabled true
|
||||
|
||||
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
|
||||
testInstrumentationRunnerArguments disableAnalytics: 'true' // Won't work yet, see: https://code.google.com/p/android/issues/detail?id=188241
|
||||
|
@ -71,6 +72,25 @@ android {
|
|||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
androidTestImplementation project(':unity-scaradapter-2000')
|
||||
androidTestImplementation project(':unity-scaradapter-1950')
|
||||
androidTestImplementation project(':unity-scaradapter-1920')
|
||||
androidTestImplementation project(':unity-scaradapter-common')
|
||||
androidTestImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
androidTestImplementation 'org.mockito:mockito-android:2.25.0'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'com.google.android.gms:play-services-ads:19.5.0'
|
||||
compileOnly 'com.google.ar:core:1.0.0'
|
||||
compileOnly project(':unity-scaradapter-2000')
|
||||
compileOnly project(':unity-scaradapter-1950')
|
||||
compileOnly project(':unity-scaradapter-1920')
|
||||
compileOnly project(':unity-scaradapter-common')
|
||||
}
|
||||
|
||||
task javadoc(type: Javadoc) {
|
||||
description "Generates Javadoc for Release"
|
||||
source = android.sourceSets.main.java.srcDirs
|
||||
|
|
|
@ -35,6 +35,10 @@
|
|||
android:configChanges="fontScale|keyboard|keyboardHidden|locale|mnc|mcc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|uiMode|touchscreen"
|
||||
android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
|
||||
android:hardwareAccelerated="true" />
|
||||
<!-- Sample AdMob app ID: ca-app-pub-3940256099942544~3347511713 -->
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="ca-app-pub-3940256099942544~3347511713"/>
|
||||
</application>
|
||||
|
||||
</manifest>
|
|
@ -1,5 +1,6 @@
|
|||
package com.unity3d.ads.test;
|
||||
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.GmaScarTestSuite;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.operation.AdOperationTests;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.operation.LoadModuleDecoratorInitializationBufferTests;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.operation.LoadModuleDecoratorTests;
|
||||
|
@ -28,7 +29,6 @@ import org.junit.runners.Suite;
|
|||
AcquisitionTypeTest.class,
|
||||
AdsPropertiesTests.class,
|
||||
InitializationNotificationCenterTest.class,
|
||||
// LoadBridgeTest.class,
|
||||
WebPlayerViewSettingsCacheTest.class,
|
||||
WebPlayerViewCacheTest.class,
|
||||
BannerViewCacheTests.class,
|
||||
|
@ -42,7 +42,8 @@ import org.junit.runners.Suite;
|
|||
LoadModuleDecoratorInitializationBufferTests.class,
|
||||
AdOperationTests.class,
|
||||
ShowModuleTests.class,
|
||||
ConfigurationTest.class
|
||||
ConfigurationTest.class,
|
||||
GmaScarTestSuite.class
|
||||
})
|
||||
|
||||
public class InstrumentationTestSuite {}
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar;
|
||||
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.adapters.ScarAdapterFactoryTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder.GMAInitializerTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder.PresenceDetectorTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder.ScarVersionFinderTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges.AdapterStatusBridgeTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges.InitializationStatusBridgeTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges.InitializeListenerBridgeTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges.MobileAdsBridgeTest;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
ScarAdapterFactoryTest.class,
|
||||
GMAInitializerTest.class,
|
||||
PresenceDetectorTest.class,
|
||||
ScarVersionFinderTest.class,
|
||||
AdapterStatusBridgeTest.class,
|
||||
InitializationStatusBridgeTest.class,
|
||||
InitializeListenerBridgeTest.class,
|
||||
MobileAdsBridgeTest.class
|
||||
})
|
||||
public class GmaScarTestSuite {
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.adapters;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.services.ads.gmascar.adapters.ScarAdapterFactory;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ScarAdapterFactoryTest {
|
||||
@Mock
|
||||
private IAdsErrorHandler adsErrorHandlerMock;
|
||||
|
||||
private ScarAdapterFactory _scarAdapterFactory = new ScarAdapterFactory();
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory1920() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterFactory.CODE_19_2, adsErrorHandlerMock);
|
||||
Assert.assertTrue(adapter instanceof com.unity3d.scar.adapter.v1920.ScarAdapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory1950() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterFactory.CODE_19_5, adsErrorHandlerMock);
|
||||
Assert.assertTrue(adapter instanceof com.unity3d.scar.adapter.v1950.ScarAdapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory2000() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(ScarAdapterFactory.CODE_20_0, adsErrorHandlerMock);
|
||||
Assert.assertTrue(adapter instanceof com.unity3d.scar.adapter.v2000.ScarAdapter);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactoryUnsupported() {
|
||||
IScarAdapter adapter = _scarAdapterFactory.createScarAdapter(-1, adsErrorHandlerMock);
|
||||
Assert.assertNull(adapter);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges;
|
||||
|
||||
import com.google.android.gms.ads.initialization.AdapterStatus;
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class AdapterStatusBridgeTest {
|
||||
|
||||
@Test
|
||||
public void testAdapterStatusBridge() {
|
||||
AdapterStatusBridge adapterStatusBridge = new AdapterStatusBridge();
|
||||
Object[] statesEnum = adapterStatusBridge.getAdapterStatesEnum();
|
||||
Assert.assertEquals(AdapterStatus.State.values().length, statesEnum.length);
|
||||
Assert.assertEquals(AdapterStatus.State.NOT_READY, statesEnum[0]);
|
||||
Assert.assertEquals(AdapterStatus.State.READY, statesEnum[1]);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class InitializationStatusBridgeTest {
|
||||
|
||||
@Test
|
||||
public void testInitializationStatusBridgeNotInitialized() {
|
||||
InitializationStatusBridge initializationStatusBridge = new InitializationStatusBridge();
|
||||
Map<String, Object> adapterStatusMap = initializationStatusBridge.getAdapterStatusMap(new Object());
|
||||
Assert.assertNull(adapterStatusMap);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
public class InitializeListenerBridgeTest {
|
||||
|
||||
@Test
|
||||
public void testInitializeListenerBridge() {
|
||||
InitializeListenerBridge initializeListenerBridge = new InitializeListenerBridge();
|
||||
Object listenerProxy = initializeListenerBridge.createInitializeListenerProxy();
|
||||
Assert.assertNotNull(listenerProxy);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.bridges;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.gms.ads.initialization.InitializationStatus;
|
||||
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.mockito.Mockito.timeout;
|
||||
|
||||
public class MobileAdsBridgeTest {
|
||||
|
||||
@Test
|
||||
@Ignore("Have to ignore for now cause the bridge is stateful (underlying call to GMA static init depends on other tests")
|
||||
public void testMobileAdsBridgeGetVersionNotInitialized() {
|
||||
MobileAdsBridge mobileAdsBridge = new MobileAdsBridge();
|
||||
String versionString = mobileAdsBridge.getVersionString();
|
||||
Assert.assertEquals("0.0.0", versionString);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMobileAdsBridgeGetVersion() {
|
||||
OnInitializationCompleteListener initializationCompleteListener = Mockito.mock(OnInitializationCompleteListener.class);
|
||||
MobileAdsBridge mobileAdsBridge = new MobileAdsBridge();
|
||||
mobileAdsBridge.initialize(InstrumentationRegistry.getInstrumentation().getContext(), initializationCompleteListener);
|
||||
Mockito.verify(initializationCompleteListener, timeout(1000).times(1)).onInitializationComplete(Mockito.any(InitializationStatus.class));
|
||||
String versionString = mobileAdsBridge.getVersionString();
|
||||
Assert.assertTrue(String.format("Minor version 203404000 is not found in %s", versionString), versionString.contains("203404000"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("Cannot test this case since the underlying GMA call is static so test ordering impacts this result.")
|
||||
public void testMobileAdsBridgeGetInitStatusNotInitialized() {
|
||||
MobileAdsBridge mobileAdsBridge = new MobileAdsBridge();
|
||||
Object initializationStatus = mobileAdsBridge.getInitializationStatus();
|
||||
Assert.assertNull(initializationStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMobileAdsBridgeGetInitStatus() {
|
||||
OnInitializationCompleteListener initializationCompleteListener = Mockito.mock(OnInitializationCompleteListener.class);
|
||||
MobileAdsBridge mobileAdsBridge = new MobileAdsBridge();
|
||||
mobileAdsBridge.initialize(InstrumentationRegistry.getInstrumentation().getContext(), initializationCompleteListener);
|
||||
Object initializationStatus = mobileAdsBridge.getInitializationStatus();
|
||||
Assert.assertTrue(InitializationStatus.class.isAssignableFrom(initializationStatus.getClass()));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.google.android.gms.ads.initialization.OnInitializationCompleteListener;
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
import com.unity3d.services.ads.gmascar.finder.GMAInitializer;
|
||||
import com.unity3d.services.core.webview.WebView;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
|
||||
import org.junit.Assert;
|
||||
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.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class GMAInitializerTest {
|
||||
@Mock
|
||||
MobileAdsBridge mobileAdsBridge;
|
||||
@Mock
|
||||
InitializeListenerBridge initializeListenerBridge;
|
||||
@Mock
|
||||
InitializationStatusBridge initializationStatusBridge;
|
||||
@Mock
|
||||
AdapterStatusBridge adapterStatusBridge;
|
||||
|
||||
@Test
|
||||
public void testGmaInitializer() {
|
||||
GMAInitializer gmaInitializer = new GMAInitializer(mobileAdsBridge, initializeListenerBridge, initializationStatusBridge, adapterStatusBridge);
|
||||
gmaInitializer.initializeGMA();
|
||||
Mockito.verify(mobileAdsBridge, times(1)).initialize(Mockito.any(Context.class), Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGmaInitializerInitSuccess() {
|
||||
MobileAdsBridge realMobileAdsBridge = new MobileAdsBridge();
|
||||
OnInitializationCompleteListener initializationCompleteListener = Mockito.mock(OnInitializationCompleteListener.class);
|
||||
realMobileAdsBridge.initialize(InstrumentationRegistry.getInstrumentation().getContext(), initializationCompleteListener);
|
||||
Object initializationStatus = realMobileAdsBridge.getInitializationStatus();
|
||||
|
||||
InitializationStatusBridge realStatusBridge = new InitializationStatusBridge();
|
||||
GMAInitializer gmaInitializer = new GMAInitializer(realMobileAdsBridge, initializeListenerBridge, realStatusBridge, adapterStatusBridge);
|
||||
|
||||
WebViewApp mockWebViewApp = Mockito.mock(WebViewApp.class);
|
||||
Mockito.when(mockWebViewApp.sendEvent(Mockito.any(Enum.class), Mockito.any(Enum.class))).thenReturn(true);
|
||||
WebViewApp.setCurrentApp(mockWebViewApp);
|
||||
Mockito.when(adapterStatusBridge.isGMAInitialized(Mockito.any())).thenReturn(true);
|
||||
boolean initSuccess = gmaInitializer.initSuccessful(initializationStatus);
|
||||
Assert.assertTrue(initSuccess);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.finder.PresenceDetector;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarVersionFinder;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
|
||||
import org.junit.Assert;
|
||||
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 PresenceDetectorTest {
|
||||
@Mock
|
||||
MobileAdsBridge mobileAdsBridgeMock;
|
||||
@Mock
|
||||
InitializeListenerBridge initializeListenerBridgeMock;
|
||||
@Mock
|
||||
InitializationStatusBridge initializationStatusBridgeMock;
|
||||
@Mock
|
||||
AdapterStatusBridge adapterStatusBridgeMock;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Mockito.when(mobileAdsBridgeMock.exists()).thenReturn(true);
|
||||
Mockito.when(initializeListenerBridgeMock.exists()).thenReturn(true);
|
||||
Mockito.when(initializationStatusBridgeMock.exists()).thenReturn(true);
|
||||
Mockito.when(adapterStatusBridgeMock.exists()).thenReturn(true);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetector() {
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(mobileAdsBridgeMock, initializeListenerBridgeMock, initializationStatusBridgeMock, adapterStatusBridgeMock);
|
||||
Assert.assertTrue(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetectorWithNullBridges() {
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(null, null, null, null);
|
||||
Assert.assertFalse(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetectorMobileAdsClassMissing() {
|
||||
Mockito.when(mobileAdsBridgeMock.exists()).thenReturn(false);
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(mobileAdsBridgeMock, initializeListenerBridgeMock, initializationStatusBridgeMock, adapterStatusBridgeMock);
|
||||
Assert.assertFalse(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetectorListenerClassMissing() {
|
||||
Mockito.when(initializeListenerBridgeMock.exists()).thenReturn(false);
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(mobileAdsBridgeMock, initializeListenerBridgeMock, initializationStatusBridgeMock, adapterStatusBridgeMock);
|
||||
Assert.assertFalse(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetectorInitStatusClassMissing() {
|
||||
Mockito.when(initializationStatusBridgeMock.exists()).thenReturn(false);
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(mobileAdsBridgeMock, initializeListenerBridgeMock, initializationStatusBridgeMock, adapterStatusBridgeMock);
|
||||
Assert.assertFalse(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarPresenceDetectorAdapterStatusClassMissing() {
|
||||
Mockito.when(adapterStatusBridgeMock.exists()).thenReturn(false);
|
||||
PresenceDetector scarPresenceDetector = new PresenceDetector(mobileAdsBridgeMock, initializeListenerBridgeMock, initializationStatusBridgeMock, adapterStatusBridgeMock);
|
||||
Assert.assertFalse(scarPresenceDetector.areGMAClassesPresent());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.ads.gmascar.finder;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
import com.unity3d.services.ads.gmascar.finder.GMAInitializer;
|
||||
import com.unity3d.services.ads.gmascar.finder.PresenceDetector;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarVersionFinder;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
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 ScarVersionFinderTest {
|
||||
@Mock
|
||||
MobileAdsBridge mobileAdsBridgeMock;
|
||||
@Mock
|
||||
PresenceDetector presenceDetector;
|
||||
@Mock
|
||||
GMAInitializer gmaInitializer;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Mockito.when(gmaInitializer.getInitializeListenerBridge()).thenReturn(Mockito.mock(InitializeListenerBridge.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarVersionFinder() {
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn("afma-sdk-a-v204890999.203404000.1");
|
||||
ScarVersionFinder scarVersionFinder = new ScarVersionFinder(mobileAdsBridgeMock, presenceDetector, gmaInitializer);
|
||||
long versionCode = scarVersionFinder.getGoogleSdkVersionCode();
|
||||
Assert.assertEquals(203404000, versionCode);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testScarVersionFinderNullVersion() {
|
||||
MobileAdsBridge mobileAdsBridgeMock = Mockito.mock(MobileAdsBridge.class);
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn(null);
|
||||
ScarVersionFinder scarVersionFinder = new ScarVersionFinder(mobileAdsBridgeMock, presenceDetector, gmaInitializer);
|
||||
long versionCode = scarVersionFinder.getGoogleSdkVersionCode();
|
||||
Assert.assertEquals(-1, versionCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarVersionFinderMissingVersion() {
|
||||
MobileAdsBridge mobileAdsBridgeMock = Mockito.mock(MobileAdsBridge.class);
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn("");
|
||||
ScarVersionFinder scarVersionFinder = new ScarVersionFinder(mobileAdsBridgeMock, presenceDetector, gmaInitializer);
|
||||
long versionCode = scarVersionFinder.getGoogleSdkVersionCode();
|
||||
Assert.assertEquals(-1, versionCode);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarVersionFinderInvalidVersion() {
|
||||
MobileAdsBridge mobileAdsBridgeMock = Mockito.mock(MobileAdsBridge.class);
|
||||
Mockito.when(mobileAdsBridgeMock.getVersionString()).thenReturn("invalid");
|
||||
ScarVersionFinder scarVersionFinder = new ScarVersionFinder(mobileAdsBridgeMock, presenceDetector, gmaInitializer);
|
||||
long versionCode = scarVersionFinder.getGoogleSdkVersionCode();
|
||||
Assert.assertEquals(-1, versionCode);
|
||||
}
|
||||
}
|
|
@ -180,6 +180,8 @@ public class UnityServices {
|
|||
}
|
||||
|
||||
private static String createExpectedParametersString(String fieldName, Object current, Object received) {
|
||||
return "\n - " + fieldName + " Current: " + current.toString() + " | Received: " + received.toString();
|
||||
String currentSafeString = current == null ? "null" : current.toString();
|
||||
String receivedSafeString = received == null ? "null" : received.toString();
|
||||
return "\n - " + fieldName + " Current: " + currentSafeString + " | Received: " + receivedSafeString;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.GMAScarAdapterBridge;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
public class GMAScar {
|
||||
|
||||
private static GMAScarAdapterBridge gmaScarAdapterBridge = new GMAScarAdapterBridge();
|
||||
|
||||
@WebViewExposed
|
||||
public static void initializeScar(final WebViewCallback callback) {
|
||||
gmaScarAdapterBridge.initializeScar();
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getVersion(final WebViewCallback callback) {
|
||||
gmaScarAdapterBridge.getVersion();
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
public static void isInitialized(final WebViewCallback callback) {
|
||||
gmaScarAdapterBridge.isInitialized();
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getSCARSignals(final JSONArray interstitialList, final JSONArray rewardedList, final WebViewCallback callback) throws JSONException {
|
||||
gmaScarAdapterBridge.getSCARSignals(getPlacementList(interstitialList), getPlacementList(rewardedList));
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void load(final String placementId, final String queryId, final Boolean canSkip, final String adUnitId, final String adString, final Integer videoLengthMs, final WebViewCallback callback) {
|
||||
gmaScarAdapterBridge.load(canSkip, placementId, queryId, adString, adUnitId, videoLengthMs);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void show(final String placementId, final String queryId, final Boolean canSkip, final WebViewCallback callback) {
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
|
@ -4,10 +4,10 @@ import android.os.ConditionVariable;
|
|||
|
||||
import com.unity3d.ads.IUnityAdsListener;
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.ads.properties.AdsProperties;
|
||||
import com.unity3d.services.ads.UnityAdsImplementation;
|
||||
import com.unity3d.services.ads.adunit.AdUnitOpen;
|
||||
import com.unity3d.services.ads.placement.Placement;
|
||||
import com.unity3d.ads.properties.AdsProperties;
|
||||
import com.unity3d.services.ads.token.TokenStorage;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
|
@ -32,7 +32,8 @@ public class AdsModuleConfiguration implements IAdsModuleConfiguration {
|
|||
com.unity3d.services.ads.api.Purchasing.class,
|
||||
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.Token.class,
|
||||
com.unity3d.services.ads.api.GMAScar.class
|
||||
};
|
||||
|
||||
return list;
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package com.unity3d.services.ads.gmascar;
|
||||
|
||||
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.services.ads.gmascar.adapters.ScarAdapterFactory;
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
import com.unity3d.services.ads.gmascar.finder.GMAInitializer;
|
||||
import com.unity3d.services.ads.gmascar.finder.PresenceDetector;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarVersionFinder;
|
||||
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.core.properties.ClientProperties;
|
||||
|
||||
/**
|
||||
* Adapter bridge that uses the Scar Adapter module based on the version of the GMA SDK in the developer's game.
|
||||
*/
|
||||
public class GMAScarAdapterBridge {
|
||||
|
||||
private IScarAdapter _scarAdapter;
|
||||
private MobileAdsBridge _mobileAdsBridge;
|
||||
private ScarVersionFinder _scarVersionFinder;
|
||||
|
||||
private InitializeListenerBridge _initializationListenerBridge;
|
||||
private InitializationStatusBridge _initializationStatusBridge;
|
||||
private AdapterStatusBridge _adapterStatusBridge;
|
||||
private PresenceDetector _presenceDetector;
|
||||
private GMAInitializer _gmaInitializer;
|
||||
private WebViewErrorHandler _webViewErrorHandler;
|
||||
private ScarAdapterFactory _scarAdapterFactory;
|
||||
|
||||
public GMAScarAdapterBridge() {
|
||||
_mobileAdsBridge = new MobileAdsBridge();
|
||||
_initializationStatusBridge = new InitializationStatusBridge();
|
||||
_initializationListenerBridge = new InitializeListenerBridge();
|
||||
_adapterStatusBridge = new AdapterStatusBridge();
|
||||
_webViewErrorHandler = new WebViewErrorHandler();
|
||||
_scarAdapterFactory = new ScarAdapterFactory();
|
||||
_presenceDetector = new PresenceDetector(_mobileAdsBridge, _initializationListenerBridge, _initializationStatusBridge, _adapterStatusBridge);
|
||||
_gmaInitializer = new GMAInitializer(_mobileAdsBridge, _initializationListenerBridge, _initializationStatusBridge, _adapterStatusBridge);
|
||||
_scarVersionFinder = new ScarVersionFinder(_mobileAdsBridge, _presenceDetector, _gmaInitializer);
|
||||
}
|
||||
|
||||
public void initializeScar() {
|
||||
if (_presenceDetector.areGMAClassesPresent()) {
|
||||
_gmaInitializer.initializeGMA();
|
||||
} else {
|
||||
_webViewErrorHandler.handleError(new GMAAdsError(GMAEvent.INIT_ERROR));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return _gmaInitializer.isInitialized();
|
||||
}
|
||||
|
||||
public void getVersion() {
|
||||
_scarVersionFinder.getVersion();
|
||||
}
|
||||
|
||||
public void getSCARSignals(String[] interstitialList, String[] rewardedList) {
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
SignalsHandler signalListener = new SignalsHandler();
|
||||
|
||||
if (_scarAdapter != null) {
|
||||
_scarAdapter.getSCARSignals(ClientProperties.getApplicationContext(), interstitialList, rewardedList, signalListener);
|
||||
} else {
|
||||
_webViewErrorHandler.handleError(GMAAdsError.InternalSignalsError("Could not create SCAR adapter object"));
|
||||
}
|
||||
}
|
||||
|
||||
public void load(final boolean canSkip, final String placementId, final String queryId, final String adString, final String adUnitId, final int videoLengthMs) {
|
||||
ScarAdMetadata scarAdMetadata = new ScarAdMetadata(placementId, queryId, adUnitId, adString, videoLengthMs);
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
if (_scarAdapter != null) {
|
||||
if (canSkip) {
|
||||
loadInterstitialAd(scarAdMetadata);
|
||||
} else {
|
||||
loadRewardedAd(scarAdMetadata);
|
||||
}
|
||||
} else {
|
||||
_webViewErrorHandler.handleError(GMAAdsError.InternalLoadError(scarAdMetadata, "Scar Adapter object is null"));
|
||||
}
|
||||
}
|
||||
|
||||
private void loadInterstitialAd(final ScarAdMetadata scarAdMetadata) {
|
||||
ScarInterstitialAdHandler adListener = new ScarInterstitialAdHandler(scarAdMetadata);
|
||||
_scarAdapter.loadInterstitialAd(ClientProperties.getApplicationContext(), scarAdMetadata, adListener);
|
||||
}
|
||||
|
||||
private void loadRewardedAd(final ScarAdMetadata scarAdMetadata) {
|
||||
ScarRewardedAdHandler adListener = new ScarRewardedAdHandler(scarAdMetadata);
|
||||
_scarAdapter.loadRewardedAd(ClientProperties.getApplicationContext(), scarAdMetadata, adListener);
|
||||
}
|
||||
|
||||
public void show(final String placementId, final String queryId, final boolean canSkip) {
|
||||
ScarAdMetadata scarAdMetadata = new ScarAdMetadata(placementId, queryId);
|
||||
_scarAdapter = getScarAdapterObject();
|
||||
if (_scarAdapter != null) {
|
||||
_scarAdapter.show(ClientProperties.getActivity(), queryId, placementId);
|
||||
} else {
|
||||
_webViewErrorHandler.handleError(GMAAdsError.InternalShowError(scarAdMetadata, "Scar Adapter object is null"));
|
||||
}
|
||||
}
|
||||
|
||||
private IScarAdapter getScarAdapterObject() {
|
||||
if (_scarAdapter == null) {
|
||||
long minorVersion = _scarVersionFinder.getGoogleSdkVersionCode();
|
||||
_scarAdapter = _scarAdapterFactory.createScarAdapter(minorVersion, _webViewErrorHandler);
|
||||
}
|
||||
return _scarAdapter;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
package com.unity3d.services.ads.gmascar.adapters;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
|
||||
public class ScarAdapterFactory {
|
||||
public static final int CODE_20_0 = 210402000;
|
||||
public static final int CODE_19_7 = 204204000;
|
||||
public static final int CODE_19_5 = 203404000;
|
||||
public static final int CODE_19_2 = 201604000;
|
||||
|
||||
public IScarAdapter createScarAdapter(long gmaVersionCode, IAdsErrorHandler adsErrorHandler) {
|
||||
IScarAdapter scarAdapter = null;
|
||||
if (gmaVersionCode >= CODE_20_0) {
|
||||
scarAdapter = new com.unity3d.scar.adapter.v2000.ScarAdapter(adsErrorHandler);
|
||||
} else if (gmaVersionCode >= CODE_19_5 && gmaVersionCode <= CODE_19_7) {
|
||||
scarAdapter = new com.unity3d.scar.adapter.v1950.ScarAdapter(adsErrorHandler);
|
||||
} else if (gmaVersionCode >= CODE_19_2) {
|
||||
scarAdapter = new com.unity3d.scar.adapter.v1920.ScarAdapter(adsErrorHandler);
|
||||
} else {
|
||||
DeviceLog.debug("SCAR version %s is not supported.", gmaVersionCode);
|
||||
}
|
||||
return scarAdapter;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class AdapterStatusBridge extends GenericBridge {
|
||||
|
||||
private static final String initializeStateMethodName = "getInitializationState";
|
||||
|
||||
// This class contains the AdapterState Enum
|
||||
private Class _adapterStateClass;
|
||||
|
||||
public AdapterStatusBridge() {
|
||||
super(new HashMap<String, Class[]>() {{
|
||||
put(initializeStateMethodName, new Class[]{});
|
||||
}});
|
||||
AdapterStatusStateBridge adapterStatusStateBridge = new AdapterStatusStateBridge();
|
||||
try {
|
||||
_adapterStateClass = Class.forName(adapterStatusStateBridge.getClassName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
DeviceLog.debug("ERROR: Could not find class %s %s", adapterStatusStateBridge.getClassName(), e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
protected String getClassName() {
|
||||
return "com.google.android.gms.ads.initialization.AdapterStatus";
|
||||
}
|
||||
|
||||
public boolean isGMAInitialized(Object adapterState) {
|
||||
Object[] states = getAdapterStatesEnum();
|
||||
if (states == null) {
|
||||
DeviceLog.debug("ERROR: Could not get adapter states enum from AdapterStatus.State");
|
||||
return false;
|
||||
}
|
||||
|
||||
// States[0]: AdapterState.NOT_READY | States[1]: AdapterState.READY
|
||||
return (callNonVoidMethod(initializeStateMethodName, adapterState, new Object[]{}) == states[1]);
|
||||
}
|
||||
|
||||
public Object[] getAdapterStatesEnum() {
|
||||
return _adapterStateClass.getEnumConstants();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
public class AdapterStatusStateBridge {
|
||||
|
||||
public AdapterStatusStateBridge() {};
|
||||
|
||||
public String getClassName() {
|
||||
return "com.google.android.gms.ads.initialization.AdapterStatus$State";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,126 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class GenericBridge {
|
||||
|
||||
private String _className;
|
||||
private Map<String, Class[]> _functionAndParameters;
|
||||
private Map<String, Method> _methodMap;
|
||||
private boolean _methodMapBuilt = false;
|
||||
|
||||
protected abstract String getClassName();
|
||||
|
||||
public GenericBridge(Map<String, Class[]> functionAndParameters) {
|
||||
_className = getClassName();
|
||||
_functionAndParameters = functionAndParameters;
|
||||
_methodMap = new HashMap<>();
|
||||
buildMethodMap();
|
||||
}
|
||||
|
||||
public Map<String,Class[]> getFunctionMap() {
|
||||
return _functionAndParameters;
|
||||
}
|
||||
|
||||
public Class classForName() {
|
||||
try {
|
||||
Class getClass = Class.forName(_className);
|
||||
if (getClass != null) {
|
||||
return getClass;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
DeviceLog.debug("ERROR: Could not find GMA SDK Class %s %s", _className, e.getLocalizedMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
if (classForName() == null) {
|
||||
DeviceLog.debug("ERROR: Could not find class %s", _className);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_methodMapBuilt) {
|
||||
buildMethodMap();
|
||||
}
|
||||
if (_methodMap.size() != getFunctionMap().size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void buildMethodMap() {
|
||||
boolean methodMapNoErrors = true;
|
||||
for (Map.Entry<String, Class[]> entry : getFunctionMap().entrySet()) {
|
||||
Class[] parameterClasses = entry.getValue();
|
||||
try {
|
||||
Method method = getReflectiveMethod(classForName(), entry.getKey(), parameterClasses);
|
||||
if (method != null) {
|
||||
_methodMap.put(entry.getKey(), method);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("ERROR: Could not find %s class with method %s and parameters : %s", _className, entry.getKey(), parameterClasses);
|
||||
methodMapNoErrors = false;
|
||||
}
|
||||
}
|
||||
_methodMapBuilt = methodMapNoErrors;
|
||||
}
|
||||
|
||||
private Method getMethod(String methodName) {
|
||||
return _methodMap.get(methodName);
|
||||
}
|
||||
|
||||
private Method getReflectiveMethod(Class methodClass, String methodName, Class... parameterClasses) {
|
||||
Method method = null;
|
||||
try {
|
||||
method = methodClass.getDeclaredMethod(methodName, parameterClasses);
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("ERROR: Could not find method %s in %s", methodName, methodClass.getName() +
|
||||
" " + e.getLocalizedMessage());
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.METHOD_ERROR);
|
||||
} finally {
|
||||
return method;
|
||||
}
|
||||
}
|
||||
|
||||
public void callVoidMethod(String methodName, Object callingObj, Object... parameters) {
|
||||
Method method = getMethod(methodName);
|
||||
if (method == null) {
|
||||
DeviceLog.debug("ERROR: Could not find method %s", methodName);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
method.invoke(callingObj, parameters);
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("ERROR: Could not invoke method %s : %s", methodName, e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public Object callNonVoidMethod(String methodName, Object callingObj, Object... parameters) {
|
||||
Method method = getMethod(methodName);
|
||||
if (method == null) {
|
||||
DeviceLog.debug("ERROR: Could not find method %s", methodName);
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return method.invoke(callingObj, parameters);
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("ERROR: Could not invoke method %s : %s", methodName, e.getLocalizedMessage());
|
||||
}
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class InitializationStatusBridge extends GenericBridge {
|
||||
private static final String adapterStatusMapMethodName = "getAdapterStatusMap";
|
||||
|
||||
public InitializationStatusBridge() {
|
||||
super(new HashMap<String, Class[]>() {{
|
||||
put(adapterStatusMapMethodName, new Class[]{});
|
||||
}});
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "com.google.android.gms.ads.initialization.InitializationStatus";
|
||||
}
|
||||
|
||||
public Map<String, Object> getAdapterStatusMap(Object initStatusObj) {
|
||||
return (Map<String, Object>) callNonVoidMethod(adapterStatusMapMethodName,
|
||||
initStatusObj, new Object[]{});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.listeners.IInitializationStatusListener;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.HashMap;
|
||||
|
||||
public class InitializeListenerBridge extends GenericBridge {
|
||||
private static final String initializationCompleteMethodName = "onInitializationComplete";
|
||||
private IInitializationStatusListener _initializationStatusListener;
|
||||
|
||||
public InitializeListenerBridge() {
|
||||
super(new HashMap<String, Class[]>(){{
|
||||
try {
|
||||
put(initializationCompleteMethodName, new Class[]{Class.forName("com.google.android.gms.ads.initialization.InitializationStatus")});
|
||||
} catch (ClassNotFoundException e) {
|
||||
DeviceLog.debug("Could not find class \"com.google.android.gms.ads.initialization.InitializationStatus\" %s", e.getLocalizedMessage());
|
||||
}
|
||||
}});
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "com.google.android.gms.ads.initialization.OnInitializationCompleteListener";
|
||||
}
|
||||
|
||||
public void setStatusListener(IInitializationStatusListener initializationStatusListener) {
|
||||
_initializationStatusListener = initializationStatusListener;
|
||||
}
|
||||
|
||||
public Object createInitializeListenerProxy() {
|
||||
try {
|
||||
Object initProxy = Proxy.newProxyInstance(classForName().getClassLoader(),
|
||||
new Class<?>[]{classForName()}, new InvocationHandler() {
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) {
|
||||
if (method.getName().equals(initializationCompleteMethodName)) {
|
||||
if (_initializationStatusListener != null) {
|
||||
// args[0] contains an InitializationStatus object
|
||||
_initializationStatusListener.onInitializationComplete(args[0]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
return initProxy;
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("ERROR: Could not create InitializeCompletionListener");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package com.unity3d.services.ads.gmascar.bridges;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class MobileAdsBridge extends GenericBridge {
|
||||
private static final String initializeMethodName = "initialize";
|
||||
private static final String initializationStatusMethodName = "getInitializationStatus";
|
||||
private static final String versionStringMethodName = "getVersionString";
|
||||
|
||||
public MobileAdsBridge() {
|
||||
super(new HashMap<String, Class[]>() {{
|
||||
try {
|
||||
put(initializeMethodName, new Class[]{Context.class, Class.forName("com.google.android.gms.ads.initialization.OnInitializationCompleteListener")});
|
||||
} catch (ClassNotFoundException e) {
|
||||
DeviceLog.debug("Could not find class \"com.google.android.gms.ads.initialization.OnInitializationCompleteListener\" %s", e.getLocalizedMessage());
|
||||
}
|
||||
put(initializationStatusMethodName, new Class[]{});
|
||||
put(versionStringMethodName, new Class[]{});
|
||||
}});
|
||||
}
|
||||
|
||||
public String getClassName() {
|
||||
return "com.google.android.gms.ads.MobileAds";
|
||||
}
|
||||
|
||||
public void initialize(Context context, Object initializeListener) {
|
||||
callVoidMethod(initializeMethodName, null, new Object[]{context, initializeListener});
|
||||
}
|
||||
|
||||
public String getVersionString() {
|
||||
Object versionString = callNonVoidMethod(versionStringMethodName, null, new Object[]{});
|
||||
if (versionString == null) {
|
||||
return "0.0.0";
|
||||
}
|
||||
return versionString.toString();
|
||||
}
|
||||
|
||||
public Object getInitializationStatus () {
|
||||
return callNonVoidMethod(initializationStatusMethodName, null, new Object[]{});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.unity3d.services.ads.gmascar.finder;
|
||||
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class GMAInitializer {
|
||||
|
||||
private MobileAdsBridge _mobileAdsBridge;
|
||||
private InitializeListenerBridge _initializationListenerBridge;
|
||||
private InitializationStatusBridge _initializationStatusBridge;
|
||||
private AdapterStatusBridge _adapterStatusBridge;
|
||||
|
||||
public GMAInitializer(MobileAdsBridge mobileAdsBridge, InitializeListenerBridge initializeListenerBridge,
|
||||
InitializationStatusBridge initializationStatusBridge, AdapterStatusBridge adapterStatusBridge) {
|
||||
_mobileAdsBridge = mobileAdsBridge;
|
||||
_initializationListenerBridge = initializeListenerBridge;
|
||||
_initializationStatusBridge = initializationStatusBridge;
|
||||
_adapterStatusBridge = adapterStatusBridge;
|
||||
}
|
||||
|
||||
// We need to initialize GMA SDK in order to get the version string
|
||||
public void initializeGMA() {
|
||||
if (isInitialized()) {
|
||||
return;
|
||||
} else {
|
||||
_mobileAdsBridge.initialize(ClientProperties.getApplicationContext(), _initializationListenerBridge.createInitializeListenerProxy());
|
||||
}
|
||||
}
|
||||
|
||||
public boolean initSuccessful(Object initStatus) {
|
||||
Map<String, Object> statusMap = _initializationStatusBridge.getAdapterStatusMap(initStatus);
|
||||
|
||||
Object adapterState = statusMap.get(_mobileAdsBridge.getClassName());
|
||||
if (adapterState != null) {
|
||||
if (_adapterStatusBridge.isGMAInitialized(adapterState)) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.INIT_SUCCESS);
|
||||
return true;
|
||||
} else {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.INIT_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
boolean isInitialized = false;
|
||||
try {
|
||||
isInitialized = initSuccessful(_mobileAdsBridge.getInitializationStatus());
|
||||
} catch (Exception e) {
|
||||
isInitialized = false;
|
||||
DeviceLog.debug("ERROR: Could not get initialization status of GMA SDK - %s", e.getLocalizedMessage());
|
||||
} finally {
|
||||
return isInitialized;
|
||||
}
|
||||
}
|
||||
|
||||
public InitializeListenerBridge getInitializeListenerBridge() {
|
||||
return _initializationListenerBridge;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.unity3d.services.ads.gmascar.finder;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.bridges.AdapterStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializationStatusBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.InitializeListenerBridge;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
|
||||
public class PresenceDetector {
|
||||
private MobileAdsBridge _mobileAdsBridge;
|
||||
private InitializeListenerBridge _initializationListenerBridge;
|
||||
private InitializationStatusBridge _initializationStatusBridge;
|
||||
private AdapterStatusBridge _adapterStatusBridge;
|
||||
|
||||
public PresenceDetector(MobileAdsBridge mobileAdsBridge, InitializeListenerBridge initializeListenerBridge,
|
||||
InitializationStatusBridge initializationStatusBridge, AdapterStatusBridge adapterStatusBridge) {
|
||||
_mobileAdsBridge = mobileAdsBridge;
|
||||
_initializationListenerBridge = initializeListenerBridge;
|
||||
_initializationStatusBridge = initializationStatusBridge;
|
||||
_adapterStatusBridge = adapterStatusBridge;
|
||||
}
|
||||
|
||||
public boolean areGMAClassesPresent() {
|
||||
if (_mobileAdsBridge == null || _initializationListenerBridge == null ||
|
||||
_initializationStatusBridge == null || _adapterStatusBridge == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _mobileAdsBridge.exists() && _initializationListenerBridge.exists() && _initializationStatusBridge.exists()
|
||||
&& _adapterStatusBridge.exists();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package com.unity3d.services.ads.gmascar.finder;
|
||||
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.ads.gmascar.bridges.MobileAdsBridge;
|
||||
import com.unity3d.services.ads.gmascar.listeners.IInitializationStatusListener;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
public class ScarVersionFinder implements IInitializationStatusListener {
|
||||
|
||||
private static MobileAdsBridge _mobileAdsBridge;
|
||||
private PresenceDetector _presenceDetector;
|
||||
private GMAInitializer _gmaInitializer;
|
||||
private long _gmaSdkVersionCode = -1;
|
||||
|
||||
public ScarVersionFinder(MobileAdsBridge mobileAdsBridge, PresenceDetector presenceDetector, GMAInitializer gmaInitializer) {
|
||||
_mobileAdsBridge = mobileAdsBridge;
|
||||
_presenceDetector = presenceDetector;
|
||||
_gmaInitializer = gmaInitializer;
|
||||
_gmaInitializer.getInitializeListenerBridge().setStatusListener(this);
|
||||
}
|
||||
|
||||
public void getVersion() {
|
||||
try {
|
||||
if (!_presenceDetector.areGMAClassesPresent()) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.INIT_GMA, GMAEvent.VERSION, "0.0.0");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_gmaInitializer.isInitialized()) {
|
||||
_gmaInitializer.initializeGMA();
|
||||
} else {
|
||||
findAndSendVersion(true);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
DeviceLog.debug("Got exception finding GMA SDK: %s", e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void findAndSendVersion(boolean initializeSuccess) {
|
||||
String version = initializeSuccess ? _mobileAdsBridge.getVersionString() : "0.0.0";
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.INIT_GMA, GMAEvent.VERSION, version);
|
||||
}
|
||||
|
||||
public long getGoogleSdkVersionCode() {
|
||||
if (_gmaSdkVersionCode == -1) {
|
||||
String gmaSdkVersion = _mobileAdsBridge.getVersionString();
|
||||
if (gmaSdkVersion != null) {
|
||||
String[] versionComponents = gmaSdkVersion.split("\\.");
|
||||
if (versionComponents.length > 1) {
|
||||
_gmaSdkVersionCode = Long.parseLong(versionComponents[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return _gmaSdkVersionCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
// @param initStatus InitializationStatus Object retrieved through reflection
|
||||
public void onInitializationComplete(Object initStatus) {
|
||||
boolean isInitSuccessful = _gmaInitializer.initSuccessful(initStatus);
|
||||
findAndSendVersion(isInitSuccessful);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.unity3d.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ScarInterstitialAdHandler implements IScarInterstitialAdListenerWrapper {
|
||||
|
||||
private ScarAdMetadata _scarAdMetadata;
|
||||
private boolean _finishedPlaying = false;
|
||||
private boolean _hasSentStartEvents = false;
|
||||
private Timer _playbackTimer;
|
||||
private TimerTask _playbackTimerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
_finishedPlaying = true;
|
||||
}
|
||||
};
|
||||
|
||||
public ScarInterstitialAdHandler(ScarAdMetadata scarAdMetadata) {
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
_playbackTimer = new Timer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_LOADED, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(int errorCode, String errorString) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.LOAD_ERROR, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId(), errorString, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdOpened() {
|
||||
// We send all three events back to back since we don't have quartile callbacks from GMA
|
||||
if (!_hasSentStartEvents) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_STARTED);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.FIRST_QUARTILE);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.MIDPOINT);
|
||||
_hasSentStartEvents = true;
|
||||
}
|
||||
// Start timer here to see if the user watched to completion
|
||||
_finishedPlaying = false;
|
||||
_playbackTimer.schedule(_playbackTimerTask, _scarAdMetadata.getVideoLengthMs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToShow(int errorCode, String errorString) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.INTERSTITIAL_SHOW_ERROR, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId(), errorString, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClicked() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_CLICKED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
if (!_finishedPlaying) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_SKIPPED);
|
||||
_playbackTimer.cancel();
|
||||
}
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_CLOSED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdLeftApplication() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdImpression() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.INTERSTITIAL_IMPRESSION_RECORDED, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.unity3d.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
|
||||
public class ScarRewardedAdHandler implements IScarRewardedAdListenerWrapper {
|
||||
|
||||
private ScarAdMetadata _scarAdMetadata;
|
||||
private boolean _finishedPlaying = false;
|
||||
private boolean _hasRewarded = false;
|
||||
private boolean _hasSentStartEvents = false;
|
||||
private Timer _playbackTimer;
|
||||
private TimerTask _playbackTimerTask = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
_finishedPlaying = true;
|
||||
}
|
||||
};
|
||||
|
||||
public ScarRewardedAdHandler(ScarAdMetadata scarAdMetadata) {
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
_playbackTimer = new Timer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdLoaded() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_LOADED, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToLoad(int errorCode, String errorString) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.LOAD_ERROR, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId(), errorString, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdOpened() {
|
||||
// We send all three events back to back since we don't have quartile callbacks from GMA
|
||||
if (!_hasSentStartEvents) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_STARTED);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.FIRST_QUARTILE);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.MIDPOINT);
|
||||
_hasSentStartEvents = true;
|
||||
}
|
||||
if (!_hasRewarded) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_EARNED_REWARD);
|
||||
_hasRewarded = true;
|
||||
}
|
||||
_finishedPlaying = false;
|
||||
_playbackTimer.schedule(_playbackTimerTask, _scarAdMetadata.getVideoLengthMs());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToShow(int errorCode, String errorString) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.REWARDED_SHOW_ERROR, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId(), errorString, errorCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserEarnedReward() {
|
||||
if (!_hasRewarded) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_EARNED_REWARD);
|
||||
_hasRewarded = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdClosed() {
|
||||
if (!_finishedPlaying) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_SKIPPED);
|
||||
_playbackTimer.cancel();
|
||||
}
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.AD_CLOSED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdImpression() {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.REWARDED_IMPRESSION_RECORDED, _scarAdMetadata.getPlacementId(), _scarAdMetadata.getQueryId());
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.unity3d.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
public class SignalsHandler implements ISignalCollectionListener {
|
||||
|
||||
@Override
|
||||
public void onSignalsCollected(String signalsMap) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.SIGNALS, signalsMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSignalsCollectionFailed(String errorMsg) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, GMAEvent.SIGNALS_ERROR, errorMsg);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.unity3d.services.ads.gmascar.handlers;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.WebViewAdsError;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
public class WebViewErrorHandler implements IAdsErrorHandler<WebViewAdsError> {
|
||||
|
||||
@Override
|
||||
public void handleError(WebViewAdsError webViewAdsError) {
|
||||
WebViewEventCategory category = WebViewEventCategory.valueOf(webViewAdsError.getDomain());
|
||||
WebViewApp.getCurrentApp().sendEvent(category, webViewAdsError.getErrorCategory(), webViewAdsError.getErrorArguments());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.unity3d.services.ads.gmascar.listeners;
|
||||
|
||||
public interface IInitializationStatusListener {
|
||||
void onInitializationComplete(Object initStatus);
|
||||
}
|
|
@ -19,5 +19,7 @@ public enum WebViewEventCategory {
|
|||
PERMISSIONS,
|
||||
STORE,
|
||||
LOAD_API,
|
||||
TOKEN
|
||||
TOKEN,
|
||||
INIT_GMA,
|
||||
GMA
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,63 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
testCoverageEnabled true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation "org.mockito:mockito-android:2.25.0"
|
||||
androidTestImplementation 'com.google.android.gms:play-services-ads:19.2.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
testImplementation 'com.google.android.gms:play-services-ads:19.2.0'
|
||||
api project(':unity-scaradapter-common')
|
||||
compileOnly 'com.google.android.gms:play-services-ads:19.2.0'
|
||||
}
|
||||
|
||||
|
||||
task deleteOldJar(type: Delete) {
|
||||
delete("../unity-ads/libs/${project.name}.jar")
|
||||
}
|
||||
|
||||
task copyJars(type: Copy) {
|
||||
from('build/intermediates/compile_library_classes_jar/release/')
|
||||
into('../unity-ads/libs/')
|
||||
include('classes.jar')
|
||||
rename('classes.jar', "${project.name}.jar")
|
||||
}
|
||||
|
||||
copyJars.dependsOn(deleteOldJar)
|
||||
|
||||
project.tasks.whenTaskAdded { Task theTask ->
|
||||
if (theTask.name == 'bundleLibCompileToJarRelease') {
|
||||
theTask.finalizedBy(copyJars)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v1920">>
|
||||
<application>
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="ca-app-pub-3940256099942544~3347511713"
|
||||
/>
|
||||
</application>
|
||||
</manifest>
|
|
@ -0,0 +1,13 @@
|
|||
package com.unity3d.ads.test;
|
||||
|
||||
import com.unity3d.scar.adapter.v1920.signals.SignalsReaderTest;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
SignalsReaderTest.class
|
||||
})
|
||||
public class InstrumentationTestSuite {
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SignalsReaderTest {
|
||||
private Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
private ISignalCollectionListener _signalCollectionListener;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
_signalCollectionListener = Mockito.mock(ISignalCollectionListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignals() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoRewarded() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoInterstitial() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v1920">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
|
@ -0,0 +1,59 @@
|
|||
package com.unity3d.scar.adapter.v1920;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.ScarAdapterBase;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1920.scarads.ScarInterstitialAd;
|
||||
import com.unity3d.scar.adapter.v1920.scarads.ScarRewardedAd;
|
||||
import com.unity3d.scar.adapter.v1920.signals.SignalsReader;
|
||||
import com.unity3d.scar.adapter.v1920.signals.SignalsStorage;
|
||||
|
||||
import static com.unity3d.scar.adapter.common.Utils.runOnUiThread;
|
||||
|
||||
public class ScarAdapter extends ScarAdapterBase implements IScarAdapter {
|
||||
|
||||
private SignalsStorage _scarSignalStorage;
|
||||
|
||||
public ScarAdapter(IAdsErrorHandler adsErrorHandler) {
|
||||
super(adsErrorHandler);
|
||||
_scarSignalStorage = new SignalsStorage();
|
||||
_scarSignalReader = new SignalsReader(_scarSignalStorage);
|
||||
}
|
||||
|
||||
public void loadInterstitialAd(Context context, final ScarAdMetadata scarAd, final IScarInterstitialAdListenerWrapper adListenerWrapper) {
|
||||
final ScarInterstitialAd interstitialAd = new ScarInterstitialAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
interstitialAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), interstitialAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadRewardedAd(Context context, final ScarAdMetadata scarAd, final IScarRewardedAdListenerWrapper adListenerWrapper) {
|
||||
final ScarRewardedAd rewardedAd = new ScarRewardedAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rewardedAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), rewardedAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.unity3d.scar.adapter.v1920.scarads;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.AdInfo;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarAd;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1920.signals.QueryInfoMetadata;
|
||||
|
||||
public abstract class ScarAdBase implements IScarAd {
|
||||
|
||||
protected Context _context;
|
||||
protected ScarAdMetadata _scarAdMetadata;
|
||||
protected QueryInfoMetadata _queryInfoMetadata;
|
||||
protected IAdsErrorHandler _adsErrorHandler;
|
||||
|
||||
public ScarAdBase(Context context, ScarAdMetadata scarAdMetadata, QueryInfoMetadata queryInfoMetadata, IAdsErrorHandler adsErrorHandler) {
|
||||
_context = context;
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
_queryInfoMetadata = queryInfoMetadata;
|
||||
_adsErrorHandler = adsErrorHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAd(IScarLoadListener loadListener) {
|
||||
if (_queryInfoMetadata != null) {
|
||||
AdInfo adInfo = new AdInfo(_queryInfoMetadata.getQueryInfo(), _scarAdMetadata.getAdString());
|
||||
AdRequest adRequest = new AdRequest.Builder().setAdInfo(adInfo).build();
|
||||
loadAdInternal(loadListener, adRequest);
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalLoadError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest);
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.unity3d.scar.adapter.v1920.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.InterstitialAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1920.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarInterstitialAd extends ScarAdBase {
|
||||
|
||||
private InterstitialAd _interstitialAd;
|
||||
private ScarInterstitialAdListener _interstitialAdDelegate;
|
||||
|
||||
public ScarInterstitialAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarInterstitialAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_interstitialAd = new InterstitialAd(_context);
|
||||
_interstitialAd.setAdUnitId(_scarAdMetadata.getAdUnitId());
|
||||
_interstitialAdDelegate = new ScarInterstitialAdListener(_interstitialAd, adListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest) {
|
||||
_interstitialAd.setAdListener(_interstitialAdDelegate.getAdListener());
|
||||
_interstitialAdDelegate.setLoadListener(loadListener);
|
||||
_interstitialAd.loadAd(adRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_interstitialAd.isLoaded()) {
|
||||
_interstitialAd.show();
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
package com.unity3d.scar.adapter.v1920.scarads;
|
||||
|
||||
import com.google.android.gms.ads.AdListener;
|
||||
import com.google.android.gms.ads.InterstitialAd;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
|
||||
public class ScarInterstitialAdListener {
|
||||
|
||||
private InterstitialAd _interstitialAd;
|
||||
private IScarInterstitialAdListenerWrapper _adListenerWrapper;
|
||||
private IScarLoadListener _loadListener;
|
||||
|
||||
public ScarInterstitialAdListener(InterstitialAd interstitialAd, IScarInterstitialAdListenerWrapper adListenerWrapper) {
|
||||
_interstitialAd = interstitialAd;
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
}
|
||||
|
||||
private AdListener _adListener = new AdListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_adListenerWrapper.onAdLoaded();
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(int adErrorCode) {
|
||||
_adListenerWrapper.onAdFailedToLoad(adErrorCode, "SCAR ad failed to load");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdOpened() {
|
||||
_adListenerWrapper.onAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClicked() {
|
||||
_adListenerWrapper.onAdClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdLeftApplication() {
|
||||
_adListenerWrapper.onAdLeftApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
_adListenerWrapper.onAdClosed();
|
||||
}
|
||||
};
|
||||
|
||||
public AdListener getAdListener() {
|
||||
return _adListener;
|
||||
}
|
||||
|
||||
public void setLoadListener(IScarLoadListener loadListener) {
|
||||
_loadListener = loadListener;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v1920.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1920.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarRewardedAd extends ScarAdBase {
|
||||
|
||||
private RewardedAd _rewardedAd;
|
||||
private ScarRewardedAdListener _rewardedAdDelegate;
|
||||
|
||||
public ScarRewardedAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarRewardedAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_rewardedAd = new RewardedAd(_context, _scarAdMetadata.getAdUnitId());
|
||||
_rewardedAdDelegate = new ScarRewardedAdListener(_rewardedAd, adListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest) {
|
||||
_rewardedAdDelegate.setLoadListener(loadListener);
|
||||
_rewardedAd.loadAd(adRequest, _rewardedAdDelegate.getRewardedAdLoadCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_rewardedAd.isLoaded()) {
|
||||
_rewardedAd.show(activity, _rewardedAdDelegate.getRewardedAdCallback());
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.unity3d.scar.adapter.v1920.scarads;
|
||||
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
|
||||
import com.google.android.gms.ads.rewarded.RewardItem;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAdCallback;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
|
||||
public class ScarRewardedAdListener {
|
||||
|
||||
private RewardedAd _rewardedAd;
|
||||
private IScarRewardedAdListenerWrapper _adListenerWrapper;
|
||||
private IScarLoadListener _loadListener;
|
||||
|
||||
public ScarRewardedAdListener(RewardedAd rewardedAd, IScarRewardedAdListenerWrapper adListenerWrapper) {
|
||||
_rewardedAd = rewardedAd;
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
}
|
||||
|
||||
private RewardedAdLoadCallback _rewardedAdLoadCallback = new RewardedAdLoadCallback() {
|
||||
@Override
|
||||
public void onRewardedAdLoaded() {
|
||||
_adListenerWrapper.onRewardedAdLoaded();
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToLoad(int adErrorCode) {
|
||||
_adListenerWrapper.onRewardedAdFailedToLoad(adErrorCode, "SCAR ad failed to show");
|
||||
}
|
||||
};
|
||||
|
||||
private RewardedAdCallback rewardedAdCallback = new RewardedAdCallback () {
|
||||
@Override
|
||||
public void onRewardedAdOpened() {
|
||||
_adListenerWrapper.onRewardedAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToShow(int adErrorCode) {
|
||||
_adListenerWrapper.onRewardedAdFailedToShow(adErrorCode, "SCAR ad failed to show");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserEarnedReward(RewardItem rewardItem) {
|
||||
_adListenerWrapper.onUserEarnedReward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdClosed() {
|
||||
_adListenerWrapper.onRewardedAdClosed();
|
||||
}
|
||||
};
|
||||
|
||||
public RewardedAdCallback getRewardedAdCallback() {
|
||||
return rewardedAdCallback;
|
||||
}
|
||||
|
||||
public RewardedAdLoadCallback getRewardedAdLoadCallback() { return _rewardedAdLoadCallback; }
|
||||
|
||||
public void setLoadListener(IScarLoadListener loadListener) {
|
||||
_loadListener = loadListener;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.google.android.gms.ads.query.QueryInfoGenerationCallback;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.v1920.ScarAdapter;
|
||||
|
||||
public class QueryInfoCallback extends QueryInfoGenerationCallback {
|
||||
|
||||
private DispatchGroup _dispatchGroup;
|
||||
private QueryInfoMetadata _gmaQueryInfoMetadata;
|
||||
|
||||
public QueryInfoCallback(final QueryInfoMetadata gmaQueryInfoMetadata, final DispatchGroup dispatchGroup) {
|
||||
_dispatchGroup = dispatchGroup;
|
||||
_gmaQueryInfoMetadata = gmaQueryInfoMetadata;
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation succeeds
|
||||
@Override
|
||||
public void onSuccess(final QueryInfo queryInfo) {
|
||||
_gmaQueryInfoMetadata.setQueryInfo(queryInfo);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation fails
|
||||
@Override
|
||||
public void onFailure(String failureMsg) {
|
||||
_gmaQueryInfoMetadata.setError(failureMsg);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
|
||||
public class QueryInfoMetadata {
|
||||
private String _placementId;
|
||||
private QueryInfo _queryInfo;
|
||||
private String _error;
|
||||
|
||||
public QueryInfoMetadata(String placementId) {
|
||||
_placementId = placementId;
|
||||
}
|
||||
|
||||
public String getPlacementId() {
|
||||
return _placementId;
|
||||
}
|
||||
|
||||
public QueryInfo getQueryInfo() {
|
||||
return _queryInfo;
|
||||
}
|
||||
|
||||
public String getQueryStr() {
|
||||
String query = null;
|
||||
if (_queryInfo != null) {
|
||||
query = _queryInfo.getQuery();
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
public void setQueryInfo(QueryInfo queryInfo) {
|
||||
_queryInfo = queryInfo;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
_error = error;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdFormat;
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalsReader;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsReader implements ISignalsReader {
|
||||
private static SignalsStorage _signalsStorage;
|
||||
|
||||
public SignalsReader(SignalsStorage signalsStorage) {
|
||||
_signalsStorage = signalsStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSCARSignals(Context context, String[] interstitialList, String[] rewardedList,
|
||||
ISignalCollectionListener signalCompletionListener) {
|
||||
DispatchGroup dispatchGroup = new DispatchGroup();
|
||||
|
||||
for (String interstitialId : interstitialList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, interstitialId, AdFormat.INTERSTITIAL, dispatchGroup);
|
||||
}
|
||||
|
||||
for (String rewardedId : rewardedList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, rewardedId, AdFormat.REWARDED, dispatchGroup);
|
||||
}
|
||||
|
||||
dispatchGroup.notify(new GMAScarDispatchCompleted(signalCompletionListener));
|
||||
}
|
||||
|
||||
private void getSCARSignal(Context context, String placementId, AdFormat adType, DispatchGroup dispatchGroup) {
|
||||
AdRequest request = new AdRequest.Builder().build();
|
||||
QueryInfoMetadata gmaQueryInfoMetadata = new QueryInfoMetadata(placementId);
|
||||
QueryInfoCallback gmaQueryInfoCallback = new QueryInfoCallback(gmaQueryInfoMetadata, dispatchGroup);
|
||||
// Callback on the QueryInfoCallback is async here.
|
||||
_signalsStorage.put(placementId, gmaQueryInfoMetadata);
|
||||
QueryInfo.generate(context, adType, request, gmaQueryInfoCallback);
|
||||
}
|
||||
|
||||
private class GMAScarDispatchCompleted implements Runnable {
|
||||
|
||||
private ISignalCollectionListener _signalListener;
|
||||
|
||||
public GMAScarDispatchCompleted(ISignalCollectionListener signalListener) {
|
||||
_signalListener = signalListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Called once every dispatched thread has returned.
|
||||
// Build up the JSON response since we received all the signals.
|
||||
Map<String, String> _placementSignalMap = new HashMap<>();
|
||||
String errorMessage = null;
|
||||
for(Map.Entry<String, QueryInfoMetadata> queryInfoMetadata : _signalsStorage.getPlacementQueryInfoMap().entrySet()) {
|
||||
QueryInfoMetadata currentQueryMetadata = queryInfoMetadata.getValue();
|
||||
_placementSignalMap.put(currentQueryMetadata.getPlacementId(), currentQueryMetadata.getQueryStr());
|
||||
if (currentQueryMetadata.getError() != null) {
|
||||
// There is an error with one of the signals.
|
||||
errorMessage = currentQueryMetadata.getError();
|
||||
}
|
||||
}
|
||||
|
||||
if (_placementSignalMap.size() > 0) {
|
||||
JSONObject placementJSON = new JSONObject(_placementSignalMap);
|
||||
_signalListener.onSignalsCollected(placementJSON.toString());
|
||||
} else if (errorMessage == null){
|
||||
_signalListener.onSignalsCollected("");
|
||||
} else {
|
||||
// If no signals could be generated, send SIGNALS_ERROR with the last error message
|
||||
_signalListener.onSignalsCollectionFailed(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsStorage {
|
||||
private Map<String, QueryInfoMetadata> _placementQueryInfoMap = new HashMap<>();
|
||||
|
||||
public Map<String, QueryInfoMetadata> getPlacementQueryInfoMap() {
|
||||
return _placementQueryInfoMap;
|
||||
}
|
||||
|
||||
public QueryInfoMetadata getQueryInfoMetadata(String placementId) {
|
||||
return _placementQueryInfoMap.get(placementId);
|
||||
}
|
||||
|
||||
public void put(String key, QueryInfoMetadata value) {
|
||||
_placementQueryInfoMap.put(key, value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package com.unity3d.scar.adapter.v1920.signals;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsStorageTest {
|
||||
private static final String TEST_PLACEMENTID = "placementId";
|
||||
private static final String TEST_PLACEMENTID2 = "placementId2";
|
||||
|
||||
private QueryInfoMetadata queryInfoMetadataMock = Mockito.mock(QueryInfoMetadata.class);
|
||||
|
||||
@Test
|
||||
public void testSignalStorage() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
QueryInfoMetadata queryInfoMetadata = signalsStorage.getQueryInfoMetadata(TEST_PLACEMENTID);
|
||||
Assert.assertEquals(queryInfoMetadata, queryInfoMetadataMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignalStorageMultiplePlacements() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
signalsStorage.put(TEST_PLACEMENTID2, queryInfoMetadataMock);
|
||||
Map<String, QueryInfoMetadata> expectedStorageContent = new HashMap<String, QueryInfoMetadata>() {
|
||||
{
|
||||
put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
put(TEST_PLACEMENTID2, queryInfoMetadataMock);
|
||||
}
|
||||
};
|
||||
Map<String, QueryInfoMetadata> queryInfoMetadataMap = signalsStorage.getPlacementQueryInfoMap();
|
||||
Assert.assertEquals(expectedStorageContent, queryInfoMetadataMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignalStorageDuplicatePlacements() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
QueryInfoMetadata queryInfoMetadata = signalsStorage.getQueryInfoMetadata(TEST_PLACEMENTID);
|
||||
Assert.assertEquals(queryInfoMetadata, queryInfoMetadataMock);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,62 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
testCoverageEnabled true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation "org.mockito:mockito-android:2.25.0"
|
||||
androidTestImplementation 'com.google.android.gms:play-services-ads:19.5.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
testImplementation 'com.google.android.gms:play-services-ads:19.2.0'
|
||||
api project(':unity-scaradapter-common')
|
||||
compileOnly 'com.google.android.gms:play-services-ads:19.5.0'
|
||||
}
|
||||
|
||||
task deleteOldJar(type: Delete) {
|
||||
delete("../unity-ads/libs/${project.name}.jar")
|
||||
}
|
||||
|
||||
task copyJars(type: Copy) {
|
||||
from('build/intermediates/compile_library_classes_jar/release/')
|
||||
into('../unity-ads/libs/')
|
||||
include('classes.jar')
|
||||
rename('classes.jar', "${project.name}.jar")
|
||||
}
|
||||
|
||||
copyJars.dependsOn(deleteOldJar)
|
||||
|
||||
project.tasks.whenTaskAdded { Task theTask ->
|
||||
if (theTask.name == 'bundleLibCompileToJarRelease') {
|
||||
theTask.finalizedBy(copyJars)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,8 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v1950">>
|
||||
<application>
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="ca-app-pub-3940256099942544~3347511713"/>
|
||||
</application>
|
||||
</manifest>
|
|
@ -0,0 +1,13 @@
|
|||
package com.unity3d.ads.test;
|
||||
|
||||
import com.unity3d.scar.adapter.v1950.signals.SignalsReaderTest;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
SignalsReaderTest.class
|
||||
})
|
||||
public class InstrumentationTestSuite {
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SignalsReaderTest {
|
||||
private Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
private ISignalCollectionListener _signalCollectionListener;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
_signalCollectionListener = Mockito.mock(ISignalCollectionListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignals() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoRewarded() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoInterstitial() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v1950">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
</manifest>
|
|
@ -0,0 +1,59 @@
|
|||
package com.unity3d.scar.adapter.v1950;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.ScarAdapterBase;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1950.scarads.ScarInterstitialAd;
|
||||
import com.unity3d.scar.adapter.v1950.scarads.ScarRewardedAd;
|
||||
import com.unity3d.scar.adapter.v1950.signals.SignalsReader;
|
||||
import com.unity3d.scar.adapter.v1950.signals.SignalsStorage;
|
||||
|
||||
import static com.unity3d.scar.adapter.common.Utils.runOnUiThread;
|
||||
|
||||
public class ScarAdapter extends ScarAdapterBase implements IScarAdapter {
|
||||
|
||||
private SignalsStorage _scarSignalStorage;
|
||||
|
||||
public ScarAdapter(IAdsErrorHandler adsErrorHandler) {
|
||||
super(adsErrorHandler);
|
||||
_scarSignalStorage = new SignalsStorage();
|
||||
_scarSignalReader = new SignalsReader(_scarSignalStorage);
|
||||
}
|
||||
|
||||
public void loadInterstitialAd(Context context, final ScarAdMetadata scarAd, final IScarInterstitialAdListenerWrapper adListenerWrapper) {
|
||||
final ScarInterstitialAd interstitialAd = new ScarInterstitialAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
interstitialAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), interstitialAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadRewardedAd(Context context, final ScarAdMetadata scarAd, final IScarRewardedAdListenerWrapper adListenerWrapper) {
|
||||
final ScarRewardedAd rewardedAd = new ScarRewardedAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rewardedAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), rewardedAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v1950.scarads;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.AdInfo;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarAd;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1950.signals.QueryInfoMetadata;
|
||||
|
||||
public abstract class ScarAdBase implements IScarAd {
|
||||
|
||||
protected Context _context;
|
||||
protected ScarAdMetadata _scarAdMetadata;
|
||||
protected QueryInfoMetadata _queryInfoMetadata;
|
||||
protected IAdsErrorHandler _adsErrorHandler;
|
||||
|
||||
public ScarAdBase(Context context, ScarAdMetadata scarAdMetadata, QueryInfoMetadata queryInfoMetadata, IAdsErrorHandler adsErrorHandler) {
|
||||
_context = context;
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
_queryInfoMetadata = queryInfoMetadata;
|
||||
_adsErrorHandler = adsErrorHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAd(IScarLoadListener loadListener) {
|
||||
if (_queryInfoMetadata != null) {
|
||||
AdInfo adInfo = new AdInfo(_queryInfoMetadata.getQueryInfo(), _scarAdMetadata.getAdString());
|
||||
AdRequest adRequest = new AdRequest.Builder().setAdInfo(adInfo).build();
|
||||
loadAdInternal(loadListener, adRequest);
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalLoadError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest);
|
||||
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.unity3d.scar.adapter.v1950.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.InterstitialAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1950.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarInterstitialAd extends ScarAdBase {
|
||||
|
||||
private InterstitialAd _interstitialAd;
|
||||
private ScarInterstitialAdListener _interstitialAdDelegate;
|
||||
|
||||
public ScarInterstitialAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarInterstitialAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_interstitialAd = new InterstitialAd(_context);
|
||||
_interstitialAd.setAdUnitId(_scarAdMetadata.getAdUnitId());
|
||||
_interstitialAdDelegate = new ScarInterstitialAdListener(_interstitialAd, adListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest) {
|
||||
_interstitialAd.setAdListener(_interstitialAdDelegate.getAdListener());
|
||||
_interstitialAdDelegate.setLoadListener(loadListener);
|
||||
_interstitialAd.loadAd(adRequest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_interstitialAd.isLoaded()) {
|
||||
_interstitialAd.show();
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package com.unity3d.scar.adapter.v1950.scarads;
|
||||
|
||||
import com.google.android.gms.ads.AdListener;
|
||||
import com.google.android.gms.ads.InterstitialAd;
|
||||
import com.google.android.gms.ads.LoadAdError;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
|
||||
public class ScarInterstitialAdListener {
|
||||
|
||||
private InterstitialAd _interstitialAd;
|
||||
private IScarInterstitialAdListenerWrapper _adListenerWrapper;
|
||||
private IScarLoadListener _loadListener;
|
||||
|
||||
public ScarInterstitialAdListener(InterstitialAd interstitialAd, IScarInterstitialAdListenerWrapper adListenerWrapper) {
|
||||
_interstitialAd = interstitialAd;
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
}
|
||||
|
||||
private AdListener _adListener = new AdListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_adListenerWrapper.onAdLoaded();
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(LoadAdError adErrorCode) {
|
||||
_adListenerWrapper.onAdFailedToLoad(adErrorCode.getCode(), adErrorCode.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdOpened() {
|
||||
_adListenerWrapper.onAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClicked() {
|
||||
_adListenerWrapper.onAdClicked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdLeftApplication() {
|
||||
_adListenerWrapper.onAdLeftApplication();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdClosed() {
|
||||
_adListenerWrapper.onAdClosed();
|
||||
}
|
||||
};
|
||||
|
||||
public AdListener getAdListener() {
|
||||
return _adListener;
|
||||
}
|
||||
|
||||
public void setLoadListener(IScarLoadListener loadListener) {
|
||||
_loadListener = loadListener;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v1950.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v1950.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarRewardedAd extends ScarAdBase {
|
||||
|
||||
private RewardedAd _rewardedAd;
|
||||
private ScarRewardedAdListener _rewardedAdDelegate;
|
||||
|
||||
public ScarRewardedAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarRewardedAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_rewardedAd = new RewardedAd(_context, _scarAdMetadata.getAdUnitId());
|
||||
_rewardedAdDelegate = new ScarRewardedAdListener(_rewardedAd, adListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAdInternal(IScarLoadListener loadListener, AdRequest adRequest) {
|
||||
_rewardedAdDelegate.setLoadListener(loadListener);
|
||||
_rewardedAd.loadAd(adRequest, _rewardedAdDelegate.getRewardedAdLoadCallback());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_rewardedAd.isLoaded()) {
|
||||
_rewardedAd.show(activity, _rewardedAdDelegate.getRewardedAdCallback());
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package com.unity3d.scar.adapter.v1950.scarads;
|
||||
|
||||
import com.google.android.gms.ads.AdError;
|
||||
import com.google.android.gms.ads.LoadAdError;
|
||||
import com.google.android.gms.ads.rewarded.RewardItem;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAdCallback;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
|
||||
public class ScarRewardedAdListener {
|
||||
|
||||
private RewardedAd _rewardedAd;
|
||||
private IScarRewardedAdListenerWrapper _adListenerWrapper;
|
||||
private IScarLoadListener _loadListener;
|
||||
|
||||
public ScarRewardedAdListener(RewardedAd rewardedAd, IScarRewardedAdListenerWrapper adListenerWrapper) {
|
||||
_rewardedAd = rewardedAd;
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
}
|
||||
|
||||
private RewardedAdLoadCallback _rewardedAdLoadCallback = new RewardedAdLoadCallback() {
|
||||
@Override
|
||||
public void onRewardedAdLoaded() {
|
||||
_adListenerWrapper.onRewardedAdLoaded();
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToLoad(LoadAdError adError) {
|
||||
_adListenerWrapper.onRewardedAdFailedToLoad(adError.getCode(), adError.toString());
|
||||
}
|
||||
};
|
||||
|
||||
private RewardedAdCallback rewardedAdCallback = new RewardedAdCallback () {
|
||||
@Override
|
||||
public void onRewardedAdOpened() {
|
||||
_adListenerWrapper.onRewardedAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdFailedToShow(AdError adError) {
|
||||
_adListenerWrapper.onRewardedAdFailedToShow(adError.getCode(), adError.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUserEarnedReward(RewardItem rewardItem) {
|
||||
_adListenerWrapper.onUserEarnedReward();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRewardedAdClosed() {
|
||||
_adListenerWrapper.onRewardedAdClosed();
|
||||
}
|
||||
};
|
||||
|
||||
public RewardedAdCallback getRewardedAdCallback() {
|
||||
return rewardedAdCallback;
|
||||
}
|
||||
|
||||
public RewardedAdLoadCallback getRewardedAdLoadCallback() { return _rewardedAdLoadCallback; }
|
||||
|
||||
public void setLoadListener(IScarLoadListener loadListener) {
|
||||
_loadListener = loadListener;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.google.android.gms.ads.query.QueryInfoGenerationCallback;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.v1950.ScarAdapter;
|
||||
|
||||
public class QueryInfoCallback extends QueryInfoGenerationCallback {
|
||||
|
||||
private DispatchGroup _dispatchGroup;
|
||||
private QueryInfoMetadata _gmaQueryInfoMetadata;
|
||||
|
||||
public QueryInfoCallback(final QueryInfoMetadata gmaQueryInfoMetadata, final DispatchGroup dispatchGroup) {
|
||||
_dispatchGroup = dispatchGroup;
|
||||
_gmaQueryInfoMetadata = gmaQueryInfoMetadata;
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation succeeds
|
||||
@Override
|
||||
public void onSuccess(final QueryInfo queryInfo) {
|
||||
_gmaQueryInfoMetadata.setQueryInfo(queryInfo);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation fails
|
||||
@Override
|
||||
public void onFailure(String failureMsg) {
|
||||
_gmaQueryInfoMetadata.setError(failureMsg);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
|
||||
public class QueryInfoMetadata {
|
||||
private String _placementId;
|
||||
private QueryInfo _queryInfo;
|
||||
private String _error;
|
||||
|
||||
public QueryInfoMetadata(String placementId) {
|
||||
_placementId = placementId;
|
||||
}
|
||||
|
||||
public String getPlacementId() {
|
||||
return _placementId;
|
||||
}
|
||||
|
||||
public QueryInfo getQueryInfo() {
|
||||
return _queryInfo;
|
||||
}
|
||||
|
||||
public String getQueryStr() {
|
||||
String query = null;
|
||||
if (_queryInfo != null) {
|
||||
query = _queryInfo.getQuery();
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
public void setQueryInfo(QueryInfo queryInfo) {
|
||||
_queryInfo = queryInfo;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
_error = error;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdFormat;
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalsReader;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsReader implements ISignalsReader {
|
||||
private static SignalsStorage _signalsStorage;
|
||||
|
||||
public SignalsReader(SignalsStorage signalsStorage) {
|
||||
_signalsStorage = signalsStorage;
|
||||
}
|
||||
|
||||
public void getSCARSignals(Context context, String[] interstitialList, String[] rewardedList,
|
||||
ISignalCollectionListener signalCompletionListener) {
|
||||
DispatchGroup dispatchGroup = new DispatchGroup();
|
||||
|
||||
for (String interstitialId : interstitialList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, interstitialId, AdFormat.INTERSTITIAL, dispatchGroup);
|
||||
}
|
||||
|
||||
for (String rewardedId : rewardedList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, rewardedId, AdFormat.REWARDED, dispatchGroup);
|
||||
}
|
||||
|
||||
dispatchGroup.notify(new GMAScarDispatchCompleted(signalCompletionListener));
|
||||
}
|
||||
|
||||
private void getSCARSignal(Context context, String placementId, AdFormat adType, DispatchGroup dispatchGroup) {
|
||||
AdRequest request = new AdRequest.Builder().build();
|
||||
QueryInfoMetadata gmaQueryInfoMetadata = new QueryInfoMetadata(placementId);
|
||||
QueryInfoCallback gmaQueryInfoCallback = new QueryInfoCallback(gmaQueryInfoMetadata, dispatchGroup);
|
||||
// Callback on the QueryInfoCallback is async here.
|
||||
_signalsStorage.put(placementId, gmaQueryInfoMetadata);
|
||||
QueryInfo.generate(context, adType, request, gmaQueryInfoCallback);
|
||||
}
|
||||
|
||||
private class GMAScarDispatchCompleted implements Runnable {
|
||||
|
||||
private ISignalCollectionListener _signalListener;
|
||||
|
||||
public GMAScarDispatchCompleted(ISignalCollectionListener signalListener) {
|
||||
_signalListener = signalListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Called once every dispatched thread has returned.
|
||||
// Build up the JSON response since we received all the signals.
|
||||
Map<String, String> _placementSignalMap = new HashMap<>();
|
||||
String errorMessage = null;
|
||||
for(Map.Entry<String, QueryInfoMetadata> queryInfoMetadata : _signalsStorage.getPlacementQueryInfoMap().entrySet()) {
|
||||
QueryInfoMetadata currentQueryMetadata = queryInfoMetadata.getValue();
|
||||
_placementSignalMap.put(currentQueryMetadata.getPlacementId(), currentQueryMetadata.getQueryStr());
|
||||
if (currentQueryMetadata.getError() != null) {
|
||||
// There is an error with one of the signals.
|
||||
errorMessage = currentQueryMetadata.getError();
|
||||
}
|
||||
}
|
||||
|
||||
if (_placementSignalMap.size() > 0) {
|
||||
JSONObject placementJSON = new JSONObject(_placementSignalMap);
|
||||
_signalListener.onSignalsCollected(placementJSON.toString());
|
||||
} else if (errorMessage == null){
|
||||
_signalListener.onSignalsCollected("");
|
||||
} else {
|
||||
// If no signals could be generated, send SIGNALS_ERROR with the last error message
|
||||
_signalListener.onSignalsCollectionFailed(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsStorage {
|
||||
private Map<String, QueryInfoMetadata> _placementQueryInfoMap = new HashMap<>();
|
||||
|
||||
public Map<String, QueryInfoMetadata> getPlacementQueryInfoMap() {
|
||||
return _placementQueryInfoMap;
|
||||
}
|
||||
|
||||
public QueryInfoMetadata getQueryInfoMetadata(String placementId) {
|
||||
return _placementQueryInfoMap.get(placementId);
|
||||
}
|
||||
|
||||
public void put(String key, QueryInfoMetadata value) {
|
||||
_placementQueryInfoMap.put(key, value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package com.unity3d.scar.adapter.v1950.signals;
|
||||
|
||||
import android.app.DownloadManager;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsStorageTest {
|
||||
private static final String TEST_PLACEMENTID = "placementId";
|
||||
private static final String TEST_PLACEMENTID2 = "placementId2";
|
||||
|
||||
private QueryInfoMetadata queryInfoMetadataMock = Mockito.mock(QueryInfoMetadata.class);
|
||||
|
||||
@Test
|
||||
public void testSignalStorage() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
QueryInfoMetadata queryInfoMetadata = signalsStorage.getQueryInfoMetadata(TEST_PLACEMENTID);
|
||||
Assert.assertEquals(queryInfoMetadata, queryInfoMetadataMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignalStorageMultiplePlacements() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
signalsStorage.put(TEST_PLACEMENTID2, queryInfoMetadataMock);
|
||||
Map<String, QueryInfoMetadata> expectedStorageContent = new HashMap<String, QueryInfoMetadata>() {
|
||||
{
|
||||
put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
put(TEST_PLACEMENTID2, queryInfoMetadataMock);
|
||||
}
|
||||
};
|
||||
Map<String, QueryInfoMetadata> queryInfoMetadataMap = signalsStorage.getPlacementQueryInfoMap();
|
||||
Assert.assertEquals(expectedStorageContent, queryInfoMetadataMap);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSignalStorageDuplicatePlacements() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
signalsStorage.put(TEST_PLACEMENTID, queryInfoMetadataMock);
|
||||
QueryInfoMetadata queryInfoMetadata = signalsStorage.getQueryInfoMetadata(TEST_PLACEMENTID);
|
||||
Assert.assertEquals(queryInfoMetadata, queryInfoMetadataMock);
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/build
|
|
@ -0,0 +1,62 @@
|
|||
plugins {
|
||||
id 'com.android.library'
|
||||
}
|
||||
|
||||
android {
|
||||
compileSdkVersion 30
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
multiDexEnabled true
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
consumerProguardFiles "consumer-rules.pro"
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
release {
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
debug {
|
||||
minifyEnabled false
|
||||
testCoverageEnabled true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
|
||||
androidTestImplementation 'androidx.test:runner:1.3.0'
|
||||
androidTestImplementation "org.mockito:mockito-android:2.25.0"
|
||||
androidTestImplementation 'com.google.android.gms:play-services-ads:20.1.0'
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
testImplementation 'com.google.android.gms:play-services-ads:20.1.0'
|
||||
api project(':unity-scaradapter-common')
|
||||
compileOnly 'com.google.android.gms:play-services-ads:20.1.0'
|
||||
}
|
||||
|
||||
task deleteOldJar(type: Delete) {
|
||||
delete("../unity-ads/libs/${project.name}.jar")
|
||||
}
|
||||
|
||||
task copyJars(type: Copy) {
|
||||
from('build/intermediates/compile_library_classes_jar/release/')
|
||||
into('../unity-ads/libs/')
|
||||
include('classes.jar')
|
||||
rename('classes.jar', "${project.name}.jar")
|
||||
}
|
||||
|
||||
copyJars.dependsOn(deleteOldJar)
|
||||
|
||||
project.tasks.whenTaskAdded { Task theTask ->
|
||||
if (theTask.name == 'bundleLibCompileToJarRelease') {
|
||||
theTask.finalizedBy(copyJars)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
# Add project specific ProGuard rules here.
|
||||
# You can control the set of applied configuration files using the
|
||||
# proguardFiles setting in build.gradle.
|
||||
#
|
||||
# For more details, see
|
||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||
|
||||
# If your project uses WebView with JS, uncomment the following
|
||||
# and specify the fully qualified class name to the JavaScript interface
|
||||
# class:
|
||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||
# public *;
|
||||
#}
|
||||
|
||||
# Uncomment this to preserve the line number information for
|
||||
# debugging stack traces.
|
||||
#-keepattributes SourceFile,LineNumberTable
|
||||
|
||||
# If you keep the line number information, uncomment this to
|
||||
# hide the original source file name.
|
||||
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,9 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v2000">>
|
||||
<application>
|
||||
<activity android:name="android.app.Activity" />
|
||||
<meta-data
|
||||
android:name="com.google.android.gms.ads.APPLICATION_ID"
|
||||
android:value="ca-app-pub-3940256099942544~3347511713"/>
|
||||
</application>
|
||||
</manifest>
|
|
@ -0,0 +1,13 @@
|
|||
package com.unity3d.ads.test;
|
||||
|
||||
import com.unity3d.scar.adapter.v2000.signals.SignalsReaderTest;
|
||||
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.Suite;
|
||||
|
||||
@RunWith(Suite.class)
|
||||
@Suite.SuiteClasses({
|
||||
SignalsReaderTest.class
|
||||
})
|
||||
public class InstrumentationTestSuite {
|
||||
}
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -0,0 +1,101 @@
|
|||
package com.unity3d.scar.adapter.v2000;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.core.app.ActivityScenario;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static com.unity3d.scar.adapter.v2000.Constants.SCARExampleAdUnitId;
|
||||
import static com.unity3d.scar.adapter.v2000.Constants.SCARExampleInterstitialAdString;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ScarAdapterTest {
|
||||
private Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
|
||||
@Mock
|
||||
IAdsErrorHandler _adsErrorHandlerMock;
|
||||
|
||||
private ScarAdapter _scarAdapter = new ScarAdapter(_adsErrorHandlerMock);
|
||||
|
||||
@Mock
|
||||
ISignalCollectionListener _signalCollectionListenerMock;
|
||||
|
||||
@Mock
|
||||
IScarInterstitialAdListenerWrapper _scarInterstitialAdListenerWrapperMock;
|
||||
|
||||
@Test
|
||||
public void testScarAdapterGetSignals() {
|
||||
_scarAdapter.getSCARSignals(context, new String[]{"video"}, new String[]{"rewarded"}, _signalCollectionListenerMock);
|
||||
Mockito.verify(_signalCollectionListenerMock, Mockito.timeout(1000).times(1)).onSignalsCollected(Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterGetSignalsEmptyInterstitialPlacement() {
|
||||
_scarAdapter.getSCARSignals(context, new String[0], new String[]{"rewarded"}, _signalCollectionListenerMock);
|
||||
Mockito.verify(_signalCollectionListenerMock, Mockito.timeout(1000).times(1)).onSignalsCollected(Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterGetSignalsEmptyRewardedPlacement() {
|
||||
_scarAdapter.getSCARSignals(context, new String[]{"video"}, new String[0], _signalCollectionListenerMock);
|
||||
Mockito.verify(_signalCollectionListenerMock, Mockito.timeout(1000).times(1)).onSignalsCollected(Mockito.anyString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterLoad() {
|
||||
_scarAdapter.getSCARSignals(context, new String[]{"video"}, new String[0], _signalCollectionListenerMock);
|
||||
Mockito.verify(_signalCollectionListenerMock, Mockito.timeout(1000).times(1)).onSignalsCollected(Mockito.anyString());
|
||||
_scarAdapter.loadInterstitialAd(context, getDefaultScarMeta(), _scarInterstitialAdListenerWrapperMock);
|
||||
Mockito.verify(_scarInterstitialAdListenerWrapperMock, Mockito.timeout(5000).times(1)).onAdLoaded();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterLoadAndShow() {
|
||||
_scarAdapter.getSCARSignals(context, new String[]{"video"}, new String[0], _signalCollectionListenerMock);
|
||||
Mockito.verify(_signalCollectionListenerMock, Mockito.timeout(1000).times(1)).onSignalsCollected(Mockito.anyString());
|
||||
_scarAdapter.loadInterstitialAd(context, getDefaultScarMeta(), _scarInterstitialAdListenerWrapperMock);
|
||||
Mockito.verify(_scarInterstitialAdListenerWrapperMock, Mockito.timeout(5000).times(1)).onAdLoaded();
|
||||
try(ActivityScenario<Activity> scenario = ActivityScenario.launch(Activity.class)) {
|
||||
scenario.onActivity(new ActivityScenario.ActivityAction<Activity>() {
|
||||
@Override
|
||||
public void perform(Activity activity) {
|
||||
_scarAdapter.show(activity, "", "video");
|
||||
}
|
||||
});
|
||||
}
|
||||
Mockito.verify(_scarInterstitialAdListenerWrapperMock, Mockito.timeout(20000).times(1)).onAdOpened();
|
||||
Mockito.verify(_scarInterstitialAdListenerWrapperMock, Mockito.timeout(20000).times(1)).onAdImpression();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScarAdapterShowWithoutLoad() {
|
||||
_scarAdapter = new ScarAdapter(_adsErrorHandlerMock);
|
||||
try(ActivityScenario<Activity> scenario = ActivityScenario.launch(Activity.class)) {
|
||||
scenario.onActivity(new ActivityScenario.ActivityAction<Activity>() {
|
||||
@Override
|
||||
public void perform(Activity activity) {
|
||||
_scarAdapter.show(activity, "", "video");
|
||||
}
|
||||
});
|
||||
}
|
||||
Mockito.verify(_adsErrorHandlerMock, Mockito.timeout(20000).times(1)).handleError(Mockito.any(GMAAdsError.class));
|
||||
}
|
||||
|
||||
private ScarAdMetadata getDefaultScarMeta() {
|
||||
return new ScarAdMetadata("video", "", SCARExampleAdUnitId, SCARExampleInterstitialAdString, 30);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
|
||||
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 QueryInfoCallbackTest {
|
||||
@Mock
|
||||
QueryInfoMetadata _queryInfoMetadataMock;
|
||||
|
||||
@Mock
|
||||
DispatchGroup _dispatchGroupMock;
|
||||
|
||||
@Mock
|
||||
QueryInfo _queryInfoMock;
|
||||
|
||||
@Test
|
||||
public void testQueryInfoCallbackSuccess() {
|
||||
QueryInfoCallback queryInfoCallback = new QueryInfoCallback(_queryInfoMetadataMock, _dispatchGroupMock);
|
||||
queryInfoCallback.onSuccess(_queryInfoMock);
|
||||
Mockito.verify(_dispatchGroupMock, Mockito.times(1)).leave();
|
||||
Mockito.verify(_queryInfoMetadataMock, Mockito.times(1)).setQueryInfo(_queryInfoMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testQueryInfoCallbackError() {
|
||||
QueryInfoCallback queryInfoCallback = new QueryInfoCallback(_queryInfoMetadataMock, _dispatchGroupMock);
|
||||
queryInfoCallback.onFailure("");
|
||||
Mockito.verify(_dispatchGroupMock, Mockito.times(1)).leave();
|
||||
Mockito.verify(_queryInfoMetadataMock, Mockito.times(1)).setError(Mockito.anyString());
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SignalsReaderTest {
|
||||
private Context context = InstrumentationRegistry.getInstrumentation().getContext();
|
||||
private ISignalCollectionListener _signalCollectionListener;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
_signalCollectionListener = Mockito.mock(ISignalCollectionListener.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignals() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoRewarded() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{"video"}, new String[]{}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetScarSignalsNoInterstitial() {
|
||||
SignalsReader signalsReader = new SignalsReader(new SignalsStorage());
|
||||
signalsReader.getSCARSignals(context, new String[]{}, new String[]{"rewarded"}, _signalCollectionListener);
|
||||
Mockito.verify(_signalCollectionListener, Mockito.timeout(5000).times(1)).onSignalsCollected(any(String.class));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SignalsStorageTest {
|
||||
@Mock
|
||||
QueryInfoMetadata _queryInfoMetadaMock;
|
||||
|
||||
@Test
|
||||
public void testSignalStorage() {
|
||||
SignalsStorage signalsStorage = new SignalsStorage();
|
||||
signalsStorage.put("video", _queryInfoMetadaMock);
|
||||
QueryInfoMetadata storedMetadata = signalsStorage.getQueryInfoMetadata("video");
|
||||
Assert.assertEquals(_queryInfoMetadaMock, storedMetadata);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.unity3d.scar.adapter.v2000">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
</manifest>
|
|
@ -0,0 +1,59 @@
|
|||
package com.unity3d.scar.adapter.v2000;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.ScarAdapterBase;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v2000.scarads.ScarInterstitialAd;
|
||||
import com.unity3d.scar.adapter.v2000.scarads.ScarRewardedAd;
|
||||
import com.unity3d.scar.adapter.v2000.signals.SignalsReader;
|
||||
import com.unity3d.scar.adapter.v2000.signals.SignalsStorage;
|
||||
|
||||
import static com.unity3d.scar.adapter.common.Utils.runOnUiThread;
|
||||
|
||||
public class ScarAdapter extends ScarAdapterBase implements IScarAdapter {
|
||||
|
||||
private SignalsStorage _scarSignalStorage;
|
||||
|
||||
public ScarAdapter(IAdsErrorHandler adsErrorHandler) {
|
||||
super(adsErrorHandler);
|
||||
_scarSignalStorage = new SignalsStorage();
|
||||
_scarSignalReader = new SignalsReader(_scarSignalStorage);
|
||||
}
|
||||
|
||||
public void loadInterstitialAd(Context context, final ScarAdMetadata scarAd, final IScarInterstitialAdListenerWrapper adListenerWrapper) {
|
||||
final ScarInterstitialAd interstitialAd = new ScarInterstitialAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
interstitialAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), interstitialAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void loadRewardedAd(Context context, final ScarAdMetadata scarAd, final IScarRewardedAdListenerWrapper adListenerWrapper) {
|
||||
final ScarRewardedAd rewardedAd = new ScarRewardedAd(context, _scarSignalStorage.getQueryInfoMetadata(scarAd.getPlacementId()), scarAd, _adsErrorHandler, adListenerWrapper);
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
rewardedAd.loadAd(new IScarLoadListener() {
|
||||
@Override
|
||||
public void onAdLoaded() {
|
||||
_loadedAds.put(scarAd.getPlacementId(), rewardedAd);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.AdInfo;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarAd;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v2000.signals.QueryInfoMetadata;
|
||||
|
||||
public abstract class ScarAdBase<T> implements IScarAd {
|
||||
|
||||
protected T _adObj;
|
||||
protected Context _context;
|
||||
protected ScarAdMetadata _scarAdMetadata;
|
||||
protected QueryInfoMetadata _queryInfoMetadata;
|
||||
protected ScarAdListener _scarAdListener;
|
||||
protected IAdsErrorHandler _adsErrorHandler;
|
||||
|
||||
public ScarAdBase(Context context, ScarAdMetadata scarAdMetadata, QueryInfoMetadata queryInfoMetadata, IAdsErrorHandler adsErrorHandler) {
|
||||
_context = context;
|
||||
_scarAdMetadata = scarAdMetadata;
|
||||
_queryInfoMetadata = queryInfoMetadata;
|
||||
_adsErrorHandler = adsErrorHandler;
|
||||
}
|
||||
|
||||
public void setGmaAd(T rewardedAd) {
|
||||
_adObj = rewardedAd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAd(IScarLoadListener loadListener) {
|
||||
if (_queryInfoMetadata != null) {
|
||||
AdInfo adInfo = new AdInfo(_queryInfoMetadata.getQueryInfo(), _scarAdMetadata.getAdString());
|
||||
AdRequest adRequest = new AdRequest.Builder().setAdInfo(adInfo).build();
|
||||
_scarAdListener.setLoadListener(loadListener);
|
||||
loadAdInternal(adRequest, loadListener);
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalLoadError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract void loadAdInternal(AdRequest adRequest, IScarLoadListener loadListener);
|
||||
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
|
||||
public class ScarAdListener {
|
||||
protected IScarLoadListener _loadListener;
|
||||
|
||||
public void setLoadListener(IScarLoadListener loadListener) {
|
||||
_loadListener = loadListener;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.interstitial.InterstitialAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v2000.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarInterstitialAd extends ScarAdBase<InterstitialAd> {
|
||||
|
||||
public ScarInterstitialAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarInterstitialAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_scarAdListener = new ScarInterstitialAdListener(adListener, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdInternal(AdRequest adRequest, IScarLoadListener loadListener) {
|
||||
InterstitialAd.load(_context, _scarAdMetadata.getAdUnitId(), adRequest, ((ScarInterstitialAdListener)_scarAdListener).getAdLoadListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_adObj != null) {
|
||||
_adObj.show(activity);
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,70 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.android.gms.ads.AdError;
|
||||
import com.google.android.gms.ads.FullScreenContentCallback;
|
||||
import com.google.android.gms.ads.LoadAdError;
|
||||
import com.google.android.gms.ads.interstitial.InterstitialAd;
|
||||
import com.google.android.gms.ads.interstitial.InterstitialAdLoadCallback;
|
||||
import com.unity3d.scar.adapter.common.IScarInterstitialAdListenerWrapper;
|
||||
|
||||
public class ScarInterstitialAdListener extends ScarAdListener {
|
||||
private final ScarInterstitialAd _scarInterstitialAd;
|
||||
private final IScarInterstitialAdListenerWrapper _adListenerWrapper;
|
||||
|
||||
public ScarInterstitialAdListener(IScarInterstitialAdListenerWrapper adListenerWrapper, ScarInterstitialAd scarInterstitialAd) {
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
_scarInterstitialAd = scarInterstitialAd;
|
||||
}
|
||||
|
||||
private final InterstitialAdLoadCallback _adLoadCallback = new InterstitialAdLoadCallback() {
|
||||
@Override
|
||||
public void onAdLoaded(@NonNull InterstitialAd interstitialAd) {
|
||||
super.onAdLoaded(interstitialAd);
|
||||
_adListenerWrapper.onAdLoaded();
|
||||
interstitialAd.setFullScreenContentCallback(_fullScreenContentCallback);
|
||||
_scarInterstitialAd.setGmaAd(interstitialAd);
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
|
||||
super.onAdFailedToLoad(loadAdError);
|
||||
_adListenerWrapper.onAdFailedToLoad(loadAdError.getCode(), loadAdError.toString());
|
||||
}
|
||||
};
|
||||
|
||||
private final FullScreenContentCallback _fullScreenContentCallback = new FullScreenContentCallback() {
|
||||
@Override
|
||||
public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
|
||||
super.onAdFailedToShowFullScreenContent(adError);
|
||||
_adListenerWrapper.onAdFailedToShow(adError.getCode(), adError.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdShowedFullScreenContent() {
|
||||
super.onAdShowedFullScreenContent();
|
||||
_adListenerWrapper.onAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdDismissedFullScreenContent() {
|
||||
super.onAdDismissedFullScreenContent();
|
||||
_adListenerWrapper.onAdClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdImpression() {
|
||||
super.onAdImpression();
|
||||
_adListenerWrapper.onAdImpression();
|
||||
}
|
||||
};
|
||||
|
||||
public InterstitialAdLoadCallback getAdLoadListener() {
|
||||
return _adLoadCallback;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
import com.unity3d.scar.adapter.common.scarads.IScarLoadListener;
|
||||
import com.unity3d.scar.adapter.common.scarads.ScarAdMetadata;
|
||||
import com.unity3d.scar.adapter.v2000.signals.QueryInfoMetadata;
|
||||
|
||||
public class ScarRewardedAd extends ScarAdBase<RewardedAd> {
|
||||
|
||||
public ScarRewardedAd(Context context, QueryInfoMetadata queryInfoMetadata, ScarAdMetadata scarAdMetadata, IAdsErrorHandler adsErrorHandler, IScarRewardedAdListenerWrapper adListener) {
|
||||
super(context, scarAdMetadata, queryInfoMetadata, adsErrorHandler);
|
||||
_scarAdListener = new ScarRewardedAdListener(adListener, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAdInternal(AdRequest adRequest, IScarLoadListener loadListener) {
|
||||
RewardedAd.load(_context, _scarAdMetadata.getAdUnitId(), adRequest, ((ScarRewardedAdListener)_scarAdListener).getAdLoadListener());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show(Activity activity) {
|
||||
if (_adObj != null) {
|
||||
_adObj.show(activity, ((ScarRewardedAdListener)_scarAdListener).getOnUserEarnedRewardListener());
|
||||
} else {
|
||||
_adsErrorHandler.handleError(GMAAdsError.InternalShowError(_scarAdMetadata));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package com.unity3d.scar.adapter.v2000.scarads;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.android.gms.ads.AdError;
|
||||
import com.google.android.gms.ads.FullScreenContentCallback;
|
||||
import com.google.android.gms.ads.LoadAdError;
|
||||
import com.google.android.gms.ads.OnUserEarnedRewardListener;
|
||||
import com.google.android.gms.ads.rewarded.RewardItem;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAd;
|
||||
import com.google.android.gms.ads.rewarded.RewardedAdLoadCallback;
|
||||
import com.unity3d.scar.adapter.common.IScarRewardedAdListenerWrapper;
|
||||
|
||||
public class ScarRewardedAdListener extends ScarAdListener {
|
||||
|
||||
private final ScarRewardedAd _scarRewardedAd;
|
||||
private final IScarRewardedAdListenerWrapper _adListenerWrapper;
|
||||
|
||||
public ScarRewardedAdListener(IScarRewardedAdListenerWrapper adListenerWrapper, ScarRewardedAd scarRewardedAd) {
|
||||
_adListenerWrapper = adListenerWrapper;
|
||||
_scarRewardedAd = scarRewardedAd;
|
||||
}
|
||||
|
||||
private final RewardedAdLoadCallback _adLoadCallback = new RewardedAdLoadCallback() {
|
||||
@Override
|
||||
public void onAdLoaded(@NonNull RewardedAd rewardedAd) {
|
||||
super.onAdLoaded(rewardedAd);
|
||||
_adListenerWrapper.onRewardedAdLoaded();
|
||||
rewardedAd.setFullScreenContentCallback(_fullScreenContentCallback);
|
||||
_scarRewardedAd.setGmaAd(rewardedAd);
|
||||
if (_loadListener != null) {
|
||||
_loadListener.onAdLoaded();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdFailedToLoad(@NonNull LoadAdError loadAdError) {
|
||||
super.onAdFailedToLoad(loadAdError);
|
||||
_adListenerWrapper.onRewardedAdFailedToLoad(loadAdError.getCode(), loadAdError.toString());
|
||||
}
|
||||
};
|
||||
|
||||
private final OnUserEarnedRewardListener _onUserEarnedRewardListener = new OnUserEarnedRewardListener() {
|
||||
@Override
|
||||
public void onUserEarnedReward(@NonNull RewardItem rewardItem) {
|
||||
_adListenerWrapper.onUserEarnedReward();
|
||||
}
|
||||
};
|
||||
|
||||
private final FullScreenContentCallback _fullScreenContentCallback = new FullScreenContentCallback() {
|
||||
@Override
|
||||
public void onAdFailedToShowFullScreenContent(@NonNull AdError adError) {
|
||||
super.onAdFailedToShowFullScreenContent(adError);
|
||||
_adListenerWrapper.onRewardedAdFailedToShow(adError.getCode(), adError.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdShowedFullScreenContent() {
|
||||
super.onAdShowedFullScreenContent();
|
||||
_adListenerWrapper.onRewardedAdOpened();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdDismissedFullScreenContent() {
|
||||
super.onAdDismissedFullScreenContent();
|
||||
_adListenerWrapper.onRewardedAdClosed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAdImpression() {
|
||||
super.onAdImpression();
|
||||
_adListenerWrapper.onAdImpression();
|
||||
}
|
||||
};
|
||||
|
||||
public OnUserEarnedRewardListener getOnUserEarnedRewardListener() {
|
||||
return _onUserEarnedRewardListener;
|
||||
}
|
||||
|
||||
public RewardedAdLoadCallback getAdLoadListener() {
|
||||
return _adLoadCallback;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.google.android.gms.ads.query.QueryInfoGenerationCallback;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.v2000.ScarAdapter;
|
||||
|
||||
public class QueryInfoCallback extends QueryInfoGenerationCallback {
|
||||
|
||||
private DispatchGroup _dispatchGroup;
|
||||
private QueryInfoMetadata _gmaQueryInfoMetadata;
|
||||
|
||||
public QueryInfoCallback(final QueryInfoMetadata gmaQueryInfoMetadata, final DispatchGroup dispatchGroup) {
|
||||
_dispatchGroup = dispatchGroup;
|
||||
_gmaQueryInfoMetadata = gmaQueryInfoMetadata;
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation succeeds
|
||||
@Override
|
||||
public void onSuccess(final QueryInfo queryInfo) {
|
||||
_gmaQueryInfoMetadata.setQueryInfo(queryInfo);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
|
||||
// Called when QueryInfo generation fails
|
||||
@Override
|
||||
public void onFailure(String failureMsg) {
|
||||
_gmaQueryInfoMetadata.setError(failureMsg);
|
||||
_dispatchGroup.leave();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
|
||||
public class QueryInfoMetadata {
|
||||
private String _placementId;
|
||||
private QueryInfo _queryInfo;
|
||||
private String _error;
|
||||
|
||||
public QueryInfoMetadata(String placementId) {
|
||||
_placementId = placementId;
|
||||
}
|
||||
|
||||
public String getPlacementId() {
|
||||
return _placementId;
|
||||
}
|
||||
|
||||
public QueryInfo getQueryInfo() {
|
||||
return _queryInfo;
|
||||
}
|
||||
|
||||
public String getQueryStr() {
|
||||
String query = null;
|
||||
if (_queryInfo != null) {
|
||||
query = _queryInfo.getQuery();
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
public String getError() {
|
||||
return _error;
|
||||
}
|
||||
|
||||
public void setQueryInfo(QueryInfo queryInfo) {
|
||||
_queryInfo = queryInfo;
|
||||
}
|
||||
|
||||
public void setError(String error) {
|
||||
_error = error;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.google.android.gms.ads.AdFormat;
|
||||
import com.google.android.gms.ads.AdRequest;
|
||||
import com.google.android.gms.ads.query.QueryInfo;
|
||||
import com.unity3d.scar.adapter.common.DispatchGroup;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalCollectionListener;
|
||||
import com.unity3d.scar.adapter.common.signals.ISignalsReader;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsReader implements ISignalsReader {
|
||||
private static Map<String, String> _placementSignalMap;
|
||||
private static SignalsStorage _signalsStorage;
|
||||
|
||||
public SignalsReader(SignalsStorage signalsStorage) {
|
||||
_signalsStorage = signalsStorage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getSCARSignals(Context context, String[] interstitialList, String[] rewardedList,
|
||||
ISignalCollectionListener signalCompletionListener) {
|
||||
DispatchGroup dispatchGroup = new DispatchGroup();
|
||||
|
||||
for (String interstitialId : interstitialList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, interstitialId, AdFormat.INTERSTITIAL, dispatchGroup);
|
||||
}
|
||||
|
||||
for (String rewardedId : rewardedList) {
|
||||
dispatchGroup.enter();
|
||||
getSCARSignal(context, rewardedId, AdFormat.REWARDED, dispatchGroup);
|
||||
}
|
||||
|
||||
dispatchGroup.notify(new GMAScarDispatchCompleted(signalCompletionListener));
|
||||
}
|
||||
|
||||
private void getSCARSignal(Context context, String placementId, AdFormat adType, DispatchGroup dispatchGroup) {
|
||||
AdRequest request = new AdRequest.Builder().build();
|
||||
QueryInfoMetadata gmaQueryInfoMetadata = new QueryInfoMetadata(placementId);
|
||||
QueryInfoCallback gmaQueryInfoCallback = new QueryInfoCallback(gmaQueryInfoMetadata, dispatchGroup);
|
||||
// Callback on the QueryInfoCallback is async here.
|
||||
_signalsStorage.put(placementId, gmaQueryInfoMetadata);
|
||||
QueryInfo.generate(context, adType, request, gmaQueryInfoCallback);
|
||||
}
|
||||
|
||||
private class GMAScarDispatchCompleted implements Runnable {
|
||||
|
||||
private ISignalCollectionListener _signalListener;
|
||||
|
||||
public GMAScarDispatchCompleted(ISignalCollectionListener signalListener) {
|
||||
_signalListener = signalListener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
// Called once every dispatched thread has returned.
|
||||
// Build up the JSON response since we received all the signals.
|
||||
_placementSignalMap = new HashMap<>();
|
||||
String errorMessage = null;
|
||||
for(Map.Entry<String, QueryInfoMetadata> queryInfoMetadata : _signalsStorage.getPlacementQueryInfoMap().entrySet()) {
|
||||
QueryInfoMetadata currentQueryMetadata = queryInfoMetadata.getValue();
|
||||
_placementSignalMap.put(currentQueryMetadata.getPlacementId(), currentQueryMetadata.getQueryStr());
|
||||
if (currentQueryMetadata.getError() != null) {
|
||||
// There is an error with one of the signals.
|
||||
errorMessage = currentQueryMetadata.getError();
|
||||
}
|
||||
}
|
||||
|
||||
if (_placementSignalMap.size() > 0) {
|
||||
JSONObject placementJSON = new JSONObject(_placementSignalMap);
|
||||
_signalListener.onSignalsCollected(placementJSON.toString());
|
||||
} else if (errorMessage == null){
|
||||
_signalListener.onSignalsCollected("");
|
||||
} else {
|
||||
// If no signals could be generated, send SIGNALS_ERROR with the last error message
|
||||
_signalListener.onSignalsCollectionFailed(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.scar.adapter.v2000.signals;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class SignalsStorage {
|
||||
private Map<String, QueryInfoMetadata> _placementQueryInfoMap = new HashMap<>();
|
||||
|
||||
public Map<String, QueryInfoMetadata> getPlacementQueryInfoMap() {
|
||||
return _placementQueryInfoMap;
|
||||
}
|
||||
|
||||
public QueryInfoMetadata getQueryInfoMetadata(String placementId) {
|
||||
return _placementQueryInfoMap.get(placementId);
|
||||
}
|
||||
|
||||
public void put(String key, QueryInfoMetadata value) {
|
||||
_placementQueryInfoMap.put(key, value);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
/build
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче