Release 4.7.0
This commit is contained in:
Родитель
ce3cb3ab2c
Коммит
97924e9f4b
2
LICENSE
2
LICENSE
|
@ -1,4 +1,4 @@
|
|||
Unity Advertisements copyright © 2022 Unity Technologies.
|
||||
Unity Advertisements copyright © 2023 Unity Technologies.
|
||||
This software is subject to, and made available under, the terms of service for Operate Solutions (see https://unity3d.com/legal/one-operate-services-terms-of-service), and is an "Operate Service" as defined therein.
|
||||
|
||||
Your use of the Services constitutes your acceptance of such terms. Unless expressly provided otherwise, the software under this license is made available strictly on an "AS IS" BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED. Please review the terms of service for details on these and other terms and conditions.
|
|
@ -1,14 +1,14 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
android {
|
||||
compileSdkVersion 32
|
||||
compileSdkVersion 33
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.unity3d.ads.example"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 32
|
||||
versionCode = 4610
|
||||
versionName = "4.6.1"
|
||||
targetSdkVersion 33
|
||||
versionCode = 4700
|
||||
versionName = "4.7.0"
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
|
10
build.gradle
10
build.gradle
|
@ -7,12 +7,15 @@ allprojects {
|
|||
|
||||
buildscript {
|
||||
ext {
|
||||
kotlin_version = '1.4.32' // 1.5 deprecated Java6
|
||||
coroutines_version = '1.4.3' // 1.6.0 deprecated Java6
|
||||
kotlin_version = '1.8.10'
|
||||
coroutines_version = '1.6.4'
|
||||
dokka_version = '1.6.10'
|
||||
startup_runtime_version = '1.1.1'
|
||||
unity_identifiers_version = '1.0.0'
|
||||
lifecycle_version = '2.5.1'
|
||||
okhttp_version = '3.12.13' // 3.13+ requires Java8 / Android5+(21)
|
||||
androidx_webkit = '1.6.1'
|
||||
androidx_core = '1.9.0'
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -21,8 +24,7 @@ buildscript {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.1.3'
|
||||
classpath 'org.jacoco:org.jacoco.core:0.8.5'
|
||||
classpath 'com.android.tools.build:gradle:7.4.2'
|
||||
classpath 'org.jfrog.buildinfo:build-info-extractor-gradle:4.20.0'
|
||||
classpath 'io.github.gradle-nexus:publish-plugin:1.1.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
|
|
|
@ -14,6 +14,7 @@ static def tasksDependentOnScar(String buildType) {
|
|||
"merge${buildType}JavaResource",
|
||||
"sync${buildType}LibJars",
|
||||
"extract${buildType}Annotations",
|
||||
"desugar${buildType}FileDependencies",
|
||||
"dokkaJavadoc"
|
||||
]
|
||||
}
|
||||
|
|
|
@ -20,4 +20,7 @@ android.useAndroidX=true
|
|||
android.disableAutomaticComponentCreation=true
|
||||
|
||||
signing.keyId=34500891
|
||||
signing.secretKeyRingFile=../gpg-private-key.gpg
|
||||
signing.secretKeyRingFile=../gpg-private-key.gpg
|
||||
|
||||
# https://kotlinlang.org/docs/whatsnew18.html#usage-of-the-latest-kotlin-stdlib-version-in-transitive-dependencies
|
||||
kotlin.stdlib.jdk.variants.version.alignment=false
|
Двоичный файл не отображается.
|
@ -1,6 +1,6 @@
|
|||
#Thu Apr 08 20:52:07 EDT 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip
|
||||
networkTimeout=10000
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
|
||||
|
|
|
@ -1,79 +1,129 @@
|
|||
#!/usr/bin/env bash
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn ( ) {
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die ( ) {
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
nonstop=false
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched.
|
||||
if $cygwin ; then
|
||||
[ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
fi
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >&-
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >&-
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
@ -82,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
|
|||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
JAVACMD=java
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
|
@ -90,75 +140,105 @@ location of your Java installation."
|
|||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
|
|
@ -1,4 +1,20 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
|
@ -8,20 +24,24 @@
|
|||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
@ -35,7 +55,7 @@ goto fail
|
|||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
|
@ -45,44 +65,26 @@ echo location of your Java installation.
|
|||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
version: 1.0
|
||||
linter: jetbrains/qodana-jvm-android:2023.1-eap
|
||||
exclude:
|
||||
- name: All
|
||||
paths:
|
||||
- app
|
||||
- unity-scaradapter-1920
|
||||
- unity-scaradapter-1950
|
||||
- unity-scaradapter-2000
|
||||
- unity-scaradapter-2100
|
||||
- unity-scaradapter-common
|
||||
include:
|
||||
- name: SizeReplaceableByIsEmpty
|
|
@ -13,23 +13,20 @@ if (project.rootProject.file('local.properties').exists()) {
|
|||
ext {
|
||||
GROUP_ID = "com.unity3d.ads"
|
||||
ARTIFACT_ID = "unity-ads"
|
||||
VERSION_ID = "4.6.1"
|
||||
VERSION_CODE = 4610
|
||||
VERSION_ID = "4.7.0"
|
||||
VERSION_CODE = 4700
|
||||
SIGN_AAR = properties.getProperty("SIGN_AAR") ?: false
|
||||
}
|
||||
|
||||
android {
|
||||
namespace = GROUP_ID
|
||||
compileSdkVersion 32
|
||||
compileSdk 33
|
||||
compileSdkExtension 5
|
||||
DdmPreferences.setLogLevel("verbose")
|
||||
DdmPreferences.setTimeOut(10 * 60000)
|
||||
|
||||
lintOptions {
|
||||
abortOnError false
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
targetSdkVersion 32
|
||||
targetSdkVersion 33
|
||||
minSdkVersion 19
|
||||
versionCode = VERSION_CODE
|
||||
versionName = VERSION_ID
|
||||
|
@ -51,29 +48,8 @@ android {
|
|||
}
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_7
|
||||
targetCompatibility JavaVersion.VERSION_1_7
|
||||
}
|
||||
|
||||
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach {
|
||||
if (it.name.contains("UnitTest")) {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||
targetCompatibility = JavaVersion.VERSION_1_8
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
}
|
||||
} else {
|
||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||
targetCompatibility = JavaVersion.VERSION_1_6
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.6"
|
||||
}
|
||||
}
|
||||
kotlinOptions {
|
||||
apiVersion = "1.4"
|
||||
languageVersion = "1.4"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xopt-in=kotlin.RequiresOptIn" + "-Xallow-result-return-type"
|
||||
}
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
targetCompatibility JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
|
@ -88,16 +64,22 @@ android {
|
|||
consumerProguardFiles 'proguard-rules.pro'
|
||||
}
|
||||
}
|
||||
lint {
|
||||
abortOnError false
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
debugImplementation fileTree(dir: 'libs/Debug', include: ['*.jar'])
|
||||
releaseImplementation fileTree(dir: 'libs/Release', include: ['*.jar'])
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation(platform("org.jetbrains.kotlin:kotlin-bom:$kotlin_version"))
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$coroutines_version"
|
||||
implementation "androidx.startup:startup-runtime:$startup_runtime_version"
|
||||
implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version"
|
||||
implementation "com.unity3d.services.identifiers:unity-services-identifiers:$unity_identifiers_version"
|
||||
implementation "com.squareup.okhttp3:okhttp:$okhttp_version"
|
||||
implementation "androidx.webkit:webkit:$androidx_webkit"
|
||||
implementation "androidx.core:core-ktx:$androidx_core"
|
||||
androidTestCompileOnly project(':unity-scaradapter-2100')
|
||||
androidTestCompileOnly project(':unity-scaradapter-2000')
|
||||
androidTestCompileOnly project(':unity-scaradapter-1950')
|
||||
|
@ -120,16 +102,18 @@ dependencies {
|
|||
compileOnly project(':unity-scaradapter-1920')
|
||||
compileOnly project(':unity-scaradapter-common')
|
||||
testImplementation 'junit:junit:4.13.2'
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-stdlib"
|
||||
testImplementation "org.jetbrains.kotlin:kotlin-test-junit"
|
||||
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
|
||||
testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
|
||||
testImplementation 'org.mockito:mockito-core:2.28.2'
|
||||
testImplementation 'com.android.billingclient:billing:4.0.0'
|
||||
testImplementation "io.mockk:mockk:1.11.0"
|
||||
testImplementation("io.mockk:mockk:1.13.4")
|
||||
testImplementation 'org.json:json:20180813'
|
||||
testImplementation 'org.powermock:powermock-api-mockito2:2.0.2'
|
||||
testImplementation 'org.powermock:powermock-module-junit4:2.0.2'
|
||||
testImplementation "com.squareup.okhttp3:mockwebserver:$okhttp_version"
|
||||
|
||||
}
|
||||
|
||||
task androidSourcesJar(type: Jar) {
|
||||
|
@ -160,5 +144,4 @@ def getPropertyStringWithDefaultValue(String key, String defaultValue) {
|
|||
}
|
||||
|
||||
apply from: 'publishing.gradle'
|
||||
apply from: 'artifactory.gradle'
|
||||
apply from: 'jacoco.gradle'
|
||||
apply from: 'artifactory.gradle'
|
|
@ -1,26 +0,0 @@
|
|||
apply plugin: 'jacoco'
|
||||
|
||||
jacoco {
|
||||
toolVersion = '0.8.5'
|
||||
}
|
||||
|
||||
tasks.withType(Test) {
|
||||
jacoco.includeNoLocationClasses = true
|
||||
}
|
||||
|
||||
task jacocoTestReport(type: JacocoReport) {
|
||||
reports {
|
||||
xml.getRequired().set(true)
|
||||
html.getRequired().set(true)
|
||||
}
|
||||
|
||||
def fileFilter = ['**/R.class', '**/R$*.class', '**/BuildConfig.*', '**/Manifest*.*', '**/*Test*.*', 'android/**/*.*']
|
||||
def javaClasses = fileTree(dir: "$project.buildDir/intermediates/classes/debug", excludes: fileFilter)
|
||||
def javaSrc = "$project.projectDir/src/main/java"
|
||||
|
||||
sourceDirectories.setFrom(files([javaSrc]))
|
||||
classDirectories.setFrom(files([javaClasses]))
|
||||
executionData.setFrom(fileTree(dir: project.buildDir, includes: [
|
||||
'outputs/code-coverage/connected/*coverage.ec'
|
||||
]))
|
||||
}
|
|
@ -70,7 +70,7 @@ publishing {
|
|||
}
|
||||
|
||||
// List all dependencies and write to POM
|
||||
configurations.api.getAllDependencies().each cl
|
||||
configurations.implementation.getAllDependencies().each cl
|
||||
configurations.releaseImplementation.getAllDependencies().each cl
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.unity3d.ads.test.instrumentation.services.ads.webplayer.WebPlayerView
|
|||
import com.unity3d.ads.test.instrumentation.services.ads.webplayer.WebPlayerViewSettingsCacheTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.banners.BannerViewCacheTests;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.configuration.InitializationNotificationCenterTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.device.AsyncTokenStorageTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.device.InMemoryAsyncTokenStorageTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.device.DeviceInfoReaderCompressorTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.device.DeviceInfoReaderFilterProviderTest;
|
||||
import com.unity3d.ads.test.instrumentation.services.core.device.DeviceInfoReaderWithFilterTest;
|
||||
|
@ -52,7 +52,7 @@ import org.junit.runners.Suite;
|
|||
ShowModuleTests.class,
|
||||
ConfigurationTest.class,
|
||||
GmaScarTestSuite.class,
|
||||
AsyncTokenStorageTest.class,
|
||||
InMemoryAsyncTokenStorageTest.class,
|
||||
NativeTokenGeneratorTest.class,
|
||||
DeviceInfoReaderCompressorTest.class,
|
||||
DeviceInfoReaderFilterProviderTest.class,
|
||||
|
|
|
@ -22,10 +22,10 @@ import com.unity3d.ads.test.legacy.SdkPropertiesTest;
|
|||
import com.unity3d.ads.test.legacy.StorageDiskTest;
|
||||
import com.unity3d.ads.test.legacy.StorageGeneralTest;
|
||||
import com.unity3d.ads.test.legacy.StorageMemoryTest;
|
||||
import com.unity3d.ads.test.legacy.TokenStorageTest;
|
||||
import com.unity3d.ads.test.legacy.InMemoryTokenStorageTest;
|
||||
import com.unity3d.ads.test.legacy.UtilitiesTest;
|
||||
import com.unity3d.ads.test.legacy.VideoViewTest;
|
||||
import com.unity3d.ads.test.legacy.VolumeChangeTest;
|
||||
import com.unity3d.ads.test.legacy.VolumeChangeContentObserverTest;
|
||||
import com.unity3d.ads.test.legacy.WebPlayerViewTest;
|
||||
import com.unity3d.ads.test.legacy.WebRequestThreadPoolTest;
|
||||
import com.unity3d.ads.test.legacy.WebViewAppTest;
|
||||
|
@ -65,12 +65,12 @@ import org.junit.runners.Suite;
|
|||
WebViewBridgeTest.class,
|
||||
WebViewCallbackTest.class,
|
||||
LifecycleListenerTest.class,
|
||||
VolumeChangeTest.class,
|
||||
VolumeChangeContentObserverTest.class,
|
||||
UtilitiesTest.class,
|
||||
WebPlayerViewTest.class,
|
||||
PreferencesTest.class,
|
||||
WebRequestThreadPoolTest.class,
|
||||
TokenStorageTest.class
|
||||
InMemoryTokenStorageTest.class
|
||||
})
|
||||
|
||||
public class LegacyTestSuite {}
|
||||
|
|
|
@ -78,10 +78,10 @@ public class HybridTest {
|
|||
|
||||
private class HybridTestConfiguration extends Configuration {
|
||||
@Override
|
||||
public String[] getModuleConfigurationList () {
|
||||
ArrayList<String> moduleConfigurationList = new ArrayList<>(Arrays.asList(super.getModuleConfigurationList()));
|
||||
moduleConfigurationList.add("com.unity3d.ads.test.hybrid.HybridTestModuleConfiguration");
|
||||
return moduleConfigurationList.toArray(new String[moduleConfigurationList.size()]);
|
||||
public Class<?>[] getModuleConfigurationList () {
|
||||
ArrayList<Class> moduleConfigurationList = new ArrayList<>(Arrays.asList(super.getModuleConfigurationList()));
|
||||
moduleConfigurationList.add(HybridTestModuleConfiguration.class);
|
||||
return moduleConfigurationList.toArray(new Class[moduleConfigurationList.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -14,9 +14,6 @@ public class HybridTestModuleConfiguration implements IModuleConfiguration {
|
|||
public boolean resetState(Configuration configuration) {
|
||||
return true;
|
||||
}
|
||||
public boolean initModuleState(Configuration configuration) {
|
||||
return true;
|
||||
}
|
||||
public boolean initErrorState(Configuration configuration, ErrorState state, String message) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ 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.scar.adapter.common.WebViewAdsError;
|
||||
import com.unity3d.services.ads.gmascar.adapters.ScarAdapterFactory;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarAdapterVersion;
|
||||
|
||||
|
@ -14,9 +15,9 @@ import org.mockito.junit.MockitoJUnitRunner;
|
|||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ScarAdapterFactoryTest {
|
||||
@Mock
|
||||
private IAdsErrorHandler adsErrorHandlerMock;
|
||||
private IAdsErrorHandler<WebViewAdsError> adsErrorHandlerMock;
|
||||
|
||||
private ScarAdapterFactory _scarAdapterFactory = new ScarAdapterFactory();
|
||||
private final ScarAdapterFactory _scarAdapterFactory = new ScarAdapterFactory();
|
||||
|
||||
@Test
|
||||
public void testScarAdapterFactory1920() {
|
||||
|
|
|
@ -11,7 +11,7 @@ import com.unity3d.services.ads.gmascar.managers.BiddingBaseManager;
|
|||
import com.unity3d.services.ads.gmascar.models.BiddingSignals;
|
||||
import com.unity3d.services.ads.gmascar.utils.ScarRequestHandler;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.request.metrics.ScarMetric;
|
||||
|
||||
|
@ -31,7 +31,7 @@ public class BiddingBaseManagerTest {
|
|||
IUnityAdsTokenListener publisherListener;
|
||||
|
||||
@Mock
|
||||
ISDKMetrics _metricSenderMock;
|
||||
SDKMetricsSender _metricSenderMock;
|
||||
|
||||
@Mock
|
||||
ScarRequestHandler _scarRequestHandlerMock;
|
||||
|
|
|
@ -15,7 +15,7 @@ import com.unity3d.services.ads.operation.load.LoadOperation;
|
|||
import com.unity3d.services.ads.operation.load.LoadOperationState;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.IWebViewBridgeInvocation;
|
||||
|
@ -42,13 +42,13 @@ public class BaseLoadModuleTests {
|
|||
private IWebViewBridgeInvoker webViewBridgeInvokerMock;
|
||||
private IUnityAdsLoadListener loadListenerMock;
|
||||
private BaseLoadModule baseLoadModule;
|
||||
private ISDKMetrics sdkMetrics;
|
||||
private SDKMetricsSender sdkMetrics;
|
||||
|
||||
@Before
|
||||
public void beforeEachTest() {
|
||||
webViewBridgeInvokerMock = mock(IWebViewBridgeInvoker.class);
|
||||
loadListenerMock = mock(IUnityAdsLoadListener.class);
|
||||
sdkMetrics = mock(ISDKMetrics.class);
|
||||
sdkMetrics = mock(SDKMetricsSender.class);
|
||||
baseLoadModule = new LoadModule(sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.unity3d.services.ads.operation.load.LoadBannerOperationState;
|
|||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
|
@ -39,7 +39,7 @@ public class LoadBannerModuleTests {
|
|||
private IWebViewBridgeInvoker webViewBridgeInvokerMock;
|
||||
private IUnityAdsLoadListener loadListenerMock;
|
||||
private LoadBannerModule loadBannerModule;
|
||||
private ISDKMetrics sdkMetrics;
|
||||
private SDKMetricsSender sdkMetrics;
|
||||
|
||||
final ArgumentCaptor<JSONObject> parametersCaptor = ArgumentCaptor.forClass(JSONObject.class);
|
||||
|
||||
|
@ -48,7 +48,7 @@ public class LoadBannerModuleTests {
|
|||
public void beforeEachTest() {
|
||||
webViewBridgeInvokerMock = mock(IWebViewBridgeInvoker.class);
|
||||
loadListenerMock = mock(IUnityAdsLoadListener.class);
|
||||
sdkMetrics = mock(ISDKMetrics.class);
|
||||
sdkMetrics = mock(SDKMetricsSender.class);
|
||||
loadBannerModule = new LoadBannerModule(sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ import com.unity3d.services.core.configuration.Configuration;
|
|||
import com.unity3d.services.core.configuration.ErrorState;
|
||||
import com.unity3d.services.core.configuration.IInitializationNotificationCenter;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -29,7 +29,7 @@ public class LoadModuleDecoratorInitializationBufferTests {
|
|||
private IInitializationNotificationCenter initializationNotificationCenterMock;
|
||||
private IWebViewBridgeInvoker webViewBridgeInvokerMock;
|
||||
private LoadOperationState loadOperationStateMock;
|
||||
private ISDKMetrics sdkMetrics;
|
||||
private SDKMetricsSender sdkMetrics;
|
||||
|
||||
@Before
|
||||
public void beforeEachTest() {
|
||||
|
@ -37,7 +37,7 @@ public class LoadModuleDecoratorInitializationBufferTests {
|
|||
initializationNotificationCenterMock = mock(IInitializationNotificationCenter.class);
|
||||
webViewBridgeInvokerMock = mock(IWebViewBridgeInvoker.class);
|
||||
loadOperationStateMock = mock(LoadOperationState.class);
|
||||
sdkMetrics = mock(ISDKMetrics.class);
|
||||
sdkMetrics = mock(SDKMetricsSender.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -15,7 +15,7 @@ import com.unity3d.services.ads.operation.load.LoadModuleDecoratorTimeout;
|
|||
import com.unity3d.services.ads.operation.load.LoadOperationState;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
import org.junit.Before;
|
||||
|
@ -34,14 +34,14 @@ public class LoadModuleDecoratorTimeoutTests {
|
|||
|
||||
private IUnityAdsLoadListener loadListenerMock;
|
||||
private ILoadModule loadModuleMock;
|
||||
private ISDKMetrics sdkMetricsMock;
|
||||
private SDKMetricsSender sdkMetricsMock;
|
||||
private ConfigurationReader configurationReaderMock;
|
||||
|
||||
@Before
|
||||
public void beforeEachTest() {
|
||||
loadListenerMock = mock(IUnityAdsLoadListener.class);
|
||||
loadModuleMock = mock(ILoadModule.class);
|
||||
sdkMetricsMock = mock(ISDKMetrics.class);
|
||||
sdkMetricsMock = mock(SDKMetricsSender.class);
|
||||
configurationReaderMock = mock(ConfigurationReader.class);
|
||||
|
||||
Mockito.when(configurationReaderMock.getCurrentConfiguration()).thenReturn(new Configuration());
|
||||
|
|
|
@ -2,25 +2,16 @@ package com.unity3d.ads.test.instrumentation.services.ads.operation;
|
|||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyString;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.timeout;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsLoadListener;
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.ads.UnityAdsLoadOptions;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerOperationState;
|
||||
import com.unity3d.services.ads.operation.load.LoadModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadOperation;
|
||||
import com.unity3d.services.ads.operation.load.LoadOperationState;
|
||||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.IWebViewBridgeInvocation;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -45,7 +36,7 @@ public class LoadModuleTests {
|
|||
private IWebViewBridgeInvoker webViewBridgeInvokerMock;
|
||||
private IUnityAdsLoadListener loadListenerMock;
|
||||
private LoadModule loadModule;
|
||||
private ISDKMetrics sdkMetrics;
|
||||
private SDKMetricsSender sdkMetrics;
|
||||
|
||||
final ArgumentCaptor<JSONObject> parametersCaptor = ArgumentCaptor.forClass(JSONObject.class);
|
||||
|
||||
|
@ -54,7 +45,7 @@ public class LoadModuleTests {
|
|||
public void beforeEachTest() {
|
||||
webViewBridgeInvokerMock = mock(IWebViewBridgeInvoker.class);
|
||||
loadListenerMock = mock(IUnityAdsLoadListener.class);
|
||||
sdkMetrics = mock(ISDKMetrics.class);
|
||||
sdkMetrics = mock(SDKMetricsSender.class);
|
||||
loadModule = new LoadModule(sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ import com.unity3d.services.ads.operation.show.ShowModuleDecoratorTimeout;
|
|||
import com.unity3d.services.ads.operation.show.ShowOperationState;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.WebViewBridgeInvocationRunnable;
|
||||
|
@ -40,7 +40,7 @@ public class ShowModuleDecoratorTimeoutTests {
|
|||
|
||||
private IUnityAdsShowListener showListenerMock;
|
||||
private IShowModule showModule;
|
||||
private ISDKMetrics sdkMetricsMock;
|
||||
private SDKMetricsSender sdkMetricsMock;
|
||||
private ConfigurationReader configurationReaderMock;
|
||||
|
||||
@Rule
|
||||
|
@ -49,7 +49,7 @@ public class ShowModuleDecoratorTimeoutTests {
|
|||
@Before
|
||||
public void beforeEachTest() {
|
||||
showListenerMock = mock(IUnityAdsShowListener.class);
|
||||
sdkMetricsMock = mock(ISDKMetrics.class);
|
||||
sdkMetricsMock = mock(SDKMetricsSender.class);
|
||||
configurationReaderMock = mock(ConfigurationReader.class);
|
||||
// We need a real instance since ShowModule will create the Operation object (which holds the State with Listener ID)
|
||||
showModule = new ShowModule(sdkMetricsMock);
|
||||
|
|
|
@ -18,7 +18,7 @@ import com.unity3d.services.ads.operation.show.ShowOperation;
|
|||
import com.unity3d.services.ads.operation.show.ShowOperationState;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.IWebViewBridgeInvocation;
|
||||
|
@ -43,7 +43,7 @@ public class ShowModuleTests {
|
|||
|
||||
private IUnityAdsShowListener _showListenerMock;
|
||||
private IShowModule _showModule;
|
||||
private ISDKMetrics _sdkMetrics;
|
||||
private SDKMetricsSender _sdkMetrics;
|
||||
private IWebViewBridgeInvoker _webViewBridgeInvokerMock;
|
||||
|
||||
@Rule
|
||||
|
@ -53,7 +53,7 @@ public class ShowModuleTests {
|
|||
public void beforeEachTest() {
|
||||
_showListenerMock = mock(IUnityAdsShowListener.class);
|
||||
_webViewBridgeInvokerMock = mock(IWebViewBridgeInvoker.class);
|
||||
_sdkMetrics = mock(ISDKMetrics.class);
|
||||
_sdkMetrics = mock(SDKMetricsSender.class);
|
||||
_showModule = new ShowModule(_sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,17 +3,25 @@ package com.unity3d.ads.test.instrumentation.services.banners;
|
|||
import androidx.test.rule.ActivityTestRule;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.ads.test.instrumentation.InstrumentationTestActivity;
|
||||
import com.unity3d.services.ads.operation.load.ILoadModule;
|
||||
import com.unity3d.services.ads.operation.load.ILoadOperation;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadOperationState;
|
||||
import com.unity3d.services.banners.BannerErrorCode;
|
||||
import com.unity3d.services.banners.BannerErrorInfo;
|
||||
import com.unity3d.services.banners.BannerView;
|
||||
import com.unity3d.services.banners.UnityBannerSize;
|
||||
import com.unity3d.services.banners.BannerViewCache;
|
||||
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
@ -94,20 +102,46 @@ public class BannerViewCacheTests {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testTriggerBannerErrorEvent() throws InterruptedException {
|
||||
public void testTriggerBannerErrorEvent() throws InterruptedException, NoSuchFieldException, IllegalAccessException {
|
||||
BannerViewCache bannerViewCache = new BannerViewCache();
|
||||
final BannerView bannerView = new BannerView(_activityRule.getActivity(), "test", new UnityBannerSize(320, 50));
|
||||
final BannerErrorInfo bannerErrorInfo = new BannerErrorInfo("test error", BannerErrorCode.NATIVE_ERROR);
|
||||
String bannerAdId = bannerViewCache.addBannerView(bannerView);
|
||||
|
||||
LoadOperationState loadOperationState = Mockito.mock(LoadOperationState.class);
|
||||
Mockito.when(loadOperationState.isBanner()).thenReturn(true);
|
||||
Mockito.when(loadOperationState.duration()).thenReturn(Long.MAX_VALUE);
|
||||
loadOperationState.placementId = "test";
|
||||
|
||||
ILoadOperation loadOperation = Mockito.mock(ILoadOperation.class);
|
||||
Mockito.when(loadOperation.getLoadOperationState()).thenReturn(loadOperationState);
|
||||
|
||||
ILoadModule loadBannerModule = new LoadBannerModule(Mockito.mock(SDKMetricsSender.class));
|
||||
ILoadModule spy = Mockito.spy(loadBannerModule);
|
||||
Mockito.when(spy.get(Mockito.anyString())).thenReturn(loadOperation);
|
||||
Mockito.doAnswer(invocation -> {
|
||||
Mockito.doAnswer(invocation1 -> {
|
||||
LoadOperationState state = invocation.getArgument(1);
|
||||
state.onUnityAdsFailedToLoad(UnityAds.UnityAdsLoadError.INTERNAL_ERROR, "test error");
|
||||
return null;
|
||||
}).when(loadOperation).onUnityAdsFailedToLoad(Mockito.anyString(), Mockito.any(), Mockito.any());
|
||||
return null;
|
||||
}).when(spy).executeAdOperation(Mockito.any(), Mockito.any());
|
||||
|
||||
Field instance = LoadBannerModule.class.getDeclaredField("_instance");
|
||||
instance.setAccessible(true);
|
||||
instance.set(LoadBannerModule.class, spy);
|
||||
|
||||
final Semaphore _errorSemaphore = new Semaphore(0);
|
||||
bannerView.setListener(new BannerView.Listener() {
|
||||
@Override
|
||||
public void onBannerFailedToLoad(BannerView bannerAdView, BannerErrorInfo _bannerErrorInfo) {
|
||||
assertEquals(bannerView, bannerAdView);
|
||||
assertEquals(bannerErrorInfo, _bannerErrorInfo);
|
||||
Mockito.verify(spy).onUnityAdsFailedToLoad(bannerAdId, UnityAds.UnityAdsLoadError.INTERNAL_ERROR, "test error");
|
||||
_errorSemaphore.release();
|
||||
}
|
||||
});
|
||||
bannerView.load();
|
||||
bannerViewCache.triggerBannerErrorEvent(bannerAdId, bannerErrorInfo);
|
||||
_errorSemaphore.acquire();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.core.device;
|
||||
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.AUID_ID_KEY;
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.SESSION_ID_KEY;
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.USER_NON_BEHAVIORAL_KEY;
|
||||
|
||||
import android.app.Application;
|
||||
|
@ -11,7 +13,7 @@ import com.unity3d.services.core.configuration.ConfigurationReader;
|
|||
import com.unity3d.services.core.configuration.Experiments;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfig;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.device.reader.IGameSessionIdReader;
|
||||
import com.unity3d.services.core.lifecycle.CachedLifecycle;
|
||||
|
@ -61,11 +63,26 @@ public class DeviceInfoReaderBuilderTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderBuilderWithPrivacy() {
|
||||
public void testDeviceInfoReaderBuilderWithoutSnb() {
|
||||
Mockito.when(_privacyConfigMock.allowedToSendPii()).thenReturn(true);
|
||||
Mockito.when(_privacyConfigMock.shouldSendNonBehavioral()).thenReturn(false);
|
||||
DeviceInfoReaderBuilder deviceInfoReaderBuilder = new DeviceInfoReaderBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
Assert.assertNull(deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
Assert.assertNotNull(deviceInfoData.get(SESSION_ID_KEY));
|
||||
Assert.assertNotNull(deviceInfoData.get(AUID_ID_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderBuilderWithSnb() {
|
||||
Mockito.when(_privacyConfigMock.allowedToSendPii()).thenReturn(true);
|
||||
Mockito.when(_privacyConfigMock.shouldSendNonBehavioral()).thenReturn(true);
|
||||
DeviceInfoReaderBuilder deviceInfoReaderBuilder = new DeviceInfoReaderBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
Assert.assertNotNull(deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
Assert.assertNotNull(deviceInfoData.get(SESSION_ID_KEY));
|
||||
Assert.assertNotNull(deviceInfoData.get(AUID_ID_KEY));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,18 +4,21 @@ import android.app.Application;
|
|||
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.ads.metadata.MetaData;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.Experiments;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfig;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderPrivacyBuilder;
|
||||
import com.unity3d.services.core.device.Storage;
|
||||
import com.unity3d.services.core.device.StorageManager;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.device.reader.IGameSessionIdReader;
|
||||
import com.unity3d.services.core.lifecycle.CachedLifecycle;
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderPrivacyBuilder;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -58,12 +61,57 @@ public class DeviceInfoReaderPrivacyBuilderTest {
|
|||
Mockito.when(_configReaderMock.getCurrentConfiguration()).thenReturn(_configurationMock);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
StorageManager.getStorage(StorageManager.StorageType.PUBLIC).clearStorage();
|
||||
StorageManager.getStorage(StorageManager.StorageType.PUBLIC).initStorage();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderPrivacyBuilder() {
|
||||
DeviceInfoReaderPrivacyBuilder deviceInfoReaderPrivacyBuilder = new DeviceInfoReaderPrivacyBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderPrivacyBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
validatePrivacyGenerics(deviceInfoData);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderPrivacyBuilderSettingNonBehavioralTrue() {
|
||||
setUserNonBehavioralFlag(true);
|
||||
DeviceInfoReaderPrivacyBuilder deviceInfoReaderPrivacyBuilder = new DeviceInfoReaderPrivacyBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderPrivacyBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
validatePrivacyGenerics(deviceInfoData);
|
||||
Assert.assertTrue((Boolean) deviceInfoData.get("user.nonBehavioral"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderPrivacyBuilderSettingNonBehavioralFalse() {
|
||||
setUserNonBehavioralFlag(false);
|
||||
DeviceInfoReaderPrivacyBuilder deviceInfoReaderPrivacyBuilder = new DeviceInfoReaderPrivacyBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderPrivacyBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
validatePrivacyGenerics(deviceInfoData);
|
||||
Assert.assertFalse((Boolean) deviceInfoData.get("user.nonBehavioral"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderPrivacyBuilderSettingNonBehavioralMissing() {
|
||||
DeviceInfoReaderPrivacyBuilder deviceInfoReaderPrivacyBuilder = new DeviceInfoReaderPrivacyBuilder(_configReaderMock, _privacyConfigStorageMock, _gameSessionIdReaderMock);
|
||||
IDeviceInfoReader deviceInfoReader = deviceInfoReaderPrivacyBuilder.build();
|
||||
Map<String, Object> deviceInfoData = deviceInfoReader.getDeviceInfoData();
|
||||
validatePrivacyGenerics(deviceInfoData);
|
||||
Assert.assertNull(deviceInfoData.get("user.nonBehavioral"));
|
||||
}
|
||||
|
||||
private void validatePrivacyGenerics(Map<String, Object> deviceInfoData) {
|
||||
Assert.assertEquals("privacy", deviceInfoData.get("callType"));
|
||||
Assert.assertEquals(SdkProperties.getVersionName(), deviceInfoData.get("sdkVersionName"));
|
||||
}
|
||||
|
||||
private void setUserNonBehavioralFlag(boolean flagValue) {
|
||||
MetaData userMetaData = new MetaData(InstrumentationRegistry.getInstrumentation().getContext());
|
||||
userMetaData.set("user.nonbehavioral", flagValue);
|
||||
userMetaData.commit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.core.device;
|
||||
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.USER_NON_BEHAVIORAL_KEY;
|
||||
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderWithBehavioralFlag;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.device.reader.pii.NonBehavioralFlag;
|
||||
import com.unity3d.services.core.device.reader.pii.NonBehavioralFlagReader;
|
||||
|
||||
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 java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DeviceInfoReaderWithNonBehavioralFlagTest {
|
||||
@Mock
|
||||
private IDeviceInfoReader _deviceInfoReaderMock;
|
||||
|
||||
@Mock
|
||||
private NonBehavioralFlagReader _nonBehavioralFlagReaderMock;
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithBehavioralFlagWhenBehavioralFlagFalse() {
|
||||
// given
|
||||
Mockito.when(_nonBehavioralFlagReaderMock.getUserNonBehavioralFlag()).thenReturn(NonBehavioralFlag.FALSE);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithBehavioralFlag deviceInfoReaderWithBehavioralFlag = new DeviceInfoReaderWithBehavioralFlag(_deviceInfoReaderMock, _nonBehavioralFlagReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithBehavioralFlag.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(false, deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithBehavioralFlagWhenBehavioralFlagTrue() {
|
||||
// given
|
||||
Mockito.when(_nonBehavioralFlagReaderMock.getUserNonBehavioralFlag()).thenReturn(NonBehavioralFlag.TRUE);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithBehavioralFlag deviceInfoReaderWithBehavioralFlag = new DeviceInfoReaderWithBehavioralFlag(_deviceInfoReaderMock, _nonBehavioralFlagReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithBehavioralFlag.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(true, deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithBehavioralFlagWhenBehavioralFlagUnknown() {
|
||||
// given
|
||||
Mockito.when(_nonBehavioralFlagReaderMock.getUserNonBehavioralFlag()).thenReturn(NonBehavioralFlag.UNKNOWN);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithBehavioralFlag deviceInfoReaderWithBehavioralFlag = new DeviceInfoReaderWithBehavioralFlag(_deviceInfoReaderMock, _nonBehavioralFlagReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithBehavioralFlag.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertNull(deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,91 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.core.device;
|
||||
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.USER_NON_BEHAVIORAL_KEY;
|
||||
|
||||
import com.unity3d.services.core.configuration.PrivacyConfig;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderWithPrivacy;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.device.reader.pii.PiiDataProvider;
|
||||
import com.unity3d.services.core.device.reader.pii.PiiTrackingStatusReader;
|
||||
|
||||
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;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DeviceInfoReaderWithPrivacyTest {
|
||||
private static final String FAKE_ADVERTISER_ID = "fakeSessionId";
|
||||
private static final boolean FAKE_NONBEHAVIORAL = true;
|
||||
|
||||
@Mock
|
||||
private PrivacyConfig _privacyConfigMock;
|
||||
|
||||
@Mock
|
||||
private IDeviceInfoReader _deviceInfoReaderMock;
|
||||
|
||||
@Mock
|
||||
private PrivacyConfigStorage _privacyConfigStorageMock;
|
||||
|
||||
@Mock
|
||||
private PiiDataProvider _piiDataProviderMock;
|
||||
|
||||
@Mock
|
||||
private PiiTrackingStatusReader _piiTrackingStatusReaderMock;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
Mockito.when(_deviceInfoReaderMock.getDeviceInfoData()).thenReturn(new HashMap<>());
|
||||
Mockito.when(_privacyConfigStorageMock.getPrivacyConfig()).thenReturn(_privacyConfigMock);
|
||||
Mockito.when(_piiDataProviderMock.getAdvertisingTrackingId()).thenReturn(FAKE_ADVERTISER_ID);
|
||||
Mockito.when(_piiTrackingStatusReaderMock.getUserNonBehavioralFlag()).thenReturn(FAKE_NONBEHAVIORAL);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithPrivacySnbDisabled() {
|
||||
// given
|
||||
Mockito.when(_privacyConfigMock.shouldSendNonBehavioral()).thenReturn(false);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithPrivacy deviceInfoReaderWithPrivacy = new DeviceInfoReaderWithPrivacy(_deviceInfoReaderMock, _privacyConfigStorageMock, _piiDataProviderMock, _piiTrackingStatusReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithPrivacy.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertNull(deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithPrivacySnbEnabledNbTrue() {
|
||||
// given
|
||||
Mockito.when(_privacyConfigMock.shouldSendNonBehavioral()).thenReturn(true);
|
||||
Mockito.when(_piiTrackingStatusReaderMock.getUserNonBehavioralFlag()).thenReturn(true);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithPrivacy deviceInfoReaderWithPrivacy = new DeviceInfoReaderWithPrivacy(_deviceInfoReaderMock, _privacyConfigStorageMock, _piiDataProviderMock, _piiTrackingStatusReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithPrivacy.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(true, deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithPrivacySnbEnabledNbFalse() {
|
||||
// given
|
||||
Mockito.when(_privacyConfigMock.shouldSendNonBehavioral()).thenReturn(true);
|
||||
Mockito.when(_piiTrackingStatusReaderMock.getUserNonBehavioralFlag()).thenReturn(false);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithPrivacy deviceInfoReaderWithPrivacy = new DeviceInfoReaderWithPrivacy(_deviceInfoReaderMock, _privacyConfigStorageMock, _piiDataProviderMock, _piiTrackingStatusReaderMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithPrivacy.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(false, deviceInfoData.get(USER_NON_BEHAVIORAL_KEY));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package com.unity3d.ads.test.instrumentation.services.core.device;
|
||||
|
||||
import static com.unity3d.services.core.device.reader.JsonStorageKeyNames.SESSION_ID_KEY;
|
||||
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderWithSessionId;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.properties.Session;
|
||||
|
||||
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 java.util.Map;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class DeviceInfoReaderWithSessionIdTest {
|
||||
private static final String FAKE_SESSION_ID = "fakeSessionId";
|
||||
|
||||
@Mock
|
||||
private IDeviceInfoReader _deviceInfoReaderMock;
|
||||
|
||||
@Mock
|
||||
private Session _sessionMock;
|
||||
|
||||
@Test
|
||||
public void testDeviceInfoReaderWithSessionId() {
|
||||
// given
|
||||
Mockito.when(_sessionMock.getId()).thenReturn(FAKE_SESSION_ID);
|
||||
|
||||
// when
|
||||
DeviceInfoReaderWithSessionId deviceInfoReaderWithBehavioralFlag = new DeviceInfoReaderWithSessionId(_deviceInfoReaderMock, _sessionMock);
|
||||
Map<String, Object> deviceInfoData = deviceInfoReaderWithBehavioralFlag.getDeviceInfoData();
|
||||
|
||||
// then
|
||||
Assert.assertEquals(FAKE_SESSION_ID, deviceInfoData.get(SESSION_ID_KEY));
|
||||
}
|
||||
}
|
|
@ -13,16 +13,12 @@ import static org.mockito.Mockito.when;
|
|||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
import com.unity3d.services.ads.gmascar.managers.IBiddingManager;
|
||||
import com.unity3d.services.ads.token.AsyncTokenStorage;
|
||||
import com.unity3d.services.ads.token.INativeTokenGenerator;
|
||||
import com.unity3d.services.ads.token.INativeTokenGeneratorListener;
|
||||
import com.unity3d.services.ads.token.TokenStorage;
|
||||
import com.unity3d.services.ads.token.*;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.request.metrics.TSIMetric;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
|
@ -46,7 +42,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class AsyncTokenStorageTest {
|
||||
public class InMemoryAsyncTokenStorageTest {
|
||||
|
||||
@Mock
|
||||
INativeTokenGenerator _nativeTokenGenerator;
|
||||
|
@ -55,7 +51,7 @@ public class AsyncTokenStorageTest {
|
|||
@Mock
|
||||
IBiddingManager _biddingManager;
|
||||
@Mock
|
||||
ISDKMetrics _sdkMetrics;
|
||||
SDKMetricsSender _sdkMetrics;
|
||||
@Mock
|
||||
TokenStorage _tokenStorage;
|
||||
|
||||
|
@ -72,7 +68,7 @@ public class AsyncTokenStorageTest {
|
|||
WebViewApp.setCurrentApp(webViewApp);
|
||||
SdkProperties.setInitializeState(SdkProperties.InitializationState.INITIALIZING);
|
||||
|
||||
_asyncTokenStorage = new AsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage = new InMemoryAsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage.setConfiguration(new Configuration());
|
||||
|
||||
Mockito.when(_biddingManager.getTokenIdentifier()).thenReturn(SCAR_TOKEN_IDENTIFIER_MOCK);
|
||||
|
@ -436,7 +432,7 @@ public class AsyncTokenStorageTest {
|
|||
Metric _metric = TSIMetric.newAsyncTokenAvailable(new HashMap<String, String>(){{
|
||||
put ("state", "initializing");
|
||||
}});
|
||||
_asyncTokenStorage = new AsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage = new InMemoryAsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage.getToken(_biddingManager);
|
||||
|
||||
Mockito.verify(_biddingManager, Mockito.times(0)).onUnityAdsTokenReady(nullable(String.class));
|
||||
|
@ -462,7 +458,7 @@ public class AsyncTokenStorageTest {
|
|||
Metric _metric = TSIMetric.newAsyncTokenAvailable(new HashMap<String, String>(){{
|
||||
put ("state", "initializing");
|
||||
}});
|
||||
_asyncTokenStorage = new AsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage = new InMemoryAsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
Mockito.when(_biddingManager.getFormattedToken(anyString())).thenReturn(SCAR_TOKEN_IDENTIFIER_MOCK + ":queue_token_1");
|
||||
_asyncTokenStorage.getToken(_biddingManager);
|
||||
|
||||
|
@ -512,7 +508,7 @@ public class AsyncTokenStorageTest {
|
|||
|
||||
@Test
|
||||
public void testNullConfiguration() throws JSONException {
|
||||
_asyncTokenStorage = new AsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage = new InMemoryAsyncTokenStorage(_nativeTokenGenerator, _handler, _sdkMetrics, _tokenStorage);
|
||||
_asyncTokenStorage.getToken(_biddingManager);
|
||||
|
||||
Mockito.verify(_biddingManager, Mockito.times(0)).onUnityAdsTokenReady(nullable(String.class));
|
||||
|
@ -568,4 +564,4 @@ public class AsyncTokenStorageTest {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,9 +9,7 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import com.unity3d.services.ads.token.INativeTokenGeneratorListener;
|
||||
import com.unity3d.services.ads.token.NativeTokenGenerator;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfig;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
|
||||
import org.junit.Before;
|
||||
|
|
|
@ -1,26 +1,27 @@
|
|||
package com.unity3d.ads.test.integration;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.di.IServicesRegistry;
|
||||
import com.unity3d.services.core.di.ServiceProvider;
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers;
|
||||
import com.unity3d.services.core.properties.InitializationStatusReader;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.Metric;
|
||||
import com.unity3d.services.core.request.metrics.MetricSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
|
||||
import kotlinx.coroutines.Dispatchers;
|
||||
import org.json.JSONObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
|
@ -29,15 +30,12 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
|||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SDKMetricsTest {
|
||||
|
||||
@Mock
|
||||
InitializationStatusReader _initStatusReaderMock;
|
||||
|
||||
@Mock
|
||||
Configuration _configurationMock;
|
||||
|
||||
@InjectMocks
|
||||
@Spy
|
||||
public MetricSender _metricSenderMock;
|
||||
|
||||
private final HashMap<String, String> TEST_STATE_TAGS = new HashMap<String, String> (){{
|
||||
|
@ -50,6 +48,20 @@ public class SDKMetricsTest {
|
|||
Field configurationIsSetField = SDKMetrics.class.getDeclaredField("_configurationIsSet");
|
||||
configurationIsSetField.setAccessible(true);
|
||||
configurationIsSetField.set(new Object(), new AtomicBoolean(false));
|
||||
IServicesRegistry registry = Mockito.mock(IServicesRegistry.class);
|
||||
Field serviceRegistry = ServiceProvider.class.getDeclaredField("serviceRegistry");
|
||||
serviceRegistry.setAccessible(true);
|
||||
serviceRegistry.set(ServiceProvider.class, registry);
|
||||
Mockito.doAnswer(invocation -> {
|
||||
Class jObject = kotlin.jvm.JvmClassMappingKt.getJavaClass(invocation.getArgument(1));
|
||||
if (jObject.getName().contains("ISDKDispatchers")) {
|
||||
ISDKDispatchers dispatchers = Mockito.mock(ISDKDispatchers.class);
|
||||
Mockito.when(dispatchers.getIo()).thenReturn(Dispatchers.getIO());
|
||||
return dispatchers;
|
||||
}
|
||||
return Mockito.mock(jObject);
|
||||
}).when(registry).getService(Mockito.any(), Mockito.any());
|
||||
_metricSenderMock = Mockito.spy(new MetricSender(_configurationMock, _initStatusReaderMock));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -58,15 +70,14 @@ public class SDKMetricsTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testUsingNullAndEmptyEvents() {
|
||||
ISDKMetrics metrics = SDKMetrics.getInstance();
|
||||
metrics.sendEvent(null);
|
||||
public void testUsingEmptyEvents() {
|
||||
SDKMetricsSender metrics = SDKMetrics.getInstance();
|
||||
metrics.sendEvent("");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUsingInstanceAfterShutdown() {
|
||||
ISDKMetrics metrics = SDKMetrics.getInstance();
|
||||
SDKMetricsSender metrics = SDKMetrics.getInstance();
|
||||
metrics.sendEvent("test_event");
|
||||
SDKMetrics.setConfiguration(new Configuration());
|
||||
metrics.sendEvent("test_event_2");
|
||||
|
@ -132,7 +143,7 @@ public class SDKMetricsTest {
|
|||
final ArgumentCaptor<Metric> metricCapture = ArgumentCaptor.forClass(Metric.class);
|
||||
Mockito.when(_initStatusReaderMock.getInitializationStateString(Mockito.<SdkProperties.InitializationState>any())).thenReturn("initialized");
|
||||
|
||||
_metricSenderMock.sendMetricWithInitState(new Metric("native_test", 14, null));
|
||||
_metricSenderMock.sendMetricWithInitState(new Metric("native_test", 14));
|
||||
|
||||
Mockito.verify(_metricSenderMock).sendMetric(metricCapture.capture());
|
||||
Assert.assertEquals(TEST_STATE_TAGS, metricCapture.getValue().getTags());
|
||||
|
@ -157,11 +168,11 @@ public class SDKMetricsTest {
|
|||
SDKMetrics.getInstance();
|
||||
Field instanceField = SDKMetrics.class.getDeclaredField("_instance");
|
||||
instanceField.setAccessible(true);
|
||||
Object instanceFieldObj = instanceField.get(ISDKMetrics.class);
|
||||
Object instanceFieldObj = instanceField.get(SDKMetricsSender.class);
|
||||
Assert.assertEquals(expectedMetricsClass, instanceFieldObj.getClass());
|
||||
Mockito.when(mockConfiguration.getMetricSampleRate()).thenReturn(newMsr);
|
||||
SDKMetrics.setConfiguration(mockConfiguration);
|
||||
instanceFieldObj = instanceField.get(ISDKMetrics.class);
|
||||
instanceFieldObj = instanceField.get(SDKMetricsSender.class);
|
||||
Assert.assertEquals(expectedMetricsClass, instanceFieldObj.getClass());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package com.unity3d.ads.test.legacy;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
import com.unity3d.services.ads.gmascar.managers.IBiddingManager;
|
||||
import com.unity3d.services.ads.token.AsyncTokenStorage;
|
||||
import com.unity3d.services.ads.token.TokenEvent;
|
||||
import com.unity3d.services.ads.token.TokenStorage;
|
||||
import com.unity3d.services.ads.token.*;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
|
@ -23,20 +23,32 @@ import org.junit.runner.RunWith;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TokenStorageTest {
|
||||
public class InMemoryTokenStorageTest {
|
||||
private TokenStorage tokenStorage;
|
||||
private AsyncTokenStorage asyncTokenStorage;
|
||||
|
||||
@Before
|
||||
public void reset() {
|
||||
MockWebViewApp webViewApp = new MockWebViewApp();
|
||||
WebViewApp.setCurrentApp(webViewApp);
|
||||
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
TokenStorage.getInstance().setPeekMode(false);
|
||||
TokenStorage.getInstance().setInitToken(null);
|
||||
tokenStorage = new InMemoryTokenStorage();
|
||||
tokenStorage.deleteTokens();
|
||||
tokenStorage.setInitToken(null);
|
||||
|
||||
asyncTokenStorage = new InMemoryAsyncTokenStorage(
|
||||
null,
|
||||
new Handler(Looper.getMainLooper()),
|
||||
SDKMetrics.getInstance(),
|
||||
tokenStorage
|
||||
);
|
||||
}
|
||||
|
||||
@After
|
||||
|
@ -50,30 +62,30 @@ public class TokenStorageTest {
|
|||
public void testCreateGetToken() throws JSONException {
|
||||
MockWebViewApp currentApp = (MockWebViewApp)WebViewApp.getCurrentApp();
|
||||
|
||||
TokenStorage.getInstance().createTokens(getTestArray());
|
||||
tokenStorage.createTokens(getTestArray());
|
||||
|
||||
String firstToken = TokenStorage.getInstance().getToken();
|
||||
String firstToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+get test: first value was not one", firstToken, "one");
|
||||
assertEquals("Token create+get test: event count not one after first event", currentApp.getEventCount(), 1);
|
||||
assertEquals("Token create+get test: event category not TOKEN in first event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+get test: event ID not TOKEN_ACCESS in first event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+get test: access counter is not zero in first event", currentApp.getLastParams()[0], 0);
|
||||
|
||||
String secondToken = TokenStorage.getInstance().getToken();
|
||||
String secondToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+get test: second value was not two", secondToken, "two");
|
||||
assertEquals("Token create+get test: event count not two after second event", currentApp.getEventCount(), 2);
|
||||
assertEquals("Token create+get test: event category not TOKEN in second event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+get test: event ID not TOKEN_ACCESS in second event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+get test: access counter is not one in second event", currentApp.getLastParams()[0], 1);
|
||||
|
||||
String thirdToken = TokenStorage.getInstance().getToken();
|
||||
String thirdToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+get test: third value was not three", thirdToken, "three");
|
||||
assertEquals("Token create+get test: event count not three after third event", currentApp.getEventCount(), 3);
|
||||
assertEquals("Token create+get test: event category not TOKEN in third event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+get test: event ID not TOKEN_ACCESS in third event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+get test: access counter is not two in third event", currentApp.getLastParams()[0], 2);
|
||||
|
||||
String nullToken = TokenStorage.getInstance().getToken();
|
||||
String nullToken = tokenStorage.getToken();
|
||||
assertNull("Token create+get test: value is not null when queue is empty", nullToken);
|
||||
assertEquals("Token create+get test: event count not four after fourth event", currentApp.getEventCount(), 4);
|
||||
assertEquals("Token create+get test: event category not TOKEN in fourth event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
|
@ -84,10 +96,10 @@ public class TokenStorageTest {
|
|||
public void testCreateDeleteToken() throws JSONException {
|
||||
MockWebViewApp currentApp = (MockWebViewApp)WebViewApp.getCurrentApp();
|
||||
|
||||
TokenStorage.getInstance().createTokens(getTestArray());
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
tokenStorage.createTokens(getTestArray());
|
||||
tokenStorage.deleteTokens();
|
||||
|
||||
String nullToken = TokenStorage.getInstance().getToken();
|
||||
String nullToken = tokenStorage.getToken();
|
||||
assertNull("Token create+delete test: value is not null when queue was deleted", nullToken);
|
||||
assertEquals("Token create+delete test: webview event was triggered when queue was deleted", currentApp.getEventCount(), 0);
|
||||
}
|
||||
|
@ -96,96 +108,66 @@ public class TokenStorageTest {
|
|||
public void testCreateAppendGetToken() throws JSONException {
|
||||
MockWebViewApp currentApp = (MockWebViewApp)WebViewApp.getCurrentApp();
|
||||
|
||||
TokenStorage.getInstance().createTokens(getTestArray());
|
||||
tokenStorage.createTokens(getTestArray());
|
||||
|
||||
String firstToken = TokenStorage.getInstance().getToken();
|
||||
String firstToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: first value was not one", firstToken, "one");
|
||||
assertEquals("Token create+append+get test: event count not one after first event", currentApp.getEventCount(), 1);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in first event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in first event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not zero in first event", currentApp.getLastParams()[0], 0);
|
||||
|
||||
TokenStorage.getInstance().appendTokens(getTestArray());
|
||||
tokenStorage.appendTokens(getTestArray());
|
||||
|
||||
String secondToken = TokenStorage.getInstance().getToken();
|
||||
String secondToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: second value was not two", secondToken, "two");
|
||||
assertEquals("Token create+append+get test: event count not two after second event", currentApp.getEventCount(), 2);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in second event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in second event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not one in second event", currentApp.getLastParams()[0], 1);
|
||||
|
||||
String thirdToken = TokenStorage.getInstance().getToken();
|
||||
String thirdToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: third value was not three", thirdToken, "three");
|
||||
assertEquals("Token create+append+get test: event count not three after third event", currentApp.getEventCount(), 3);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in third event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in third event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not two in third event", currentApp.getLastParams()[0], 2);
|
||||
|
||||
String fourthToken = TokenStorage.getInstance().getToken();
|
||||
String fourthToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: fourth value was not one", fourthToken, "one");
|
||||
assertEquals("Token create+append+get test: event count not four after fourth event", currentApp.getEventCount(), 4);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in fourth event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in fourth event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not three in fourth event", currentApp.getLastParams()[0], 3);
|
||||
|
||||
String fifthToken = TokenStorage.getInstance().getToken();
|
||||
String fifthToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: fifth value was not two", fifthToken, "two");
|
||||
assertEquals("Token create+append+get test: event count not five after fifth event", currentApp.getEventCount(), 5);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in fifth event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in fifth event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not four in fifth event", currentApp.getLastParams()[0], 4);
|
||||
|
||||
String sixthToken = TokenStorage.getInstance().getToken();
|
||||
String sixthToken = tokenStorage.getToken();
|
||||
assertEquals("Token create+append+get test: sixth value was not three", sixthToken, "three");
|
||||
assertEquals("Token create+append+get test: event count not six after sixth event", currentApp.getEventCount(), 6);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in sixth event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not TOKEN_ACCESS in sixth event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token create+append+get test: access counter is not five in sixth event", currentApp.getLastParams()[0], 5);
|
||||
|
||||
String nullToken = TokenStorage.getInstance().getToken();
|
||||
String nullToken = tokenStorage.getToken();
|
||||
assertNull("Token create+append+get test: value is not null when queue is empty", nullToken);
|
||||
assertEquals("Token create+append+get test: event count not seven after seventh event", currentApp.getEventCount(), 7);
|
||||
assertEquals("Token create+append+get test: event category not TOKEN in seventh event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token create+append+get test: event ID not QUEUE_EMPTY in seventh event", currentApp.getLastEventId(), TokenEvent.QUEUE_EMPTY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPeekMode() throws JSONException {
|
||||
String staticToken = "static_token";
|
||||
|
||||
MockWebViewApp currentApp = (MockWebViewApp)WebViewApp.getCurrentApp();
|
||||
|
||||
JSONArray array = new JSONArray();
|
||||
array.put(staticToken);
|
||||
|
||||
TokenStorage.getInstance().setPeekMode(true);
|
||||
TokenStorage.getInstance().createTokens(array);
|
||||
|
||||
String firstToken = TokenStorage.getInstance().getToken();
|
||||
assertEquals("Token peekmode test: first value was not correct", firstToken, staticToken);
|
||||
assertEquals("Token peekmode test: event count not one after first event", currentApp.getEventCount(), 1);
|
||||
assertEquals("Token peekmode test: event category not TOKEN in first event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token peekmode test: event ID not TOKEN_ACCESS in first event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token peekmode test: access counter is not zero in first event", currentApp.getLastParams()[0], 0);
|
||||
|
||||
String secondToken = TokenStorage.getInstance().getToken();
|
||||
assertEquals("Token peekmode test: second value was not correct", secondToken, staticToken);
|
||||
assertEquals("Token peekmode test: event count not two after second event", currentApp.getEventCount(), 2);
|
||||
assertEquals("Token peekmode test: event category not TOKEN in second event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token peekmode test: event ID not TOKEN_ACCESS in second event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token peekmode test: access counter is not one in second event", currentApp.getLastParams()[0], 1);
|
||||
|
||||
String thirdToken = TokenStorage.getInstance().getToken();
|
||||
assertEquals("Token peekmode test: third value was not correct", thirdToken, staticToken);
|
||||
assertEquals("Token peekmode test: event count not one after third event", currentApp.getEventCount(), 3);
|
||||
assertEquals("Token peekmode test: event category not TOKEN in third event", currentApp.getLastEventCategory(), WebViewEventCategory.TOKEN);
|
||||
assertEquals("Token peekmode test: event ID not TOKEN_ACCESS in third event", currentApp.getLastEventId(), TokenEvent.TOKEN_ACCESS);
|
||||
assertEquals("Token peekmode test: access counter is not two in third event", currentApp.getLastParams()[0], 2);
|
||||
}
|
||||
|
||||
@Test(timeout = 2000)
|
||||
public void testDeadlockRegression() throws InterruptedException {
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
public void testDeadlockRegression() throws InterruptedException, IllegalAccessException {
|
||||
tokenStorage.deleteTokens();
|
||||
|
||||
Field field = Arrays.stream(InMemoryTokenStorage.class.getDeclaredFields()).filter(f -> f.getName().contains("asyncTokenStorage")).findFirst().get();
|
||||
field.setAccessible(true);
|
||||
field.set(tokenStorage, kotlin.LazyKt.lazyOf(asyncTokenStorage));
|
||||
|
||||
ClientProperties.setApplicationContext(androidx.test.core.app.ApplicationProvider.getApplicationContext());
|
||||
SdkProperties.setInitializeState(SdkProperties.InitializationState.INITIALIZING);
|
||||
|
@ -195,7 +177,7 @@ public class TokenStorageTest {
|
|||
final CountDownLatch tokensReady = new CountDownLatch(tokenRequestCount);
|
||||
final String[] actualToken = {"", ""};
|
||||
|
||||
AsyncTokenStorage.getInstance().setConfiguration(new Configuration());
|
||||
asyncTokenStorage.setConfiguration(new Configuration());
|
||||
|
||||
Thread appendTokens = new Thread(new Runnable() {
|
||||
@Override
|
||||
|
@ -206,7 +188,7 @@ public class TokenStorageTest {
|
|||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
TokenStorage.getInstance().appendTokens(getTestArray());
|
||||
tokenStorage.appendTokens(getTestArray());
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -220,7 +202,7 @@ public class TokenStorageTest {
|
|||
|
||||
for (int i = 0; i < tokenRequestCount; i++) {
|
||||
final int finalI = i;
|
||||
AsyncTokenStorage.getInstance().getToken(new IBiddingManager() {
|
||||
asyncTokenStorage.getToken(new IBiddingManager() {
|
||||
@Override
|
||||
public String getTokenIdentifier() {
|
||||
return "";
|
|
@ -178,21 +178,6 @@ public class InitializeThreadTest {
|
|||
assertEquals("Init state reset test: next state config url is not set", config.getConfigUrl(), null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeStateAdBlockerCheck() {
|
||||
Configuration goodConfig = new Configuration("http://www.unity3d.com/test");
|
||||
InitializeThread.InitializeStateInitModules state = new InitializeThread.InitializeStateInitModules(goodConfig);
|
||||
Object nextState = state.execute();
|
||||
|
||||
assertTrue("Init state ad blocker check test: next state is not load config", nextState instanceof InitializeThread.InitializeStateConfig);
|
||||
|
||||
Configuration badConfig = new Configuration("http://localhost/test");
|
||||
InitializeThread.InitializeStateInitModules state2 = new InitializeThread.InitializeStateInitModules(badConfig);
|
||||
Object nextState2 = state2.execute();
|
||||
|
||||
assertTrue("Init state ad blocker check test: next state is not error state", nextState2 instanceof InitializeThread.InitializeStateError);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitializeStateConfig() {
|
||||
Configuration initConfig = new Configuration(SdkProperties.getConfigUrl());
|
||||
|
|
|
@ -4,6 +4,7 @@ import android.os.ConditionVariable;
|
|||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Parcel;
|
||||
import android.webkit.ValueCallback;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
|
@ -104,7 +105,7 @@ public class InvocationTest {
|
|||
public void run() {
|
||||
WebViewApp.getCurrentApp().setWebView(new WebView(ClientProperties.getApplicationContext(), false) {
|
||||
@Override
|
||||
public void invokeJavascript(String data) {
|
||||
public void evaluateJavascript(String data, ValueCallback<String> callback) {
|
||||
BatchInvocationTestApi.JAVASCRIPT_INVOKED = true;
|
||||
}
|
||||
});
|
||||
|
@ -142,7 +143,7 @@ public class InvocationTest {
|
|||
public void run() {
|
||||
WebViewApp.getCurrentApp().setWebView(new WebView(ClientProperties.getApplicationContext(), false) {
|
||||
@Override
|
||||
public void invokeJavascript(String data) {
|
||||
public void evaluateJavascript(String data, ValueCallback<String> callback) {
|
||||
BatchInvocationTestApi.JAVASCRIPT_INVOKED = true;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,36 +1,40 @@
|
|||
package com.unity3d.ads.test.legacy;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.media.AudioManager;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.test.filters.RequiresDevice;
|
||||
import androidx.test.filters.SdkSuppress;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.unity3d.services.core.api.DeviceInfo;
|
||||
import com.unity3d.services.core.device.IVolumeChangeListener;
|
||||
import com.unity3d.services.core.device.VolumeChange;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.ads.test.TestUtilities;
|
||||
import com.unity3d.services.ads.video.VideoPlayerEvent;
|
||||
import com.unity3d.services.ads.video.VideoPlayerView;
|
||||
import com.unity3d.services.core.device.DeviceInfoEvent;
|
||||
import com.unity3d.services.core.device.VolumeChange;
|
||||
import com.unity3d.services.core.device.VolumeChangeContentObserver;
|
||||
import com.unity3d.services.core.device.VolumeChangeListener;
|
||||
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 org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
||||
public class VolumeChangeContentObserverTest extends AdUnitActivityTestBaseClass {
|
||||
@Before
|
||||
public void setup() {
|
||||
WebViewApp.setCurrentApp(null);
|
||||
|
@ -41,6 +45,7 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
@SdkSuppress(minSdkVersion = 21)
|
||||
public void testVolumeChange() throws Exception {
|
||||
final Activity activity = waitForActivityStart(null);
|
||||
final VolumeChange volumeChange = new VolumeChangeContentObserver();
|
||||
|
||||
ClientProperties.setApplicationContext(InstrumentationRegistry.getInstrumentation().getTargetContext());
|
||||
|
||||
|
@ -69,7 +74,7 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
CONDITION_VARIABLE.open();
|
||||
}
|
||||
}
|
||||
if (eventCategory.equals(WebViewEventCategory.DEVICEINFO) && eventId.equals(DeviceInfo.DeviceInfoEvent.VOLUME_CHANGED)) {
|
||||
if (eventCategory.equals(WebViewEventCategory.DEVICEINFO) && eventId.equals(DeviceInfoEvent.VOLUME_CHANGED)) {
|
||||
EVENT_PARAMS = params;
|
||||
CONDITION_VARIABLE.open();
|
||||
}
|
||||
|
@ -108,11 +113,11 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
mockWebViewApp.CONDITION_VARIABLE = cv;
|
||||
success = cv.block(3000);
|
||||
|
||||
IVolumeChangeListener vcl = new IVolumeChangeListener() {
|
||||
VolumeChangeListener vcl = new VolumeChangeListener() {
|
||||
@Override
|
||||
public void onVolumeChanged(int volume) {
|
||||
DeviceLog.debug("VOLUME_CHANGED: " + volume);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.DEVICEINFO, DeviceInfo.DeviceInfoEvent.VOLUME_CHANGED, volume);
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.DEVICEINFO, DeviceInfoEvent.VOLUME_CHANGED, volume);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,7 +126,7 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
}
|
||||
};
|
||||
|
||||
VolumeChange.registerListener(vcl);
|
||||
volumeChange.registerListener(vcl);
|
||||
|
||||
am.setStreamVolume(AudioManager.STREAM_MUSIC, 1, 0);
|
||||
|
||||
|
@ -134,10 +139,10 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
assertNotNull("First EVENT_PARAMS NULL", mockWebViewApp.EVENT_PARAMS[0]);
|
||||
assertEquals("Volume not what was expected", 1, (int)mockWebViewApp.EVENT_PARAMS[0]);
|
||||
|
||||
VolumeChange.unregisterListener(vcl);
|
||||
volumeChange.unregisterListener(vcl);
|
||||
am.setStreamVolume(AudioManager.STREAM_MUSIC, 3, 0);
|
||||
|
||||
VolumeChange.registerListener(vcl);
|
||||
volumeChange.registerListener(vcl);
|
||||
am.setStreamVolume(AudioManager.STREAM_MUSIC, 2, 0);
|
||||
|
||||
cv = new ConditionVariable();
|
||||
|
@ -152,4 +157,32 @@ public class VolumeChangeTest extends AdUnitActivityTestBaseClass {
|
|||
|
||||
assertTrue("Didn't get activity finish", waitForActivityFinish(activity));
|
||||
}
|
||||
|
||||
@Test(timeout = 10000)
|
||||
public void testVolumeChangeThreadConcurrency() throws InterruptedException {
|
||||
|
||||
final VolumeChangeListener vcl = Mockito.mock(VolumeChangeListener.class);
|
||||
final int clearListenerThreadCount = 10;
|
||||
final CountDownLatch registerListenerLatch = new CountDownLatch(1);
|
||||
final VolumeChange volumeChange = new VolumeChangeContentObserver();
|
||||
|
||||
final CountDownLatch clearListenerLatch = new CountDownLatch(clearListenerThreadCount);
|
||||
|
||||
for (int threadCount = 0; threadCount < clearListenerThreadCount; threadCount++) {
|
||||
Thread clearListenerThread = new Thread(() -> {
|
||||
try {
|
||||
registerListenerLatch.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
volumeChange.clearAllListeners();
|
||||
clearListenerLatch.countDown();
|
||||
});
|
||||
clearListenerThread.start();
|
||||
}
|
||||
registerListenerLatch.countDown();
|
||||
volumeChange.registerListener(vcl);
|
||||
clearListenerLatch.await();
|
||||
|
||||
}
|
||||
}
|
|
@ -4,6 +4,7 @@ import android.content.Context;
|
|||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.webkit.ValueCallback;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
|
@ -64,6 +65,7 @@ public class WebViewAppTest {
|
|||
public void run() {
|
||||
WebViewApp.getCurrentApp().setWebAppLoaded(true);
|
||||
WebViewApp.getCurrentApp().setWebAppInitialized(false);
|
||||
WebViewApp.getCurrentApp().setWebAppFailureCode(1);
|
||||
}
|
||||
}, 100);
|
||||
ErrorState webViewErrorState = WebViewApp.create(conf);
|
||||
|
@ -542,7 +544,7 @@ public class WebViewAppTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void invokeJavascript(String data) {
|
||||
public void evaluateJavascript(String data, ValueCallback<String> callback) {
|
||||
JS_INVOKED = true;
|
||||
JS_CALL = data;
|
||||
}
|
||||
|
|
|
@ -1,12 +1,18 @@
|
|||
package com.unity3d.ads.test.legacy;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.os.ConditionVariable;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.webkit.ValueCallback;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import androidx.webkit.JavaScriptReplyProxy;
|
||||
import androidx.webkit.WebMessageCompat;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.IExperiments;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.ads.test.TestUtilities;
|
||||
import com.unity3d.services.core.webview.WebView;
|
||||
|
@ -17,21 +23,29 @@ import com.unity3d.services.core.webview.bridge.WebViewBridgeInterface;
|
|||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
import kotlinx.coroutines.Dispatchers;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.json.JSONException;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class WebViewBridgeInterfaceTest {
|
||||
|
||||
@Mock
|
||||
private JavaScriptReplyProxy javaScriptProxy;
|
||||
|
||||
private static boolean nativeCallbackInvoked = false;
|
||||
private static CallbackStatus nativeCallbackStatus = null;
|
||||
private static String nativeCallbackValue = null;
|
||||
|
@ -98,7 +112,7 @@ public class WebViewBridgeInterfaceTest {
|
|||
WebViewApp.getCurrentApp().setWebAppInitialized(true);
|
||||
WebViewApp.getCurrentApp().setWebView(new WebView(ClientProperties.getApplicationContext(), false) {
|
||||
@Override
|
||||
public void invokeJavascript(String data) {
|
||||
public void evaluateJavascript(String data, ValueCallback<String> callback) {
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -129,24 +143,72 @@ public class WebViewBridgeInterfaceTest {
|
|||
webInterface.handleInvocation("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethodNoParams\", null, \"CALLBACK_01\"]]");
|
||||
}
|
||||
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void testOnHandleInvocationShouldFailParametersNull() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleInvocation(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethodNoParams\", null, \"CALLBACK_01\"]]"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testHandleCallbackShouldFailParametersNull () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.handleCallback("CALLBACK_01", "OK", null);
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testOnHandleCallbackShouldFailParametersNull() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"CALLBACK_01\",\"status\":\"OK\"}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test (expected = ClassCastException.class)
|
||||
public void testHandleInvocationShouldFailParametersEmpty () throws JSONException {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.handleInvocation("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethodNoParams\", \"\", \"CALLBACK_01\"]]");
|
||||
}
|
||||
|
||||
@Test(expected = ClassCastException.class)
|
||||
public void testOnHandleInvocationShouldFailParametersEmpty() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleInvocation(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethodNoParams\", \"\", \"CALLBACK_01\"]]"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test (expected = JSONException.class)
|
||||
public void testHandleCallbackShouldFailParametersEmpty () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.handleCallback("CALLBACK_01", "OK", "");
|
||||
}
|
||||
|
||||
@Test(expected = JSONException.class)
|
||||
public void testOnHandleCallbackShouldFailParametersEmpty() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"CALLBACK_01\",\"status\":\"OK\",\"parameters\":\"\"}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleInvocationShouldSucceed () throws JSONException {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -155,6 +217,20 @@ public class WebViewBridgeInterfaceTest {
|
|||
assertEquals("CallbackID's didn't match", "CALLBACK_01", WebViewBridgeTestApi.callback.getCallbackId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnHandleInvocationShouldSucceed() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleInvocation(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethodNoParams\", [], \"CALLBACK_01\"]]"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
assertTrue("ApiMethod should have been invoked but wasn't", WebViewBridgeTestApi.invoked);
|
||||
assertEquals("CallbackID's didn't match", "CALLBACK_01", WebViewBridgeTestApi.callback.getCallbackId());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleInvocationWithParamsShouldSucceed () throws JSONException {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -164,6 +240,21 @@ public class WebViewBridgeInterfaceTest {
|
|||
assertEquals("Callback value wasn't same as was originally given", "test", WebViewBridgeTestApi.value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnHandleInvocationWithParamsShouldSucceed() {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
webInterface.onHandleInvocation(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("[[\"com.unity3d.ads.test.legacy.WebViewBridgeInterfaceTest$WebViewBridgeTestApi\", \"apiTestMethod\", [\"test\"], \"CALLBACK_01\"]]"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
assertTrue("ApiMethod should have been invoked but wasn't", WebViewBridgeTestApi.invoked);
|
||||
assertEquals("CallbackID's didn't match", "CALLBACK_01", WebViewBridgeTestApi.callback.getCallbackId());
|
||||
assertEquals("Callback value wasn't same as was originally given", "test", WebViewBridgeTestApi.value);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testHandleCallbackShouldFailCallbackNotAdded () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -172,6 +263,20 @@ public class WebViewBridgeInterfaceTest {
|
|||
webInterface.handleCallback(callback.getId(), "OK", "[]");
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testOnHandleCallbackShouldFailCallbackNotAdded() throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
Method m = getClass().getMethod("staticTestHandleCallback", CallbackStatus.class);
|
||||
NativeCallback callback = new NativeCallback(m);
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"" + callback.getId() + "\",\"status\":\"OK\",\"parameters\":\"[]\"}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testHandleCallbackShouldFailMethodNotStatic () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -181,6 +286,21 @@ public class WebViewBridgeInterfaceTest {
|
|||
webInterface.handleCallback(callback.getId(), "OK", "[]");
|
||||
}
|
||||
|
||||
@Test(expected = NullPointerException.class)
|
||||
public void testOnHandleCallbackShouldFailMethodNotStatic() throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
Method m = getClass().getMethod("instanceTestHandleCallback", CallbackStatus.class);
|
||||
NativeCallback callback = new NativeCallback(m);
|
||||
WebViewApp.getCurrentApp().addCallback(callback);
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"" + callback.getId() + "\",\"status\":\"OK\",\"parameters\":\"[]\"}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCallbackShouldSucceed () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -192,6 +312,23 @@ public class WebViewBridgeInterfaceTest {
|
|||
assertEquals("NativeCallback status wasn't OK", CallbackStatus.OK, nativeCallbackStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnHandleCallbackShouldSucceed() throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
Method m = getClass().getMethod("staticTestHandleCallback", CallbackStatus.class);
|
||||
NativeCallback callback = new NativeCallback(m);
|
||||
WebViewApp.getCurrentApp().addCallback(callback);
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"" + callback.getId() + "\",\"status\":\"OK\",\"parameters\":\"[]\"}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
assertTrue("NativeCallback -method should have been invoked but wasn't", nativeCallbackInvoked);
|
||||
assertEquals("NativeCallback status wasn't OK", CallbackStatus.OK, nativeCallbackStatus);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleCallbackWithParamsShouldSucceed () throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
|
@ -206,6 +343,26 @@ public class WebViewBridgeInterfaceTest {
|
|||
assertEquals("The value received wasn't the same than was originally given", "test", nativeCallbackValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnHandleCallbackWithParamsShouldSucceed() throws Exception {
|
||||
WebViewBridgeInterface webInterface = new WebViewBridgeInterface();
|
||||
Method m = getClass().getMethod("staticTestHandleCallbackStringParam", CallbackStatus.class, String.class);
|
||||
NativeCallback callback = new NativeCallback(m);
|
||||
WebViewApp.getCurrentApp().addCallback(callback);
|
||||
webInterface.onHandleCallback(
|
||||
WebViewApp.getCurrentApp().getWebView(),
|
||||
new WebMessageCompat("{\"id\":\"" + callback.getId() + "\",\"status\":\"OK\",\"parameters\":[\"test\"]}"),
|
||||
Uri.EMPTY,
|
||||
true,
|
||||
javaScriptProxy
|
||||
);
|
||||
|
||||
assertTrue("NativeCallback -method should have been invoked but wasn't", nativeCallbackInvoked);
|
||||
assertEquals("NativeCallback status wasn't OK", CallbackStatus.OK, nativeCallbackStatus);
|
||||
assertNotNull("Received value should not be null", nativeCallbackValue);
|
||||
assertEquals("The value received wasn't the same than was originally given", "test", nativeCallbackValue);
|
||||
}
|
||||
|
||||
public static void staticTestHandleCallback (CallbackStatus status) {
|
||||
nativeCallbackInvoked = true;
|
||||
nativeCallbackStatus = status;
|
||||
|
|
|
@ -11,9 +11,11 @@ import android.os.Parcel;
|
|||
import android.os.Parcelable;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.platform.app.InstrumentationRegistry;
|
||||
|
||||
import com.unity3d.ads.test.TestUtilities;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
import com.unity3d.services.core.webview.bridge.NativeCallback;
|
||||
|
@ -121,22 +123,23 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testAllNull () throws Exception {
|
||||
WebViewBridge.handleInvocation(null, null, null, null);
|
||||
WebViewBridge.getInstance().handleInvocation(null, null, null, null);
|
||||
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testClassNameSetOthersNull () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", null, null, null);
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", null, null, null);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testClassNameMethodSetOthersNull () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", null, null);
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", null, null);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testOthersSetParametersNull () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", null, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", null, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -144,7 +147,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", null, new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", null, new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -162,7 +165,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation(null, "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation(null, "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -180,7 +183,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApina", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApina", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -198,7 +201,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apinaTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apinaTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -213,7 +216,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test (expected = NullPointerException.class)
|
||||
public void testAllSetParametersWrong () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{1, "test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{1, "test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -221,7 +224,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -239,7 +242,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -254,7 +257,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test (expected = IllegalArgumentException.class)
|
||||
public void testOthersSetCallbackNull () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, null);
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, null);
|
||||
}
|
||||
|
||||
public class MockWebViewCallback extends WebViewCallback {
|
||||
|
@ -296,7 +299,7 @@ public class WebViewBridgeTest {
|
|||
boolean gotException = false;
|
||||
|
||||
try {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "wrongMethodName", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "wrongMethodName", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
}
|
||||
catch (Exception e) {
|
||||
assertEquals("Should have received exception of type NoSuchMethodException", NoSuchMethodException.class, e.getClass());
|
||||
|
@ -314,7 +317,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test
|
||||
public void testAllSetMethodNoParams () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethodNoParams", new Object[]{}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethodNoParams", new Object[]{}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
assertEquals(true, WebViewBridgeTestApi.invoked);
|
||||
assertNull(WebViewBridgeTestApi.value);
|
||||
assertNotNull(WebViewBridgeTestApi.callback);
|
||||
|
@ -323,7 +326,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test
|
||||
public void testOthersSetParametersNullMethodNoParams () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethodNoParams", null, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethodNoParams", null, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
assertEquals(true, WebViewBridgeTestApi.invoked);
|
||||
assertNull(WebViewBridgeTestApi.value);
|
||||
assertNotNull(WebViewBridgeTestApi.callback);
|
||||
|
@ -332,7 +335,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test
|
||||
public void testAllSetCorrectly () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("APICALLBACK_01", 1));
|
||||
assertEquals(true, WebViewBridgeTestApi.invoked);
|
||||
assertEquals("test", WebViewBridgeTestApi.value);
|
||||
assertNotNull(WebViewBridgeTestApi.callback);
|
||||
|
@ -341,7 +344,7 @@ public class WebViewBridgeTest {
|
|||
|
||||
@Test
|
||||
public void testAllSetCallbackEmpty () throws Exception {
|
||||
WebViewBridge.handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("", 1));
|
||||
WebViewBridge.getInstance().handleInvocation("com.unity3d.ads.test.legacy.WebViewBridgeTest$WebViewBridgeTestApi", "apiTestMethod", new Object[]{"test"}, new MockWebViewCallback("", 1));
|
||||
assertEquals(true, WebViewBridgeTestApi.invoked);
|
||||
assertEquals("test", WebViewBridgeTestApi.value);
|
||||
assertNotNull(WebViewBridgeTestApi.callback);
|
||||
|
@ -365,7 +368,7 @@ public class WebViewBridgeTest {
|
|||
NativeCallback ncb = new NativeCallback(ncbm);
|
||||
WebViewApp.getCurrentApp().addCallback(ncb);
|
||||
Object[] params = new Object[]{"Test"};
|
||||
WebViewBridge.handleCallback(ncb.getId(), CallbackStatus.OK.toString(), params);
|
||||
WebViewBridge.getInstance().handleCallback(ncb.getId(), CallbackStatus.OK.toString(), params);
|
||||
assertEquals("Native Callback status was expected to be OK", CallbackStatus.OK, nativeCallbackStatus);
|
||||
assertTrue("Native Callback should have finished", nativeCallbackFinished);
|
||||
assertEquals("Native callback should have received a string as a parameter with value \"Test\"", "Test", nativeCallbackValue);
|
||||
|
@ -377,7 +380,7 @@ public class WebViewBridgeTest {
|
|||
NativeCallback ncb = new NativeCallback(ncbm);
|
||||
WebViewApp.getCurrentApp().addCallback(ncb);
|
||||
Object[] params = null;
|
||||
WebViewBridge.handleCallback(ncb.getId(), CallbackStatus.OK.toString(), params);
|
||||
WebViewBridge.getInstance().handleCallback(ncb.getId(), CallbackStatus.OK.toString(), params);
|
||||
assertEquals("Native Callback status was expected to be OK", CallbackStatus.OK, nativeCallbackStatus);
|
||||
assertTrue("Native Callback should have finished", nativeCallbackFinished);
|
||||
assertNull("Native callback should have not received a value \"Test\"", nativeCallbackValue);
|
||||
|
@ -389,7 +392,7 @@ public class WebViewBridgeTest {
|
|||
NativeCallback ncb = new NativeCallback(ncbm);
|
||||
WebViewApp.getCurrentApp().addCallback(ncb);
|
||||
Object[] params = new Object[]{"Test"};
|
||||
WebViewBridge.handleCallback(ncb.getId(), "INVALID_STATUS", params);
|
||||
WebViewBridge.getInstance().handleCallback(ncb.getId(), "INVALID_STATUS", params);
|
||||
}
|
||||
|
||||
@Test (expected = NullPointerException.class)
|
||||
|
|
|
@ -62,7 +62,7 @@ public class MetricCommonTagsTest {
|
|||
mediationMetaData.set("adapter_version", "456");
|
||||
mediationMetaData.commit();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect metricSampleRate value", currentTags.get("msr"));
|
||||
assertEquals("Incorrect mediation name value", "MediationNetwork", currentTags.get("m_name"));
|
||||
|
@ -78,7 +78,7 @@ public class MetricCommonTagsTest {
|
|||
|
||||
MetricCommonTags commonTags = new MetricCommonTags();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect mediation name value", currentTags.get("m_name"));
|
||||
assertNull("Incorrect mediation version value", currentTags.get("m_ver"));
|
||||
|
@ -90,7 +90,7 @@ public class MetricCommonTagsTest {
|
|||
mediationMetaData.set("adapter_version", "456");
|
||||
mediationMetaData.commit();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertEquals("Incorrect mediation name value", "MediationNetwork", currentTags.get("m_name"));
|
||||
assertEquals("Incorrect mediation version value", "123", currentTags.get("m_ver"));
|
||||
|
@ -104,7 +104,7 @@ public class MetricCommonTagsTest {
|
|||
|
||||
MetricCommonTags commonTags = new MetricCommonTags();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect mediation name value", currentTags.get("m_name"));
|
||||
assertNull("Incorrect mediation version value", currentTags.get("m_ver"));
|
||||
|
@ -116,7 +116,7 @@ public class MetricCommonTagsTest {
|
|||
mediationMetaData.set("adapter_version", "456");
|
||||
mediationMetaData.commit();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect mediation name value", currentTags.get("m_name"));
|
||||
assertEquals("Incorrect mediation version value", "123", currentTags.get("m_ver"));
|
||||
|
@ -130,7 +130,7 @@ public class MetricCommonTagsTest {
|
|||
|
||||
MetricCommonTags commonTags = new MetricCommonTags();
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect experiment tag tsi_prw value", currentTags.get("tsi_prw"));
|
||||
assertNull("Incorrect experiment tag wac value", currentTags.get("wac"));
|
||||
|
@ -148,7 +148,7 @@ public class MetricCommonTagsTest {
|
|||
MetricCommonTags commonTags = new MetricCommonTags();
|
||||
commonTags.updateWithConfig(configMock);
|
||||
|
||||
currentTags = commonTags.asMap();
|
||||
currentTags = commonTags.toMap();
|
||||
|
||||
assertNull("Incorrect experiment tag tsi_prw value", currentTags.get("tsi_prw"));
|
||||
assertEquals("Incorrect experiment tag wac value","true", currentTags.get("wac"));
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="com.google.android.gms.permission.AD_ID"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_TOPICS" />
|
||||
<uses-permission android:name="android.permission.ACCESS_ADSERVICES_ATTRIBUTION" />
|
||||
|
||||
<application>
|
||||
<activity
|
||||
|
@ -48,6 +50,10 @@
|
|||
android:name="com.unity3d.services.core.configuration.AdsSdkInitializer"
|
||||
android:value="androidx.startup" />
|
||||
</provider>
|
||||
|
||||
<property android:name="android.adservices.AD_SERVICES_CONFIG"
|
||||
android:resource="@xml/ad_services_config" />
|
||||
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
|
|
|
@ -3,12 +3,13 @@ package com.unity3d.services
|
|||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.request.metrics.Metric
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import java.lang.IllegalStateException
|
||||
import java.lang.RuntimeException
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
class SDKErrorHandler(private val dispatchers: ISDKDispatchers) : CoroutineExceptionHandler {
|
||||
class SDKErrorHandler(private val dispatchers: ISDKDispatchers, private val sdkMetricsSender: SDKMetricsSender) : CoroutineExceptionHandler {
|
||||
|
||||
override val key = CoroutineExceptionHandler.Key
|
||||
|
||||
|
@ -25,9 +26,9 @@ class SDKErrorHandler(private val dispatchers: ISDKDispatchers) : CoroutineExcep
|
|||
else -> "native_exception"
|
||||
}
|
||||
|
||||
sendMetric(Metric(name, "{$className}_$line", null))
|
||||
sendMetric(Metric(name, "{$className}_$line"))
|
||||
}
|
||||
|
||||
|
||||
private fun sendMetric(metric: Metric) = SDKMetrics.getInstance().sendMetric(metric);
|
||||
private fun sendMetric(metric: Metric) = sdkMetricsSender.sendMetric(metric);
|
||||
}
|
|
@ -1,187 +0,0 @@
|
|||
package com.unity3d.services;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsInitializationListener;
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.EnvironmentCheck;
|
||||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender;
|
||||
import com.unity3d.services.core.configuration.InitializeThread;
|
||||
import com.unity3d.services.core.device.Device;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.properties.Session;
|
||||
|
||||
public class UnityServices {
|
||||
|
||||
public enum UnityServicesError {
|
||||
INVALID_ARGUMENT,
|
||||
INIT_SANITY_CHECK_FAIL
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes Unity Ads. Unity Ads should be initialized when app starts.
|
||||
* @param context Current Android application context of calling app
|
||||
* @param gameId Unique identifier for a game, given by Unity Ads admin tools or Unity editor
|
||||
* @param testMode If true, only test ads are shown
|
||||
* @param initializationListener Listener for IUnityAdsInitializationListener callbacks
|
||||
*/
|
||||
public static void initialize(final Context context, final String gameId, final boolean testMode, final IUnityAdsInitializationListener initializationListener) {
|
||||
DeviceLog.entered();
|
||||
|
||||
if (SdkProperties.getCurrentInitializationState() != SdkProperties.InitializationState.NOT_INITIALIZED) {
|
||||
String differingParameters = "";
|
||||
|
||||
String previousGameId = ClientProperties.getGameId();
|
||||
if (previousGameId != null && !previousGameId.equals(gameId)) {
|
||||
differingParameters += createExpectedParametersString("Game ID", ClientProperties.getGameId(), gameId);
|
||||
}
|
||||
|
||||
boolean previousTestMode = SdkProperties.isTestMode();
|
||||
if (previousTestMode != testMode) {
|
||||
differingParameters += createExpectedParametersString("Test Mode", previousTestMode, testMode);
|
||||
}
|
||||
|
||||
if (!TextUtils.isEmpty(differingParameters)) {
|
||||
String message = "Unity Ads SDK failed to initialize due to already being initialized with different parameters" + differingParameters;
|
||||
DeviceLog.warning(message);
|
||||
if (initializationListener != null) {
|
||||
initializationListener.onInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SdkProperties.addInitializationListener(initializationListener);
|
||||
|
||||
if(SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.INITIALIZED_SUCCESSFULLY) {
|
||||
SdkProperties.notifyInitializationComplete();
|
||||
return;
|
||||
}
|
||||
|
||||
if(SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.INITIALIZED_FAILED) {
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INTERNAL_ERROR, "Unity Ads SDK failed to initialize due to previous failed reason");
|
||||
return;
|
||||
}
|
||||
|
||||
if(SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.INITIALIZING) {
|
||||
return;
|
||||
}
|
||||
SdkProperties.setInitializeState(SdkProperties.InitializationState.INITIALIZING);
|
||||
ClientProperties.setGameId(gameId);
|
||||
SdkProperties.setTestMode(testMode);
|
||||
|
||||
if(!isSupported()) {
|
||||
DeviceLog.error("Error while initializing Unity Services: device is not supported");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INTERNAL_ERROR, "Unity Ads SDK failed to initialize due to device is not supported");
|
||||
return;
|
||||
}
|
||||
|
||||
SdkProperties.setInitializationTime(Device.getElapsedRealtime());
|
||||
SdkProperties.setInitializationTimeSinceEpoch(System.currentTimeMillis());
|
||||
|
||||
if(gameId == null || gameId.length() == 0) {
|
||||
DeviceLog.error("Error while initializing Unity Services: empty game ID, halting Unity Ads init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, "Unity Ads SDK failed to initialize due to empty game ID");
|
||||
return;
|
||||
}
|
||||
|
||||
if(context == null) {
|
||||
DeviceLog.error("Error while initializing Unity Services: null context, halting Unity Ads init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, "Unity Ads SDK failed to initialize due to null context");
|
||||
return;
|
||||
}
|
||||
|
||||
if (context instanceof Application) {
|
||||
ClientProperties.setApplication((Application) context);
|
||||
} else if (context instanceof Activity) {
|
||||
if (((Activity) context).getApplication() != null) {
|
||||
ClientProperties.setApplication(((Activity) context).getApplication());
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: cannot retrieve application from context, halting Unity Ads init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, "Unity Ads SDK failed to initialize due to inability to retrieve application from context");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: invalid context, halting Unity Ads init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, "Unity Ads SDK failed to initialize due to invalid context");
|
||||
return;
|
||||
}
|
||||
|
||||
if(testMode) {
|
||||
DeviceLog.info("Initializing Unity Services " + SdkProperties.getVersionName() + " (" + SdkProperties.getVersionCode() + ") with game id " + gameId + " in test mode, session " + Session.Default.getId());
|
||||
} else {
|
||||
DeviceLog.info("Initializing Unity Services " + SdkProperties.getVersionName() + " (" + SdkProperties.getVersionCode() + ") with game id " + gameId + " in production mode, session " + Session.Default.getId());
|
||||
}
|
||||
|
||||
SdkProperties.setDebugMode(SdkProperties.getDebugMode());
|
||||
|
||||
if (context.getApplicationContext() != null) {
|
||||
ClientProperties.setApplicationContext(context.getApplicationContext());
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: cannot retrieve application context, halting Unity Ads init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT, "Unity Ads SDK failed to initialize due to inability to retrieve application context");
|
||||
return;
|
||||
}
|
||||
|
||||
if(!EnvironmentCheck.isEnvironmentOk()) {
|
||||
DeviceLog.error("Error during Unity Services environment check, halting Unity Services init");
|
||||
SdkProperties.notifyInitializationFailed(UnityAds.UnityAdsInitializationError.INTERNAL_ERROR, "Unity Ads SDK failed to initialize due to environment check failed");
|
||||
return;
|
||||
}
|
||||
DeviceLog.info("Unity Services environment check OK");
|
||||
|
||||
ConfigurationReader configurationReader = new ConfigurationReader();
|
||||
Configuration configuration = configurationReader.getCurrentConfiguration();
|
||||
boolean isNewInitFlow = configuration.getExperiments().isNewInitFlowEnabled();
|
||||
InitializeEventsMetricSender.getInstance().setNewInitFlow(isNewInitFlow);
|
||||
if (isNewInitFlow) {
|
||||
UnityAdsSDK.INSTANCE.initialize();
|
||||
} else {
|
||||
InitializeThread.initialize(configuration);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSupported() {
|
||||
return Build.VERSION.SDK_INT >= 16;
|
||||
}
|
||||
|
||||
public static boolean isInitialized() {
|
||||
return SdkProperties.isInitialized();
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
return SdkProperties.getVersionName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles debug mode on/off
|
||||
*
|
||||
* @param debugMode If true, debug mode is on and there will be lots of debug output from Unity Services. If false, there will be only some short log messages from Unity Services.
|
||||
*/
|
||||
public static void setDebugMode(boolean debugMode) {
|
||||
SdkProperties.setDebugMode(debugMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current debug mode status
|
||||
*
|
||||
* @return If true, debug mode is on. If false, debug mode is off.
|
||||
*/
|
||||
public static boolean getDebugMode() {
|
||||
return SdkProperties.getDebugMode();
|
||||
}
|
||||
|
||||
private static String createExpectedParametersString(String fieldName, Object current, Object received) {
|
||||
String currentSafeString = current == null ? "null" : current.toString();
|
||||
String receivedSafeString = received == null ? "null" : received.toString();
|
||||
return "\n - " + fieldName + " Current: " + currentSafeString + " | Received: " + receivedSafeString;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package com.unity3d.services
|
||||
|
||||
import android.app.Activity
|
||||
import android.app.Application
|
||||
import android.content.Context
|
||||
import com.unity3d.ads.IUnityAdsInitializationListener
|
||||
import com.unity3d.ads.UnityAds
|
||||
import com.unity3d.ads.UnityAds.UnityAdsInitializationError
|
||||
import com.unity3d.services.UnityAdsSDK.initialize
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader
|
||||
import com.unity3d.services.core.configuration.EnvironmentCheck
|
||||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender
|
||||
import com.unity3d.services.core.configuration.InitializeThread
|
||||
import com.unity3d.services.core.device.Device
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.properties.ClientProperties
|
||||
import com.unity3d.services.core.properties.SdkProperties
|
||||
import com.unity3d.services.core.properties.SdkProperties.InitializationState
|
||||
import com.unity3d.services.core.properties.Session.Default.id
|
||||
import com.unity3d.services.core.request.metrics.InitMetric
|
||||
|
||||
object UnityServices {
|
||||
/**
|
||||
* Initializes Unity Ads. Unity Ads should be initialized when app starts.
|
||||
* @param context Current Android application context of calling app
|
||||
* @param gameId Unique identifier for a game, given by Unity Ads admin tools or Unity editor
|
||||
* @param testMode If true, only test ads are shown
|
||||
* @param initializationListener Listener for IUnityAdsInitializationListener callbacks
|
||||
*/
|
||||
@JvmStatic
|
||||
fun initialize(
|
||||
context: Context?,
|
||||
gameId: String?,
|
||||
testMode: Boolean,
|
||||
initializationListener: IUnityAdsInitializationListener?
|
||||
) {
|
||||
DeviceLog.entered()
|
||||
|
||||
gameId?.toIntOrNull() ?: run {
|
||||
initializationListener?.onInitializationFailed(
|
||||
UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"gameId \"$gameId\" should be a number."
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (SdkProperties.getCurrentInitializationState() != InitializationState.NOT_INITIALIZED) {
|
||||
val previousGameId = ClientProperties.getGameId()
|
||||
val previousTestMode = SdkProperties.isTestMode()
|
||||
|
||||
val differingParameters = buildString {
|
||||
if (previousGameId != null && previousGameId != gameId) {
|
||||
appendLine(createExpectedParametersString("Game ID", previousGameId, gameId))
|
||||
}
|
||||
|
||||
if (previousTestMode != testMode) {
|
||||
appendLine(createExpectedParametersString("Test Mode", previousTestMode, testMode))
|
||||
}
|
||||
}
|
||||
|
||||
val params = if (differingParameters.isNotEmpty()) {
|
||||
InitializeEventsMetricSender.getInstance().sendMetric(InitMetric.newInitDiffParams())
|
||||
"different parameters: \n$differingParameters"
|
||||
} else {
|
||||
InitializeEventsMetricSender.getInstance().sendMetric(InitMetric.newInitSameParams())
|
||||
"the same Game ID: $gameId and Test Mode: $testMode values."
|
||||
}
|
||||
|
||||
DeviceLog.warning("Unity Ads SDK initialize has already been called with $params Responding with first initialization result.")
|
||||
}
|
||||
|
||||
SdkProperties.addInitializationListener(initializationListener)
|
||||
|
||||
when (SdkProperties.getCurrentInitializationState()) {
|
||||
InitializationState.INITIALIZED_SUCCESSFULLY -> {
|
||||
SdkProperties.notifyInitializationComplete()
|
||||
return
|
||||
}
|
||||
InitializationState.INITIALIZED_FAILED -> {
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INTERNAL_ERROR,
|
||||
"Unity Ads SDK failed to initialize due to previous failed reason"
|
||||
)
|
||||
return
|
||||
}
|
||||
InitializationState.INITIALIZING -> return
|
||||
else -> SdkProperties.setInitializeState(InitializationState.INITIALIZING)
|
||||
}
|
||||
|
||||
ClientProperties.setGameId(gameId)
|
||||
SdkProperties.setTestMode(testMode)
|
||||
|
||||
if (!isSupported) {
|
||||
DeviceLog.error("Error while initializing Unity Services: device is not supported")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INTERNAL_ERROR,
|
||||
"Unity Ads SDK failed to initialize due to device is not supported"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
SdkProperties.setInitializationTime(Device.getElapsedRealtime())
|
||||
SdkProperties.setInitializationTimeSinceEpoch(System.currentTimeMillis())
|
||||
|
||||
if (gameId.isNullOrEmpty()) {
|
||||
DeviceLog.error("Error while initializing Unity Services: empty game ID, halting Unity Ads init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"Unity Ads SDK failed to initialize due to empty game ID"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (context == null) {
|
||||
DeviceLog.error("Error while initializing Unity Services: null context, halting Unity Ads init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"Unity Ads SDK failed to initialize due to null context"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (context is Application) {
|
||||
ClientProperties.setApplication(context)
|
||||
} else if (context is Activity) {
|
||||
if (context.application != null) {
|
||||
ClientProperties.setApplication(context.application)
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: cannot retrieve application from context, halting Unity Ads init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"Unity Ads SDK failed to initialize due to inability to retrieve application from context"
|
||||
)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: invalid context, halting Unity Ads init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"Unity Ads SDK failed to initialize due to invalid context"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
val mode = if (testMode) "test mode" else "production mode"
|
||||
DeviceLog.info("Initializing Unity Services ${SdkProperties.getVersionName()} (${SdkProperties.getVersionCode()}) with game id $gameId in $mode, session $id")
|
||||
|
||||
SdkProperties.setDebugMode(SdkProperties.getDebugMode())
|
||||
|
||||
if (context.applicationContext != null) {
|
||||
ClientProperties.setApplicationContext(context.applicationContext)
|
||||
} else {
|
||||
DeviceLog.error("Error while initializing Unity Services: cannot retrieve application context, halting Unity Ads init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INVALID_ARGUMENT,
|
||||
"Unity Ads SDK failed to initialize due to inability to retrieve application context"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
if (!EnvironmentCheck.isEnvironmentOk()) {
|
||||
DeviceLog.error("Error during Unity Services environment check, halting Unity Services init")
|
||||
SdkProperties.notifyInitializationFailed(
|
||||
UnityAds.UnityAdsInitializationError.INTERNAL_ERROR,
|
||||
"Unity Ads SDK failed to initialize due to environment check failed"
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
DeviceLog.info("Unity Services environment check OK")
|
||||
|
||||
initialize()
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
val isSupported: Boolean = true
|
||||
|
||||
@JvmStatic
|
||||
val isInitialized: Boolean
|
||||
get() = SdkProperties.isInitialized()
|
||||
|
||||
@JvmStatic
|
||||
val version: String
|
||||
get() = SdkProperties.getVersionName()
|
||||
|
||||
@JvmStatic
|
||||
var debugMode: Boolean
|
||||
/**
|
||||
* Get current debug mode status
|
||||
*
|
||||
* @return If true, debug mode is on. If false, debug mode is off.
|
||||
*/
|
||||
get() = SdkProperties.getDebugMode()
|
||||
/**
|
||||
* Toggles debug mode on/off
|
||||
*
|
||||
* @param debugMode If true, debug mode is on and there will be lots of debug output from Unity Services. If false, there will be only some short log messages from Unity Services.
|
||||
*/
|
||||
set(debugMode) {
|
||||
SdkProperties.setDebugMode(debugMode)
|
||||
}
|
||||
|
||||
private fun createExpectedParametersString(fieldName: String, current: Any?, received: Any?): String =
|
||||
"- $fieldName Current: $current | Received: $received"
|
||||
|
||||
enum class UnityServicesError {
|
||||
INVALID_ARGUMENT,
|
||||
INIT_SANITY_CHECK_FAIL
|
||||
}
|
||||
}
|
|
@ -1,5 +1,7 @@
|
|||
package com.unity3d.services.ads;
|
||||
|
||||
import static com.unity3d.services.core.misc.Utilities.wrapCustomerListener;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
|
@ -21,11 +23,12 @@ import com.unity3d.services.ads.token.AsyncTokenStorage;
|
|||
import com.unity3d.services.ads.token.TokenStorage;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.IExperiments;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewBridgeInvoker;
|
||||
|
||||
|
@ -33,6 +36,9 @@ public final class UnityAdsImplementation implements IUnityAds {
|
|||
private static Configuration configuration = null;
|
||||
private static WebViewBridgeInvoker webViewBridgeInvoker = new WebViewBridgeInvoker();
|
||||
private static IUnityAds instance;
|
||||
private final TokenStorage tokenStorage = Utilities.getService(TokenStorage.class);
|
||||
private final AsyncTokenStorage asyncTokenStorage = Utilities.getService(AsyncTokenStorage.class);
|
||||
private final SDKMetricsSender sdkMetricsSender = Utilities.getService(SDKMetricsSender.class);
|
||||
|
||||
public static IUnityAds getInstance() {
|
||||
if (instance == null) {
|
||||
|
@ -138,7 +144,7 @@ public final class UnityAdsImplementation implements IUnityAds {
|
|||
}
|
||||
|
||||
private void handleShowError(IUnityAdsShowListener showListener, String placementId, UnityAds.UnityAdsShowError error, String message) {
|
||||
SDKMetrics.getInstance().sendMetricWithInitState(AdOperationMetric.newAdShowFailure(error, 0L));
|
||||
sdkMetricsSender.sendMetricWithInitState(AdOperationMetric.newAdShowFailure(error, 0L));
|
||||
if (showListener == null) return;
|
||||
showListener.onUnityAdsShowFailure(placementId, error, message);
|
||||
}
|
||||
|
@ -172,7 +178,7 @@ public final class UnityAdsImplementation implements IUnityAds {
|
|||
@Override
|
||||
public String getToken() {
|
||||
// Getting the available token from storage
|
||||
final String token = TokenStorage.getInstance().getToken();
|
||||
final String token = tokenStorage.getToken();
|
||||
if (token == null || token.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
@ -191,14 +197,16 @@ public final class UnityAdsImplementation implements IUnityAds {
|
|||
return;
|
||||
} else if (ClientProperties.getApplicationContext() == null) {
|
||||
// Invalidating app Context.
|
||||
listener.onUnityAdsTokenReady(null);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsTokenReady(null));
|
||||
return;
|
||||
}
|
||||
|
||||
Configuration config = configuration == null ? new ConfigurationReader().getCurrentConfiguration() : configuration;
|
||||
BiddingBaseManager manager = BiddingManagerFactory.getInstance().createManager(listener, config.getExperiments());
|
||||
manager.start();
|
||||
AsyncTokenStorage.getInstance().getToken(manager);
|
||||
|
||||
asyncTokenStorage.getToken(manager);
|
||||
}
|
||||
|
||||
public static void setConfiguration(Configuration configuration) {
|
||||
|
|
|
@ -1,34 +1,16 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.unity3d.services.ads.api.AdUnit;
|
||||
import com.unity3d.services.core.api.Intent;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.misc.ViewUtilities;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
import com.unity3d.services.core.webview.bridge.SharedInstances;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AdUnitActivity extends Activity {
|
||||
public class AdUnitActivity extends Activity implements IAdUnitActivity {
|
||||
|
||||
public static final String EXTRA_VIEWS = "views";
|
||||
public static final String EXTRA_ACTIVITY_ID = "activityId";
|
||||
|
@ -38,480 +20,141 @@ public class AdUnitActivity extends Activity {
|
|||
public static final String EXTRA_KEEP_SCREEN_ON = "keepScreenOn";
|
||||
public static final String EXTRA_DISPLAY_CUTOUT_MODE = "displayCutoutMode";
|
||||
|
||||
protected AdUnitRelativeLayout _layout;
|
||||
private String[] _views;
|
||||
private int _orientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
private int _systemUiVisibility;
|
||||
private int _activityId;
|
||||
private ArrayList<Integer> _keyEventList;
|
||||
boolean _keepScreenOn;
|
||||
private Map<String, IAdUnitViewHandler> _viewHandlers;
|
||||
private int _displayCutoutMode;
|
||||
protected AdUnitActivityController _controller;
|
||||
|
||||
private final IAdUnitViewHandlerFactory _adUnitViewHandlerFactory = new AdUnitViewHandlerFactory();
|
||||
protected AdUnitActivityController createController() {
|
||||
return new AdUnitActivityController(this, SharedInstances.INSTANCE.getWebViewEventSender(), new AdUnitViewHandlerFactory());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// This error condition will trigger if activity is backgrounded while activity is in foreground,
|
||||
// app process is killed while app is in background and then app is yet again launched to foreground
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onCreate");
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
AdUnit.setAdUnitActivity(this);
|
||||
Intent.setActiveActivity(this);
|
||||
|
||||
createLayout();
|
||||
|
||||
ViewUtilities.removeViewFromParent(_layout);
|
||||
addContentView(_layout, _layout.getLayoutParams());
|
||||
|
||||
AdUnitEvent event;
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
_views = getIntent().getStringArrayExtra(EXTRA_VIEWS);
|
||||
_keyEventList = getIntent().getIntegerArrayListExtra(EXTRA_KEY_EVENT_LIST);
|
||||
|
||||
if (getIntent().hasExtra(EXTRA_ORIENTATION)) {
|
||||
_orientation = getIntent().getIntExtra(EXTRA_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
}
|
||||
if (getIntent().hasExtra(EXTRA_SYSTEM_UI_VISIBILITY)) {
|
||||
_systemUiVisibility = getIntent().getIntExtra(EXTRA_SYSTEM_UI_VISIBILITY, 0);
|
||||
}
|
||||
if (getIntent().hasExtra(EXTRA_ACTIVITY_ID)) {
|
||||
_activityId = getIntent().getIntExtra(EXTRA_ACTIVITY_ID, -1);
|
||||
}
|
||||
if (getIntent().hasExtra(EXTRA_DISPLAY_CUTOUT_MODE)) {
|
||||
_displayCutoutMode = getIntent().getIntExtra(EXTRA_DISPLAY_CUTOUT_MODE, 0);
|
||||
}
|
||||
|
||||
event = AdUnitEvent.ON_CREATE;
|
||||
} else {
|
||||
_views = savedInstanceState.getStringArray(EXTRA_VIEWS);
|
||||
_orientation = savedInstanceState.getInt(EXTRA_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
_systemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
|
||||
_keyEventList = savedInstanceState.getIntegerArrayList(EXTRA_KEY_EVENT_LIST);
|
||||
_keepScreenOn = savedInstanceState.getBoolean(EXTRA_KEEP_SCREEN_ON);
|
||||
_activityId = savedInstanceState.getInt(EXTRA_ACTIVITY_ID, -1);
|
||||
_displayCutoutMode = savedInstanceState.getInt(EXTRA_DISPLAY_CUTOUT_MODE, 0);
|
||||
setKeepScreenOn(_keepScreenOn);
|
||||
event = AdUnitEvent.ON_RESTORE;
|
||||
}
|
||||
|
||||
setOrientation(_orientation);
|
||||
setSystemUiVisibility(_systemUiVisibility);
|
||||
setLayoutInDisplayCutoutMode(_displayCutoutMode);
|
||||
|
||||
if(_views != null) {
|
||||
for (String viewName : _views) {
|
||||
IAdUnitViewHandler handler = getViewHandler(viewName);
|
||||
|
||||
if (handler != null) {
|
||||
handler.onCreate(this, savedInstanceState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, event, _activityId);
|
||||
_controller = createController();
|
||||
_controller.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
public AdUnitRelativeLayout getLayout() {
|
||||
return _layout;
|
||||
return _controller.getLayout();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
if(!isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onStart");
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onStart(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_START, _activityId);
|
||||
_controller.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop();
|
||||
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
if(!isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onStop");
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onStop(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_STOP, _activityId);
|
||||
_controller.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
if(!isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onResume");
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setViews(_views);
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onResume(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_RESUME, _activityId);
|
||||
_controller.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
if(!isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onPause");
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (WebViewApp.getCurrentApp().getWebView() == null) {
|
||||
DeviceLog.warning("Unity Ads web view is null, from onPause");
|
||||
} else if (isFinishing()) {
|
||||
ViewUtilities.removeViewFromParent(WebViewApp.getCurrentApp().getWebView());
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onPause(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_PAUSE, isFinishing(), _activityId);
|
||||
_controller.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putInt(EXTRA_ORIENTATION, _orientation);
|
||||
outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, _systemUiVisibility);
|
||||
outState.putIntegerArrayList(EXTRA_KEY_EVENT_LIST, _keyEventList);
|
||||
outState.putBoolean(EXTRA_KEEP_SCREEN_ON, _keepScreenOn);
|
||||
outState.putStringArray(EXTRA_VIEWS, _views);
|
||||
outState.putInt(EXTRA_ACTIVITY_ID, _activityId);
|
||||
_controller.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
|
||||
if(WebViewApp.getCurrentApp() == null) {
|
||||
if(!isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onDestroy");
|
||||
finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_DESTROY, isFinishing(), _activityId);
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onDestroy(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AdUnit.getCurrentAdUnitActivityId() == _activityId) {
|
||||
AdUnit.setAdUnitActivity(null);
|
||||
}
|
||||
|
||||
Intent.removeActiveActivity(this);
|
||||
_controller.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (_keyEventList != null) {
|
||||
if (_keyEventList.contains(keyCode)) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.KEY_DOWN, keyCode, event.getEventTime(), event.getDownTime(), event.getRepeatCount(), _activityId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return _controller.onKeyDown(keyCode, event);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_FOCUS_GAINED, _activityId);
|
||||
} else {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_FOCUS_LOST, _activityId);
|
||||
}
|
||||
_controller.onWindowFocusChanged(hasFocus);
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
try {
|
||||
JSONArray permissionsArray = new JSONArray();
|
||||
JSONArray grantResultsArray = new JSONArray();
|
||||
|
||||
for (String permission : permissions) {
|
||||
permissionsArray.put(permission);
|
||||
}
|
||||
|
||||
for (int grantResult : grantResults) {
|
||||
grantResultsArray.put(grantResult);
|
||||
}
|
||||
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.PERMISSIONS, PermissionsEvent.PERMISSIONS_RESULT, requestCode, permissionsArray, grantResultsArray);
|
||||
}
|
||||
catch (Exception e) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.PERMISSIONS, PermissionsEvent.PERMISSIONS_ERROR, e.getMessage());
|
||||
}
|
||||
_controller.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||
}
|
||||
|
||||
/* API */
|
||||
|
||||
@Override
|
||||
public void setViewFrame (String view, int x, int y, int width, int height) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
View targetView = null;
|
||||
|
||||
if (view.equals("adunit")) {
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
|
||||
params.setMargins(x, y, 0, 0);
|
||||
_layout.setLayoutParams(params);
|
||||
}
|
||||
else if (handler != null) {
|
||||
targetView = handler.getView();
|
||||
}
|
||||
|
||||
if (targetView != null) {
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
|
||||
params.setMargins(x, y, 0, 0);
|
||||
targetView.setLayoutParams(params);
|
||||
}
|
||||
_controller.setViewFrame(view, x, y, width, height);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Integer> getViewFrame (String view) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
View targetView = null;
|
||||
|
||||
if (view.equals("adunit")) {
|
||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)_layout.getLayoutParams();
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
map.put("x", params.leftMargin);
|
||||
map.put("y", params.topMargin);
|
||||
map.put("width", _layout.getWidth());
|
||||
map.put("height", _layout.getHeight());
|
||||
return map;
|
||||
}
|
||||
else if (handler != null) {
|
||||
targetView = handler.getView();
|
||||
}
|
||||
|
||||
if (targetView != null) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)targetView.getLayoutParams();
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
map.put("x", params.leftMargin);
|
||||
map.put("y", params.topMargin);
|
||||
map.put("width", targetView.getWidth());
|
||||
map.put("height", targetView.getHeight());
|
||||
return map;
|
||||
}
|
||||
|
||||
return null;
|
||||
return _controller.getViewFrame(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setViews (String[] views) {
|
||||
String[] actualViews;
|
||||
|
||||
if (views == null)
|
||||
actualViews = new String[0];
|
||||
else
|
||||
actualViews = views;
|
||||
|
||||
ArrayList<String> newViews = new ArrayList<>(Arrays.asList(actualViews));
|
||||
|
||||
if (_views == null) {
|
||||
_views = new String[0];
|
||||
}
|
||||
|
||||
ArrayList<String> removedViews = new ArrayList<>(Arrays.asList(_views));
|
||||
removedViews.removeAll(newViews);
|
||||
|
||||
for (String view : removedViews) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
handler.destroy();
|
||||
}
|
||||
|
||||
_views = actualViews;
|
||||
|
||||
for (String view : actualViews) {
|
||||
if (view == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
handler.create(this);
|
||||
if (!handleViewPlacement(handler.getView())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_controller.setViews(views);
|
||||
}
|
||||
|
||||
private boolean handleViewPlacement (View view) {
|
||||
if (view == null) {
|
||||
finish();
|
||||
DeviceLog.error("Could not place view because it is null, finishing activity");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (view.getParent() != null && view.getParent().equals(_layout)) {
|
||||
_layout.bringChildToFront(view);
|
||||
}
|
||||
else {
|
||||
ViewUtilities.removeViewFromParent(view);
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
|
||||
params.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||
params.setMargins(0, 0, 0, 0);
|
||||
view.setPadding(0, 0, 0, 0);
|
||||
_layout.addView(view, params);
|
||||
}
|
||||
|
||||
return true;
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String[] getViews () {
|
||||
return _views;
|
||||
return _controller.getViews();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOrientation (int orientation) {
|
||||
_orientation = orientation;
|
||||
setRequestedOrientation(orientation);
|
||||
_controller.setOrientation(orientation);
|
||||
}
|
||||
|
||||
// Returns true if successfully set, false if error
|
||||
@Override
|
||||
public boolean setKeepScreenOn(boolean keepScreenOn) {
|
||||
_keepScreenOn = keepScreenOn;
|
||||
|
||||
// If activity is non-visual there is no window
|
||||
if(getWindow() == null)
|
||||
return false;
|
||||
|
||||
if(keepScreenOn) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
} else {
|
||||
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
return true;
|
||||
return _controller.setKeepScreenOn(keepScreenOn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setSystemUiVisibility (int flags) {
|
||||
_systemUiVisibility = flags;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
try {
|
||||
getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
DeviceLog.exception("Error while setting SystemUIVisibility", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return _controller.setSystemUiVisibility(flags);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setKeyEventList (ArrayList<Integer> keyevents) {
|
||||
_keyEventList = keyevents;
|
||||
_controller.setKeyEventList(keyevents);
|
||||
}
|
||||
|
||||
public IAdUnitViewHandler getViewHandler(String name) {
|
||||
IAdUnitViewHandler viewHandler;
|
||||
|
||||
if (_viewHandlers != null && _viewHandlers.containsKey(name)) {
|
||||
viewHandler = _viewHandlers.get(name);
|
||||
}
|
||||
else {
|
||||
viewHandler = _adUnitViewHandlerFactory.createViewHandler(name);
|
||||
|
||||
if (viewHandler != null) {
|
||||
if (_viewHandlers == null) {
|
||||
_viewHandlers = new HashMap<>();
|
||||
}
|
||||
|
||||
_viewHandlers.put(name, viewHandler);
|
||||
}
|
||||
}
|
||||
|
||||
return viewHandler;
|
||||
return _controller.getViewHandler(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLayoutInDisplayCutoutMode(int flags) {
|
||||
_displayCutoutMode = flags;
|
||||
|
||||
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES also needs system ui flags View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
if (Build.VERSION.SDK_INT >= 28 && getWindow() != null) {
|
||||
WindowManager.LayoutParams lp = getWindow().getAttributes();
|
||||
try {
|
||||
Field layoutInDisplayCutoutMode = lp.getClass().getField("layoutInDisplayCutoutMode");
|
||||
layoutInDisplayCutoutMode.setInt(lp, flags);
|
||||
} catch (IllegalAccessException e) {
|
||||
DeviceLog.debug("Error setting layoutInDisplayCutoutMode", e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
DeviceLog.debug("Error getting layoutInDisplayCutoutMode", e);
|
||||
}
|
||||
}
|
||||
_controller.setLayoutInDisplayCutoutMode(flags);
|
||||
}
|
||||
|
||||
/* LAYOUT */
|
||||
|
||||
protected void createLayout () {
|
||||
if (_layout != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_layout = new AdUnitRelativeLayout(this);
|
||||
_layout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
ViewUtilities.setBackground(_layout, new ColorDrawable(Color.BLACK));
|
||||
@Override
|
||||
public Activity getActivity() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,498 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import static com.unity3d.services.ads.adunit.AdUnitActivity.*;
|
||||
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
import com.unity3d.services.ads.api.AdUnit;
|
||||
import com.unity3d.services.core.api.Intent;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.misc.ViewUtilities;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class AdUnitActivityController {
|
||||
|
||||
protected AdUnitRelativeLayout _layout;
|
||||
private String[] _views;
|
||||
private int _orientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
|
||||
private int _systemUiVisibility;
|
||||
private int _activityId;
|
||||
private ArrayList<Integer> _keyEventList;
|
||||
boolean _keepScreenOn;
|
||||
private Map<String, IAdUnitViewHandler> _viewHandlers;
|
||||
private int _displayCutoutMode;
|
||||
private final IAdUnitActivity _adUnitActivity;
|
||||
|
||||
private final IEventSender _eventSender;
|
||||
private final IAdUnitViewHandlerFactory _adUnitViewHandlerFactory;
|
||||
|
||||
public AdUnitActivityController(IAdUnitActivity activity, IEventSender eventSender, IAdUnitViewHandlerFactory adUnitViewHandlerFactory) {
|
||||
_adUnitActivity = activity;
|
||||
_eventSender = eventSender;
|
||||
_adUnitViewHandlerFactory = adUnitViewHandlerFactory;
|
||||
}
|
||||
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
// This error condition will trigger if activity is backgrounded while activity is in foreground,
|
||||
// app process is killed while app is in background and then app is yet again launched to foreground
|
||||
if(!_eventSender.canSend()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onCreate");
|
||||
_adUnitActivity.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
AdUnit.setAdUnitActivity(_adUnitActivity);
|
||||
Intent.setActiveActivity(_adUnitActivity.getActivity());
|
||||
|
||||
createLayout();
|
||||
|
||||
ViewUtilities.removeViewFromParent(_layout);
|
||||
_adUnitActivity.addContentView(_layout, _layout.getLayoutParams());
|
||||
|
||||
AdUnitEvent event;
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
_views = _adUnitActivity.getIntent().getStringArrayExtra(EXTRA_VIEWS);
|
||||
_keyEventList = _adUnitActivity.getIntent().getIntegerArrayListExtra(EXTRA_KEY_EVENT_LIST);
|
||||
|
||||
if (_adUnitActivity.getIntent().hasExtra(EXTRA_ORIENTATION)) {
|
||||
_orientation = _adUnitActivity.getIntent().getIntExtra(EXTRA_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
}
|
||||
if (_adUnitActivity.getIntent().hasExtra(EXTRA_SYSTEM_UI_VISIBILITY)) {
|
||||
_systemUiVisibility = _adUnitActivity.getIntent().getIntExtra(EXTRA_SYSTEM_UI_VISIBILITY, 0);
|
||||
}
|
||||
if (_adUnitActivity.getIntent().hasExtra(EXTRA_ACTIVITY_ID)) {
|
||||
_activityId = _adUnitActivity.getIntent().getIntExtra(EXTRA_ACTIVITY_ID, -1);
|
||||
}
|
||||
if (_adUnitActivity.getIntent().hasExtra(EXTRA_DISPLAY_CUTOUT_MODE)) {
|
||||
_displayCutoutMode = _adUnitActivity.getIntent().getIntExtra(EXTRA_DISPLAY_CUTOUT_MODE, 0);
|
||||
}
|
||||
|
||||
event = AdUnitEvent.ON_CREATE;
|
||||
} else {
|
||||
_views = savedInstanceState.getStringArray(EXTRA_VIEWS);
|
||||
_orientation = savedInstanceState.getInt(EXTRA_ORIENTATION, ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
|
||||
_systemUiVisibility = savedInstanceState.getInt(EXTRA_SYSTEM_UI_VISIBILITY, 0);
|
||||
_keyEventList = savedInstanceState.getIntegerArrayList(EXTRA_KEY_EVENT_LIST);
|
||||
_keepScreenOn = savedInstanceState.getBoolean(EXTRA_KEEP_SCREEN_ON);
|
||||
_activityId = savedInstanceState.getInt(EXTRA_ACTIVITY_ID, -1);
|
||||
_displayCutoutMode = savedInstanceState.getInt(EXTRA_DISPLAY_CUTOUT_MODE, 0);
|
||||
setKeepScreenOn(_keepScreenOn);
|
||||
event = AdUnitEvent.ON_RESTORE;
|
||||
}
|
||||
|
||||
setOrientation(_orientation);
|
||||
setSystemUiVisibility(_systemUiVisibility);
|
||||
setLayoutInDisplayCutoutMode(_displayCutoutMode);
|
||||
|
||||
if(_views != null) {
|
||||
for (String viewName : _views) {
|
||||
IAdUnitViewHandler handler = getViewHandler(viewName);
|
||||
|
||||
if (handler != null) {
|
||||
handler.onCreate(_adUnitActivity, savedInstanceState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, event, _activityId);
|
||||
}
|
||||
|
||||
public AdUnitRelativeLayout getLayout() {
|
||||
return _layout;
|
||||
}
|
||||
|
||||
public void onStart() {
|
||||
if(!_eventSender.canSend()) {
|
||||
if(!_adUnitActivity.isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onStart");
|
||||
_adUnitActivity.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onStart(_adUnitActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_START, _activityId);
|
||||
}
|
||||
|
||||
public void onStop() {
|
||||
if(!_eventSender.canSend()) {
|
||||
if(!_adUnitActivity.isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onStop");
|
||||
_adUnitActivity.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onStop(_adUnitActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_STOP, _activityId);
|
||||
}
|
||||
|
||||
public void onResume() {
|
||||
if(!_eventSender.canSend()) {
|
||||
if(!_adUnitActivity.isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onResume");
|
||||
_adUnitActivity.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
setViews(_views);
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onResume(_adUnitActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_RESUME, _activityId);
|
||||
}
|
||||
|
||||
public void onPause() {
|
||||
if(!_eventSender.canSend()) {
|
||||
if(!_adUnitActivity.isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onPause");
|
||||
_adUnitActivity.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (WebViewApp.getCurrentApp().getWebView() == null) {
|
||||
DeviceLog.warning("Unity Ads web view is null, from onPause");
|
||||
} else if (_adUnitActivity.isFinishing()) {
|
||||
ViewUtilities.removeViewFromParent(WebViewApp.getCurrentApp().getWebView());
|
||||
}
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onPause(_adUnitActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_PAUSE, _adUnitActivity.isFinishing(), _activityId);
|
||||
}
|
||||
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
outState.putInt(EXTRA_ORIENTATION, _orientation);
|
||||
outState.putInt(EXTRA_SYSTEM_UI_VISIBILITY, _systemUiVisibility);
|
||||
outState.putIntegerArrayList(EXTRA_KEY_EVENT_LIST, _keyEventList);
|
||||
outState.putBoolean(EXTRA_KEEP_SCREEN_ON, _keepScreenOn);
|
||||
outState.putStringArray(EXTRA_VIEWS, _views);
|
||||
outState.putInt(EXTRA_ACTIVITY_ID, _activityId);
|
||||
}
|
||||
|
||||
public void onDestroy() {
|
||||
if(!_eventSender.canSend()) {
|
||||
if(!_adUnitActivity.isFinishing()) {
|
||||
DeviceLog.error("Unity Ads web app is null, closing Unity Ads activity from onDestroy");
|
||||
_adUnitActivity.finish();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_DESTROY, _adUnitActivity.isFinishing(), _activityId);
|
||||
|
||||
if (_viewHandlers != null) {
|
||||
for (Map.Entry<String, IAdUnitViewHandler> entry : _viewHandlers.entrySet()) {
|
||||
if (entry.getValue() != null) {
|
||||
entry.getValue().onDestroy(_adUnitActivity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AdUnit.getCurrentAdUnitActivityId() == _activityId) {
|
||||
AdUnit.setAdUnitActivity(null);
|
||||
}
|
||||
|
||||
Intent.removeActiveActivity(_adUnitActivity.getActivity());
|
||||
}
|
||||
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (_keyEventList != null) {
|
||||
if (_keyEventList.contains(keyCode)) {
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.KEY_DOWN, keyCode, event.getEventTime(), event.getDownTime(), event.getRepeatCount(), _activityId);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_FOCUS_GAINED, _activityId);
|
||||
} else {
|
||||
_eventSender.sendEvent(WebViewEventCategory.ADUNIT, AdUnitEvent.ON_FOCUS_LOST, _activityId);
|
||||
}
|
||||
}
|
||||
|
||||
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
|
||||
try {
|
||||
JSONArray permissionsArray = new JSONArray();
|
||||
JSONArray grantResultsArray = new JSONArray();
|
||||
|
||||
for (String permission : permissions) {
|
||||
permissionsArray.put(permission);
|
||||
}
|
||||
|
||||
for (int grantResult : grantResults) {
|
||||
grantResultsArray.put(grantResult);
|
||||
}
|
||||
|
||||
_eventSender.sendEvent(WebViewEventCategory.PERMISSIONS, PermissionsEvent.PERMISSIONS_RESULT, requestCode, permissionsArray, grantResultsArray);
|
||||
}
|
||||
catch (Exception e) {
|
||||
_eventSender.sendEvent(WebViewEventCategory.PERMISSIONS, PermissionsEvent.PERMISSIONS_ERROR, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* API */
|
||||
|
||||
public void setViewFrame (String view, int x, int y, int width, int height) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
View targetView = null;
|
||||
|
||||
if (view.equals("adunit")) {
|
||||
FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, height);
|
||||
params.setMargins(x, y, 0, 0);
|
||||
_layout.setLayoutParams(params);
|
||||
}
|
||||
else if (handler != null) {
|
||||
targetView = handler.getView();
|
||||
}
|
||||
|
||||
if (targetView != null) {
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(width, height);
|
||||
params.setMargins(x, y, 0, 0);
|
||||
targetView.setLayoutParams(params);
|
||||
}
|
||||
}
|
||||
|
||||
public Map<String, Integer> getViewFrame (String view) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
View targetView = null;
|
||||
|
||||
if (view.equals("adunit")) {
|
||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams)_layout.getLayoutParams();
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
map.put("x", params.leftMargin);
|
||||
map.put("y", params.topMargin);
|
||||
map.put("width", _layout.getWidth());
|
||||
map.put("height", _layout.getHeight());
|
||||
return map;
|
||||
}
|
||||
else if (handler != null) {
|
||||
targetView = handler.getView();
|
||||
}
|
||||
|
||||
if (targetView != null) {
|
||||
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)targetView.getLayoutParams();
|
||||
HashMap<String, Integer> map = new HashMap<>();
|
||||
map.put("x", params.leftMargin);
|
||||
map.put("y", params.topMargin);
|
||||
map.put("width", targetView.getWidth());
|
||||
map.put("height", targetView.getHeight());
|
||||
return map;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setViews (String[] views) {
|
||||
String[] actualViews;
|
||||
|
||||
if (views == null)
|
||||
actualViews = new String[0];
|
||||
else
|
||||
actualViews = views;
|
||||
|
||||
ArrayList<String> newViews = new ArrayList<>(Arrays.asList(actualViews));
|
||||
|
||||
if (_views == null) {
|
||||
_views = new String[0];
|
||||
}
|
||||
|
||||
ArrayList<String> removedViews = new ArrayList<>(Arrays.asList(_views));
|
||||
removedViews.removeAll(newViews);
|
||||
|
||||
for (String view : removedViews) {
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
handler.destroy();
|
||||
}
|
||||
|
||||
_views = actualViews;
|
||||
|
||||
for (String view : actualViews) {
|
||||
if (view == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IAdUnitViewHandler handler = getViewHandler(view);
|
||||
handler.create(_adUnitActivity);
|
||||
if (!handleViewPlacement(handler.getView())) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean handleViewPlacement (View view) {
|
||||
if (view == null) {
|
||||
_adUnitActivity.finish();
|
||||
DeviceLog.error("Could not place view because it is null, finishing activity");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (view.getParent() != null && view.getParent().equals(_layout)) {
|
||||
_layout.bringChildToFront(view);
|
||||
}
|
||||
else {
|
||||
ViewUtilities.removeViewFromParent(view);
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
|
||||
params.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||
params.setMargins(0, 0, 0, 0);
|
||||
view.setPadding(0, 0, 0, 0);
|
||||
_layout.addView(view, params);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getViews () {
|
||||
return _views;
|
||||
}
|
||||
|
||||
public void setOrientation (int orientation) {
|
||||
_orientation = orientation;
|
||||
_adUnitActivity.setRequestedOrientation(orientation);
|
||||
}
|
||||
|
||||
// Returns true if successfully set, false if error
|
||||
public boolean setKeepScreenOn(boolean keepScreenOn) {
|
||||
_keepScreenOn = keepScreenOn;
|
||||
|
||||
// If activity is non-visual there is no window
|
||||
if(_adUnitActivity.getWindow() == null)
|
||||
return false;
|
||||
|
||||
if(keepScreenOn) {
|
||||
_adUnitActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
} else {
|
||||
_adUnitActivity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean setSystemUiVisibility (int flags) {
|
||||
_systemUiVisibility = flags;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 11) {
|
||||
try {
|
||||
_adUnitActivity.getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
return true;
|
||||
}
|
||||
catch (Exception e) {
|
||||
DeviceLog.exception("Error while setting SystemUIVisibility", e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void setKeyEventList (ArrayList<Integer> keyevents) {
|
||||
_keyEventList = keyevents;
|
||||
}
|
||||
|
||||
public IAdUnitViewHandler getViewHandler(String name) {
|
||||
IAdUnitViewHandler viewHandler;
|
||||
|
||||
if (_viewHandlers != null && _viewHandlers.containsKey(name)) {
|
||||
viewHandler = _viewHandlers.get(name);
|
||||
}
|
||||
else {
|
||||
viewHandler = createViewHandler(name);
|
||||
|
||||
if (viewHandler != null) {
|
||||
if (_viewHandlers == null) {
|
||||
_viewHandlers = new HashMap<>();
|
||||
}
|
||||
|
||||
_viewHandlers.put(name, viewHandler);
|
||||
}
|
||||
}
|
||||
|
||||
return viewHandler;
|
||||
}
|
||||
|
||||
public void setLayoutInDisplayCutoutMode(int flags) {
|
||||
_displayCutoutMode = flags;
|
||||
|
||||
// LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES also needs system ui flags View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
if (Build.VERSION.SDK_INT >= 28 && _adUnitActivity.getWindow() != null) {
|
||||
WindowManager.LayoutParams lp = _adUnitActivity.getWindow().getAttributes();
|
||||
try {
|
||||
Field layoutInDisplayCutoutMode = lp.getClass().getField("layoutInDisplayCutoutMode");
|
||||
layoutInDisplayCutoutMode.setInt(lp, flags);
|
||||
} catch (IllegalAccessException e) {
|
||||
DeviceLog.debug("Error setting layoutInDisplayCutoutMode", e);
|
||||
} catch (NoSuchFieldException e) {
|
||||
DeviceLog.debug("Error getting layoutInDisplayCutoutMode", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* LAYOUT */
|
||||
|
||||
protected void createLayout () {
|
||||
if (_layout != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
_layout = new AdUnitRelativeLayout(_adUnitActivity.getContext());
|
||||
_layout.setLayoutParams(new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
|
||||
ViewUtilities.setBackground(_layout, new ColorDrawable(Color.BLACK));
|
||||
}
|
||||
|
||||
private IAdUnitViewHandler createViewHandler(String name) {
|
||||
return _adUnitViewHandlerFactory.createViewHandler(name);
|
||||
}
|
||||
}
|
|
@ -3,9 +3,11 @@ package com.unity3d.services.ads.adunit;
|
|||
import android.os.ConditionVariable;
|
||||
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
|
||||
|
@ -16,6 +18,7 @@ import java.lang.reflect.Method;
|
|||
public class AdUnitOpen {
|
||||
private static ConditionVariable _waitShowStatus;
|
||||
private static Configuration _configuration;
|
||||
private static final SDKMetricsSender _sdkMetricsSender = Utilities.getService(SDKMetricsSender.class);
|
||||
|
||||
public static synchronized boolean open(String placementId, JSONObject options) throws NoSuchMethodException {
|
||||
Method showCallback = AdUnitOpen.class.getMethod("showCallback", CallbackStatus.class);
|
||||
|
@ -27,7 +30,7 @@ public class AdUnitOpen {
|
|||
boolean success = _waitShowStatus.block(_configuration.getShowTimeout());
|
||||
_waitShowStatus = null;
|
||||
if (!success) {
|
||||
SDKMetrics.getInstance().sendMetric(AdOperationMetric.newAdShowFailure(AdOperationError.timeout, Long.valueOf(_configuration.getShowTimeout())));
|
||||
_sdkMetricsSender.sendMetric(AdOperationMetric.newAdShowFailure(AdOperationError.timeout, Long.valueOf(_configuration.getShowTimeout())));
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.util.SparseArray;
|
||||
import android.util.SparseIntArray;
|
||||
import android.view.InputEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.RelativeLayout;
|
||||
|
||||
|
@ -13,6 +19,7 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
private final ArrayList<AdUnitMotionEvent> _motionEvents = new ArrayList<>();
|
||||
private int _maxEvents = 10000;
|
||||
private boolean _shouldCapture = false;
|
||||
private InputEvent _lastInputEvent;
|
||||
|
||||
public AdUnitRelativeLayout(Context context) {
|
||||
super(context);
|
||||
|
@ -22,6 +29,13 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
public boolean onInterceptTouchEvent(MotionEvent e) {
|
||||
super.onInterceptTouchEvent(e);
|
||||
|
||||
if (e.getActionMasked() == ACTION_UP ||
|
||||
e.getActionMasked() == ACTION_DOWN ||
|
||||
e.getActionMasked() == ACTION_POINTER_UP ||
|
||||
e.getActionMasked() == ACTION_POINTER_DOWN) {
|
||||
_lastInputEvent = e;
|
||||
}
|
||||
|
||||
if (_shouldCapture) {
|
||||
if (_motionEvents.size() < _maxEvents) {
|
||||
boolean isObscured = (e.getFlags() & MotionEvent.FLAG_WINDOW_IS_OBSCURED) != 0;
|
||||
|
@ -102,4 +116,8 @@ public class AdUnitRelativeLayout extends RelativeLayout {
|
|||
|
||||
return returnArray;
|
||||
}
|
||||
|
||||
public InputEvent getLastInputEvent() {
|
||||
return _lastInputEvent;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,17 +6,17 @@ import android.graphics.drawable.ColorDrawable;
|
|||
import android.os.Bundle;
|
||||
|
||||
import com.unity3d.services.core.misc.ViewUtilities;
|
||||
import com.unity3d.services.core.webview.bridge.SharedInstances;
|
||||
|
||||
public class AdUnitTransparentActivity extends AdUnitActivity {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
ViewUtilities.setBackground(super._layout, new ColorDrawable(Color.TRANSPARENT));
|
||||
ViewUtilities.setBackground(super._controller._layout, new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createLayout() {
|
||||
super.createLayout();
|
||||
ViewUtilities.setBackground(_layout, new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
@Override
|
||||
protected AdUnitActivityController createController() {
|
||||
return new AdUnitTransparentActivityController(this, SharedInstances.INSTANCE.getWebViewEventSender(), new AdUnitViewHandlerFactory());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
|
||||
import com.unity3d.services.core.misc.ViewUtilities;
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender;
|
||||
|
||||
public class AdUnitTransparentActivityController extends AdUnitActivityController {
|
||||
public AdUnitTransparentActivityController(IAdUnitActivity activity, IEventSender eventSender, IAdUnitViewHandlerFactory adUnitViewHandlerFactory) {
|
||||
super(activity, eventSender, adUnitViewHandlerFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void createLayout() {
|
||||
super.createLayout();
|
||||
ViewUtilities.setBackground(_layout, new ColorDrawable(Color.TRANSPARENT));
|
||||
}
|
||||
}
|
|
@ -13,10 +13,10 @@ public class AdUnitViewHandlerFactory implements IAdUnitViewHandlerFactory {
|
|||
public IAdUnitViewHandler createViewHandler(String name) {
|
||||
if (WebViewApp.getCurrentApp() != null) {
|
||||
Configuration configuration = WebViewApp.getCurrentApp().getConfiguration();
|
||||
String[] list = configuration.getModuleConfigurationList();
|
||||
Class[] list = configuration.getModuleConfigurationList();
|
||||
|
||||
for (String moduleName : list) {
|
||||
IModuleConfiguration moduleConfig = configuration.getModuleConfiguration(moduleName);
|
||||
for (Class moduleClass : list) {
|
||||
IModuleConfiguration moduleConfig = configuration.getModuleConfiguration(moduleClass);
|
||||
if (moduleConfig instanceof IAdsModuleConfiguration) {
|
||||
Map<String, Class> adUnitViewHandlers = ((IAdsModuleConfiguration) moduleConfig).getAdUnitViewHandlers();
|
||||
if (adUnitViewHandlers != null && adUnitViewHandlers.containsKey(name)) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
package com.unity3d.services.ads.adunit;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.Window;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IAdUnitActivity {
|
||||
void finish();
|
||||
|
||||
void addContentView(View view, ViewGroup.LayoutParams params);
|
||||
|
||||
Intent getIntent();
|
||||
|
||||
boolean isFinishing();
|
||||
|
||||
void setRequestedOrientation(int orientation);
|
||||
|
||||
Window getWindow();
|
||||
|
||||
Context getContext();
|
||||
|
||||
void requestPermissions(String[] permissions, int requestCode);
|
||||
|
||||
String[] getViews();
|
||||
|
||||
int getRequestedOrientation();
|
||||
|
||||
void setViews(String[] viewList);
|
||||
|
||||
void setOrientation(int orientation);
|
||||
|
||||
boolean setKeepScreenOn(boolean screenOn);
|
||||
|
||||
boolean setSystemUiVisibility(int systemUiVisibility);
|
||||
|
||||
void setKeyEventList(ArrayList<Integer> keyEventList);
|
||||
|
||||
void setViewFrame(String view, int x, int y, int width, int height);
|
||||
|
||||
Map<String, Integer> getViewFrame(String view);
|
||||
|
||||
AdUnitRelativeLayout getLayout();
|
||||
|
||||
void setLayoutInDisplayCutoutMode(int displayCutoutMode);
|
||||
|
||||
Activity getActivity();
|
||||
}
|
|
@ -4,14 +4,14 @@ import android.os.Bundle;
|
|||
import android.view.View;
|
||||
|
||||
public interface IAdUnitViewHandler {
|
||||
boolean create(AdUnitActivity activity);
|
||||
boolean create(IAdUnitActivity activity);
|
||||
boolean destroy();
|
||||
View getView();
|
||||
|
||||
void onCreate(AdUnitActivity activity, Bundle savedInstanceState);
|
||||
void onStart(AdUnitActivity activity);
|
||||
void onStop(AdUnitActivity activity);
|
||||
void onResume(AdUnitActivity activity);
|
||||
void onPause(AdUnitActivity activity);
|
||||
void onDestroy(AdUnitActivity activity);
|
||||
void onCreate(IAdUnitActivity activity, Bundle savedInstanceState);
|
||||
void onStart(IAdUnitActivity activity);
|
||||
void onStop(IAdUnitActivity activity);
|
||||
void onResume(IAdUnitActivity activity);
|
||||
void onPause(IAdUnitActivity activity);
|
||||
void onDestroy(IAdUnitActivity activity);
|
||||
}
|
||||
|
|
|
@ -13,14 +13,14 @@ public class VideoPlayerHandler implements IAdUnitViewHandler {
|
|||
private RelativeLayout _videoContainer;
|
||||
private VideoPlayerView _videoView;
|
||||
|
||||
public boolean create(AdUnitActivity activity) {
|
||||
public boolean create(IAdUnitActivity activity) {
|
||||
DeviceLog.entered();
|
||||
if (_videoContainer == null) {
|
||||
_videoContainer = new RelativeLayout(activity);
|
||||
_videoContainer = new RelativeLayout(activity.getContext());
|
||||
}
|
||||
|
||||
if (_videoView == null) {
|
||||
_videoView = new VideoPlayerView(activity);
|
||||
_videoView = new VideoPlayerView(activity.getContext());
|
||||
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
|
||||
params.addRule(RelativeLayout.CENTER_IN_PARENT);
|
||||
_videoView.setLayoutParams(params);
|
||||
|
@ -57,23 +57,23 @@ public class VideoPlayerHandler implements IAdUnitViewHandler {
|
|||
return _videoContainer;
|
||||
}
|
||||
|
||||
public void onCreate(AdUnitActivity activity, Bundle savedInstanceState) {
|
||||
public void onCreate(IAdUnitActivity activity, Bundle savedInstanceState) {
|
||||
create(activity);
|
||||
}
|
||||
|
||||
public void onStart(AdUnitActivity activity) {
|
||||
public void onStart(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onStop(AdUnitActivity activity) {
|
||||
public void onStop(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onResume(AdUnitActivity activity) {
|
||||
public void onResume(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onPause(AdUnitActivity activity) {
|
||||
public void onPause(IAdUnitActivity activity) {
|
||||
destroy();
|
||||
}
|
||||
|
||||
public void onDestroy(AdUnitActivity activity) {
|
||||
public void onDestroy(IAdUnitActivity activity) {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,10 +13,10 @@ public class WebPlayerHandler implements IAdUnitViewHandler {
|
|||
|
||||
private static String webPlayerViewId = "webplayer";
|
||||
|
||||
public boolean create(AdUnitActivity activity) {
|
||||
public boolean create(IAdUnitActivity activity) {
|
||||
if (_webPlayerView == null) {
|
||||
WebPlayerSettingsCache webPlayerSettingsCache = WebPlayerSettingsCache.getInstance();
|
||||
_webPlayerView = new WebPlayerView(activity, webPlayerViewId, webPlayerSettingsCache.getWebSettings(webPlayerViewId), webPlayerSettingsCache.getWebPlayerSettings(webPlayerViewId));
|
||||
_webPlayerView = new WebPlayerView(activity.getContext(), webPlayerViewId, webPlayerSettingsCache.getWebSettings(webPlayerViewId), webPlayerSettingsCache.getWebPlayerSettings(webPlayerViewId));
|
||||
_webPlayerView.setEventSettings(webPlayerSettingsCache.getWebPlayerEventSettings(webPlayerViewId));
|
||||
WebPlayerViewCache.getInstance().addWebPlayer(webPlayerViewId, _webPlayerView);
|
||||
}
|
||||
|
@ -40,23 +40,23 @@ public class WebPlayerHandler implements IAdUnitViewHandler {
|
|||
return _webPlayerView;
|
||||
}
|
||||
|
||||
public void onCreate(AdUnitActivity activity, Bundle savedInstanceState) {
|
||||
public void onCreate(IAdUnitActivity activity, Bundle savedInstanceState) {
|
||||
this.create(activity);
|
||||
}
|
||||
|
||||
public void onStart(AdUnitActivity activity) {
|
||||
public void onStart(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onStop(AdUnitActivity activity) {
|
||||
public void onStop(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onResume(AdUnitActivity activity) {
|
||||
public void onResume(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onPause(AdUnitActivity activity) {
|
||||
public void onPause(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onDestroy(AdUnitActivity activity) {
|
||||
public void onDestroy(IAdUnitActivity activity) {
|
||||
if (activity.isFinishing()) {
|
||||
destroy();
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@ import com.unity3d.services.core.misc.ViewUtilities;
|
|||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
|
||||
public class WebViewHandler implements IAdUnitViewHandler {
|
||||
public boolean create(AdUnitActivity activity) {
|
||||
public boolean create(IAdUnitActivity activity) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -26,22 +26,22 @@ public class WebViewHandler implements IAdUnitViewHandler {
|
|||
return null;
|
||||
}
|
||||
|
||||
public void onCreate(AdUnitActivity activity, Bundle savedInstanceState) {
|
||||
public void onCreate(IAdUnitActivity activity, Bundle savedInstanceState) {
|
||||
}
|
||||
|
||||
public void onStart(AdUnitActivity activity) {
|
||||
public void onStart(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onStop(AdUnitActivity activity) {
|
||||
public void onStop(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onResume(AdUnitActivity activity) {
|
||||
public void onResume(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onPause(AdUnitActivity activity) {
|
||||
public void onPause(IAdUnitActivity activity) {
|
||||
}
|
||||
|
||||
public void onDestroy(AdUnitActivity activity) {
|
||||
public void onDestroy(IAdUnitActivity activity) {
|
||||
destroy();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import com.unity3d.services.ads.adunit.AdUnitMotionEvent;
|
|||
import com.unity3d.services.ads.adunit.AdUnitSoftwareActivity;
|
||||
import com.unity3d.services.ads.adunit.AdUnitTransparentActivity;
|
||||
import com.unity3d.services.ads.adunit.AdUnitTransparentSoftwareActivity;
|
||||
import com.unity3d.services.ads.adunit.IAdUnitActivity;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
|
@ -30,17 +31,17 @@ import java.util.Iterator;
|
|||
import java.util.Map;
|
||||
|
||||
public class AdUnit {
|
||||
private static AdUnitActivity _adUnitActivity;
|
||||
private static IAdUnitActivity _adUnitActivity;
|
||||
private static int _currentActivityId = -1;
|
||||
|
||||
private AdUnit () {
|
||||
}
|
||||
|
||||
public static void setAdUnitActivity (AdUnitActivity activity) {
|
||||
public static void setAdUnitActivity (IAdUnitActivity activity) {
|
||||
_adUnitActivity = activity;
|
||||
}
|
||||
|
||||
public static AdUnitActivity getAdUnitActivity () {
|
||||
public static IAdUnitActivity getAdUnitActivity () {
|
||||
return _adUnitActivity;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import android.view.InputEvent;
|
||||
|
||||
import com.unity3d.services.ads.measurements.MeasurementsErrors;
|
||||
import com.unity3d.services.ads.measurements.MeasurementsService;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
public class Measurements {
|
||||
private static final MeasurementsService measurementsService = Utilities.getService(MeasurementsService.class);
|
||||
|
||||
@WebViewExposed
|
||||
public static void checkAvailability(WebViewCallback callback) {
|
||||
measurementsService.checkAvailability();
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void registerView(final String url, WebViewCallback callback) {
|
||||
measurementsService.registerView(url);
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void registerClick(final String url, WebViewCallback callback) {
|
||||
if (AdUnit.getAdUnitActivity() == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_AD_UNIT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (AdUnit.getAdUnitActivity().getLayout() == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_LAYOUT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
InputEvent lastInputEvent = AdUnit.getAdUnitActivity().getLayout().getLastInputEvent();
|
||||
if (lastInputEvent == null) {
|
||||
callback.error(MeasurementsErrors.ERROR_LAST_INPUT_EVENT_NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
measurementsService.registerClick(url, lastInputEvent);
|
||||
callback.invoke();
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.unity3d.services.ads.api;
|
|||
|
||||
import com.unity3d.services.ads.token.TokenError;
|
||||
import com.unity3d.services.ads.token.TokenStorage;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
|
@ -9,10 +10,12 @@ import org.json.JSONArray;
|
|||
import org.json.JSONException;
|
||||
|
||||
public class Token {
|
||||
private static final TokenStorage tokenStorage = Utilities.getService(TokenStorage.class);
|
||||
|
||||
@WebViewExposed
|
||||
public static void createTokens(JSONArray tokens, WebViewCallback callback) {
|
||||
try {
|
||||
TokenStorage.getInstance().createTokens(tokens);
|
||||
tokenStorage.createTokens(tokens);
|
||||
} catch (JSONException e) {
|
||||
callback.error(TokenError.JSON_EXCEPTION, e.getMessage());
|
||||
return;
|
||||
|
@ -24,7 +27,7 @@ public class Token {
|
|||
@WebViewExposed
|
||||
public static void appendTokens(JSONArray tokens, WebViewCallback callback) {
|
||||
try {
|
||||
TokenStorage.getInstance().appendTokens(tokens);
|
||||
tokenStorage.appendTokens(tokens);
|
||||
} catch (JSONException e) {
|
||||
callback.error(TokenError.JSON_EXCEPTION, e.getMessage());
|
||||
return;
|
||||
|
@ -35,21 +38,14 @@ public class Token {
|
|||
|
||||
@WebViewExposed
|
||||
public static void deleteTokens(WebViewCallback callback) {
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void setPeekMode(Boolean mode, WebViewCallback callback) {
|
||||
TokenStorage.getInstance().setPeekMode(mode);
|
||||
tokenStorage.deleteTokens();
|
||||
|
||||
callback.invoke();
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getNativeGeneratedToken(WebViewCallback callback) {
|
||||
TokenStorage.getInstance().getNativeGeneratedToken();
|
||||
tokenStorage.getNativeGeneratedToken();
|
||||
|
||||
callback.invoke();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.services.ads.api;
|
||||
|
||||
import com.unity3d.services.ads.topics.TopicsService;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewCallback;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewExposed;
|
||||
|
||||
public class Topics {
|
||||
private static final TopicsService topicsService = Utilities.getService(TopicsService.class);
|
||||
|
||||
@WebViewExposed
|
||||
public static void checkAvailability(WebViewCallback callback) {
|
||||
callback.invoke(topicsService.checkAvailability());
|
||||
}
|
||||
|
||||
@WebViewExposed
|
||||
public static void getTopics(String adsSdkName, Boolean shouldRecordObservation, WebViewCallback callback) {
|
||||
topicsService.getTopics(adsSdkName, shouldRecordObservation);
|
||||
callback.invoke();
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import com.unity3d.services.ads.token.TokenStorage;
|
|||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ErrorState;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.MalformedURLException;
|
||||
|
@ -18,6 +19,8 @@ import java.util.Map;
|
|||
|
||||
public class AdsModuleConfiguration implements IAdsModuleConfiguration {
|
||||
private InetAddress _address;
|
||||
private final TokenStorage tokenStorage = Utilities.getService(TokenStorage.class);
|
||||
private final AsyncTokenStorage asyncTokenStorage = Utilities.getService(AsyncTokenStorage.class);
|
||||
|
||||
public Class[] getWebAppApiClassList() {
|
||||
Class[] list = {
|
||||
|
@ -27,7 +30,9 @@ public class AdsModuleConfiguration implements IAdsModuleConfiguration {
|
|||
com.unity3d.services.ads.api.Load.class,
|
||||
com.unity3d.services.ads.api.Show.class,
|
||||
com.unity3d.services.ads.api.Token.class,
|
||||
com.unity3d.services.ads.api.GMAScar.class
|
||||
com.unity3d.services.ads.api.GMAScar.class,
|
||||
com.unity3d.services.ads.api.Measurements.class,
|
||||
com.unity3d.services.ads.api.Topics.class,
|
||||
};
|
||||
|
||||
return list;
|
||||
|
@ -36,59 +41,21 @@ public class AdsModuleConfiguration implements IAdsModuleConfiguration {
|
|||
public boolean resetState(Configuration configuration) {
|
||||
AdUnitOpen.setConfiguration(configuration);
|
||||
UnityAdsImplementation.setConfiguration(configuration);
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
AsyncTokenStorage.getInstance().setConfiguration(configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean initModuleState(Configuration configuration) {
|
||||
DeviceLog.debug("Unity Ads init: checking for ad blockers");
|
||||
|
||||
final String configHost;
|
||||
try {
|
||||
configHost = new URL(configuration.getConfigUrl()).getHost();
|
||||
} catch(MalformedURLException e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final ConditionVariable cv = new ConditionVariable();
|
||||
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
_address = InetAddress.getByName(configHost);
|
||||
cv.open();
|
||||
} catch(Exception e) {
|
||||
DeviceLog.exception("Couldn't get address. Host: " + configHost, e);
|
||||
cv.open();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
|
||||
// This is checking if config url is in /etc/hosts or equivalent. No need for long wait.
|
||||
boolean success = cv.block(2000);
|
||||
if(success && _address != null && _address.isLoopbackAddress()) {
|
||||
DeviceLog.error("Unity Ads init: halting init because Unity Ads config resolves to loopback address (due to ad blocker?)");
|
||||
return false;
|
||||
}
|
||||
AdUnitOpen.setConfiguration(configuration);
|
||||
UnityAdsImplementation.setConfiguration(configuration);
|
||||
AsyncTokenStorage.getInstance().setConfiguration(configuration);
|
||||
|
||||
tokenStorage.deleteTokens();
|
||||
asyncTokenStorage.setConfiguration(configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean initErrorState(Configuration configuration, ErrorState state, String errorMessage) {
|
||||
TokenStorage.getInstance().setInitToken(null);
|
||||
TokenStorage.getInstance().deleteTokens();
|
||||
tokenStorage.setInitToken(null);
|
||||
tokenStorage.deleteTokens();
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean initCompleteState(Configuration configuration) {
|
||||
AdUnitOpen.setConfiguration(configuration);
|
||||
UnityAdsImplementation.setConfiguration(configuration);
|
||||
AsyncTokenStorage.getInstance().setConfiguration(configuration);
|
||||
asyncTokenStorage.setConfiguration(configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,13 +3,14 @@ package com.unity3d.services.ads.gmascar.adapters;
|
|||
import com.unity3d.scar.adapter.common.GMAAdsError;
|
||||
import com.unity3d.scar.adapter.common.IAdsErrorHandler;
|
||||
import com.unity3d.scar.adapter.common.IScarAdapter;
|
||||
import com.unity3d.scar.adapter.common.WebViewAdsError;
|
||||
import com.unity3d.services.ads.gmascar.finder.ScarAdapterVersion;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
|
||||
public class ScarAdapterFactory {
|
||||
|
||||
public IScarAdapter createScarAdapter(ScarAdapterVersion adapterVersion, IAdsErrorHandler adsErrorHandler) {
|
||||
public IScarAdapter createScarAdapter(ScarAdapterVersion adapterVersion, IAdsErrorHandler<WebViewAdsError> adsErrorHandler) {
|
||||
IScarAdapter scarAdapter = null;
|
||||
|
||||
switch (adapterVersion) {
|
||||
|
@ -32,7 +33,7 @@ public class ScarAdapterFactory {
|
|||
return scarAdapter;
|
||||
}
|
||||
|
||||
private void reportAdapterFailure(ScarAdapterVersion adapterVersion, IAdsErrorHandler adsErrorHandler) {
|
||||
private void reportAdapterFailure(ScarAdapterVersion adapterVersion, IAdsErrorHandler<WebViewAdsError> adsErrorHandler) {
|
||||
String errorMessage = String.format("SCAR version %s is not supported.", adapterVersion.name());
|
||||
adsErrorHandler.handleError(GMAAdsError.AdapterCreationError(errorMessage));
|
||||
DeviceLog.debug(errorMessage);
|
||||
|
|
|
@ -2,14 +2,24 @@ 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;
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender;
|
||||
import com.unity3d.services.core.webview.bridge.SharedInstances;
|
||||
|
||||
public class WebViewErrorHandler implements IAdsErrorHandler<WebViewAdsError> {
|
||||
|
||||
private final IEventSender _eventSender;
|
||||
|
||||
public WebViewErrorHandler() {
|
||||
this(SharedInstances.INSTANCE.getWebViewEventSender());
|
||||
}
|
||||
|
||||
public WebViewErrorHandler(IEventSender eventSender) {
|
||||
_eventSender = eventSender;
|
||||
}
|
||||
@Override
|
||||
public void handleError(WebViewAdsError webViewAdsError) {
|
||||
WebViewEventCategory category = WebViewEventCategory.valueOf(webViewAdsError.getDomain());
|
||||
WebViewApp.getCurrentApp().sendEvent(category, webViewAdsError.getErrorCategory(), webViewAdsError.getErrorArguments());
|
||||
_eventSender.sendEvent(category, webViewAdsError.getErrorCategory(), webViewAdsError.getErrorArguments());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package com.unity3d.services.ads.gmascar.managers;
|
||||
|
||||
import static com.unity3d.services.ads.gmascar.utils.ScarConstants.TOKEN_WITH_SCAR_FORMAT;
|
||||
import static com.unity3d.services.core.misc.Utilities.wrapCustomerListener;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsTokenListener;
|
||||
import com.unity3d.services.ads.gmascar.GMA;
|
||||
|
@ -8,7 +9,8 @@ import com.unity3d.services.ads.gmascar.listeners.IBiddingSignalsListener;
|
|||
import com.unity3d.services.ads.gmascar.models.BiddingSignals;
|
||||
import com.unity3d.services.ads.gmascar.utils.ScarRequestHandler;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.ScarMetric;
|
||||
|
||||
|
@ -58,7 +60,7 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
@Override
|
||||
public final void onUnityAdsTokenReady(String token) {
|
||||
if (unityAdsTokenListener != null) {
|
||||
unityAdsTokenListener.onUnityAdsTokenReady(token);
|
||||
wrapCustomerListener(() -> unityAdsTokenListener.onUnityAdsTokenReady(token));
|
||||
}
|
||||
|
||||
if (token != null && !token.isEmpty()) {
|
||||
|
@ -142,7 +144,7 @@ public abstract class BiddingBaseManager implements IBiddingManager {
|
|||
}).start();
|
||||
}
|
||||
|
||||
public ISDKMetrics getMetricSender() {
|
||||
return SDKMetrics.getInstance();
|
||||
public SDKMetricsSender getMetricSender() {
|
||||
return Utilities.getService(SDKMetricsSender.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,16 +1,26 @@
|
|||
package com.unity3d.services.ads.gmascar.utils;
|
||||
|
||||
import com.unity3d.scar.adapter.common.GMAEvent;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender;
|
||||
import com.unity3d.services.core.webview.bridge.SharedInstances;
|
||||
|
||||
public class GMAEventSender {
|
||||
private final IEventSender _eventSender;
|
||||
|
||||
public GMAEventSender() {
|
||||
this(SharedInstances.INSTANCE.getWebViewEventSender());
|
||||
}
|
||||
|
||||
public GMAEventSender(IEventSender eventSender) {
|
||||
_eventSender = eventSender;
|
||||
}
|
||||
|
||||
public void send(GMAEvent event, Object... params) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.GMA, event, params);
|
||||
_eventSender.sendEvent(WebViewEventCategory.GMA, event, params);
|
||||
}
|
||||
|
||||
public void sendVersion(String version) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.INIT_GMA, GMAEvent.VERSION, version);
|
||||
_eventSender.sendEvent(WebViewEventCategory.INIT_GMA, GMAEvent.VERSION, version);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,35 +5,41 @@ import static com.unity3d.services.ads.gmascar.utils.ScarConstants.TOKEN_ID_KEY;
|
|||
|
||||
import com.unity3d.services.ads.gmascar.models.BiddingSignals;
|
||||
import com.unity3d.services.core.device.Device;
|
||||
import com.unity3d.services.core.request.WebRequest;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.network.core.HttpClient;
|
||||
import com.unity3d.services.core.network.model.HttpRequest;
|
||||
|
||||
import com.unity3d.services.core.network.model.RequestType;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ScarRequestHandler {
|
||||
private final HttpClient httpClient = Utilities.getService(HttpClient.class);
|
||||
|
||||
public ScarRequestHandler() {};
|
||||
public ScarRequestHandler() {
|
||||
}
|
||||
|
||||
public void makeUploadRequest(String tokenIdentifier, BiddingSignals signals, String url) throws Exception {
|
||||
Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("Content-Type",
|
||||
Collections.singletonList("application/json"));
|
||||
Map<String, List<String>> headers = new HashMap<>();
|
||||
headers.put("Content-Type", Collections.singletonList("application/json"));
|
||||
|
||||
final WebRequest request = new WebRequest(
|
||||
url,
|
||||
"POST",
|
||||
headers);
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put(IDFI_KEY, Device.getIdfi());
|
||||
body.put(TOKEN_ID_KEY, tokenIdentifier);
|
||||
body.putAll(signals.getMap());
|
||||
|
||||
Map<String, String> body = new HashMap<>();
|
||||
body.put(IDFI_KEY, Device.getIdfi());
|
||||
body.put(TOKEN_ID_KEY, tokenIdentifier);
|
||||
body.putAll(signals.getMap());
|
||||
request.setBody(new JSONObject(body).toString());
|
||||
|
||||
request.makeRequest();
|
||||
HttpRequest request = new HttpRequest(
|
||||
url,
|
||||
"",
|
||||
RequestType.POST,
|
||||
new JSONObject(body).toString().getBytes(StandardCharsets.UTF_8),
|
||||
headers
|
||||
);
|
||||
httpClient.executeBlocking(request);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
enum class MeasurementsErrors {
|
||||
ERROR_AD_SERVICES_DISABLED,
|
||||
ERROR_EXTENSION_BELOW_4,
|
||||
ERROR_API_BELOW_33,
|
||||
ERROR_MANAGER_NULL,
|
||||
ERROR_EXCEPTION,
|
||||
ERROR_AD_UNIT_NULL,
|
||||
ERROR_LAYOUT_NULL,
|
||||
ERROR_LAST_INPUT_EVENT_NULL,
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
enum class MeasurementsEvents {
|
||||
NOT_AVAILABLE,
|
||||
AVAILABLE,
|
||||
VIEW_SUCCESSFUL,
|
||||
VIEW_ERROR,
|
||||
CLICK_SUCCESSFUL,
|
||||
CLICK_ERROR,
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsReceiver(
|
||||
private val eventSender: IEventSender,
|
||||
private val successEvent: MeasurementsEvents,
|
||||
private val errorEvent: MeasurementsEvents,
|
||||
): OutcomeReceiver<Any, Exception> {
|
||||
override fun onResult(p0: Any) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, successEvent)
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, errorEvent, error.toString())
|
||||
}
|
||||
}
|
|
@ -0,0 +1,76 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.adservices.AdServicesState
|
||||
import android.adservices.measurement.MeasurementManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.OutcomeReceiver
|
||||
import android.os.ext.SdkExtensions
|
||||
import android.view.InputEvent
|
||||
import com.unity3d.services.core.device.Device
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import kotlinx.coroutines.asExecutor
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsService(context: Context, private val dispatchers: ISDKDispatchers, private val eventSender: IEventSender) {
|
||||
private val measurementManager: MeasurementManager? = getMeasurementManager(context)
|
||||
|
||||
fun checkAvailability() {
|
||||
if (Device.getApiLevel() < 33) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_API_BELOW_33)
|
||||
return
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_EXTENSION_BELOW_4)
|
||||
return
|
||||
}
|
||||
|
||||
if (measurementManager == null) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_MANAGER_NULL)
|
||||
return
|
||||
}
|
||||
|
||||
if (!AdServicesState.isAdServicesStateEnabled()) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_AD_SERVICES_DISABLED)
|
||||
return
|
||||
}
|
||||
|
||||
measurementManager.getMeasurementApiStatus(dispatchers.default.asExecutor(), MeasurementsStatusReceiver(eventSender))
|
||||
}
|
||||
|
||||
fun registerView(url: String) {
|
||||
measurementManager?.registerSource(
|
||||
Uri.parse(url),
|
||||
null,
|
||||
dispatchers.default.asExecutor(),
|
||||
MeasurementsReceiver(eventSender, MeasurementsEvents.VIEW_SUCCESSFUL, MeasurementsEvents.VIEW_ERROR)
|
||||
)
|
||||
}
|
||||
|
||||
fun registerClick(url: String, inputEvent: InputEvent) {
|
||||
measurementManager?.registerSource(
|
||||
Uri.parse(url),
|
||||
inputEvent,
|
||||
dispatchers.default.asExecutor(),
|
||||
MeasurementsReceiver(eventSender, MeasurementsEvents.CLICK_SUCCESSFUL, MeasurementsEvents.CLICK_ERROR)
|
||||
)
|
||||
}
|
||||
|
||||
private fun getMeasurementManager(context: Context): MeasurementManager? {
|
||||
// accessing MeasurementManager without API level and extension version checks can crash old Android devices
|
||||
// also accessing SdkExtensions below API level 30 causes exception so check API level first
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return null
|
||||
}
|
||||
|
||||
return context.getSystemService(MeasurementManager::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package com.unity3d.services.ads.measurements
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class MeasurementsStatusReceiver(private val eventSender: IEventSender) : OutcomeReceiver<Int, Exception> {
|
||||
override fun onResult(status: Int) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.AVAILABLE, status)
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.MEASUREMENTS, MeasurementsEvents.NOT_AVAILABLE, MeasurementsErrors.ERROR_EXCEPTION, error.toString())
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
package com.unity3d.services.ads.operation;
|
||||
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewSharedObject;
|
||||
import com.unity3d.services.core.webview.bridge.WebViewBridgeSharedObjectStore;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.WebViewBridgeInvocationSingleThreadedExecutor;
|
||||
|
@ -8,16 +8,16 @@ import com.unity3d.services.core.webview.bridge.invocation.WebViewBridgeInvocati
|
|||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
public abstract class AdModule<T extends IWebViewSharedObject, T2> extends WebViewBridgeSharedObjectStore<T> implements IAdModule<T, T2> {
|
||||
protected ISDKMetrics _sdkMetrics;
|
||||
protected SDKMetricsSender _sdkMetrics;
|
||||
protected ExecutorService _executorService;
|
||||
|
||||
protected AdModule(ISDKMetrics sdkMetrics) {
|
||||
protected AdModule(SDKMetricsSender sdkMetrics) {
|
||||
super();
|
||||
_sdkMetrics = sdkMetrics;
|
||||
_executorService = WebViewBridgeInvocationSingleThreadedExecutor.getInstance().getExecutorService();
|
||||
}
|
||||
|
||||
public ISDKMetrics getMetricSender() {
|
||||
public SDKMetricsSender getMetricSender() {
|
||||
return _sdkMetrics;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package com.unity3d.services.ads.operation;
|
||||
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeSharedObjectStore;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewSharedObject;
|
||||
|
||||
public interface IAdModule<T extends IWebViewSharedObject, T2> extends IWebViewBridgeSharedObjectStore<T> {
|
||||
void executeAdOperation(final IWebViewBridgeInvoker webViewBridgeInvoker, final T2 state);
|
||||
ISDKMetrics getMetricSender();
|
||||
SDKMetricsSender getMetricSender();
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import com.unity3d.services.core.device.Device;
|
|||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
import com.unity3d.services.core.webview.bridge.invocation.IWebViewBridgeInvocationCallback;
|
||||
|
@ -25,7 +25,7 @@ public abstract class BaseLoadModule extends AdModule<ILoadOperation, LoadOperat
|
|||
static final String errorMsgPlacementIdNull = "[UnityAds] Placement ID cannot be null";
|
||||
static final String errorMsgFailedToCreateLoadRequest = "[UnityAds] Failed to create load request";
|
||||
|
||||
public BaseLoadModule(ISDKMetrics sdkMetrics) {
|
||||
public BaseLoadModule(SDKMetricsSender sdkMetrics) {
|
||||
super(sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,8 @@ import com.unity3d.services.banners.UnityBannerSize;
|
|||
import com.unity3d.services.banners.bridge.BannerBridge;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.InitializationNotificationCenter;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
@ -17,7 +18,7 @@ public class LoadBannerModule extends BaseLoadModule {
|
|||
|
||||
public static ILoadModule getInstance() {
|
||||
if (_instance == null) {
|
||||
LoadBannerModule loadModule = new LoadBannerModule(SDKMetrics.getInstance());
|
||||
LoadBannerModule loadModule = new LoadBannerModule(Utilities.getService(SDKMetricsSender.class));
|
||||
LoadModuleDecoratorInitializationBuffer bufferedLoadModule = new LoadModuleDecoratorInitializationBuffer(loadModule, InitializationNotificationCenter.getInstance());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ConfigurationReader());
|
||||
_instance = timedLoadModule;
|
||||
|
@ -25,7 +26,7 @@ public class LoadBannerModule extends BaseLoadModule {
|
|||
return _instance;
|
||||
}
|
||||
|
||||
public LoadBannerModule(ISDKMetrics sdkMetrics) {
|
||||
public LoadBannerModule(SDKMetricsSender sdkMetrics) {
|
||||
super(sdkMetrics);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,8 @@ package com.unity3d.services.ads.operation.load;
|
|||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.InitializationNotificationCenter;
|
||||
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
|
||||
import org.json.JSONException;
|
||||
|
@ -15,7 +16,7 @@ public class LoadModule extends BaseLoadModule {
|
|||
|
||||
public static ILoadModule getInstance() {
|
||||
if (_instance == null) {
|
||||
LoadModule loadModule = new LoadModule(SDKMetrics.getInstance());
|
||||
LoadModule loadModule = new LoadModule(Utilities.getService(SDKMetricsSender.class));
|
||||
LoadModuleDecoratorInitializationBuffer bufferedLoadModule = new LoadModuleDecoratorInitializationBuffer(loadModule, InitializationNotificationCenter.getInstance());
|
||||
LoadModuleDecoratorTimeout timedLoadModule = new LoadModuleDecoratorTimeout(bufferedLoadModule, new ConfigurationReader());
|
||||
_instance = timedLoadModule;
|
||||
|
@ -23,12 +24,12 @@ public class LoadModule extends BaseLoadModule {
|
|||
return _instance;
|
||||
}
|
||||
|
||||
public LoadModule(ISDKMetrics sdkMetrics) {
|
||||
public LoadModule(SDKMetricsSender sdkMetrics) {
|
||||
super(sdkMetrics);
|
||||
}
|
||||
|
||||
@Override
|
||||
void addOptionalParameters(LoadOperationState state, JSONObject parameters) throws JSONException {
|
||||
void addOptionalParameters(LoadOperationState state, JSONObject parameters) {
|
||||
// none needed
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.load;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
public class LoadModuleDecorator implements ILoadModule {
|
||||
|
@ -17,7 +17,7 @@ public class LoadModuleDecorator implements ILoadModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ISDKMetrics getMetricSender() {
|
||||
public SDKMetricsSender getMetricSender() {
|
||||
return _loadModule.getMetricSender();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.load;
|
||||
|
||||
import static com.unity3d.services.core.misc.Utilities.wrapCustomerListener;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsLoadListener;
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.ads.UnityAdsLoadOptions;
|
||||
|
@ -18,13 +20,15 @@ public class LoadOperationState extends OperationState {
|
|||
|
||||
public void onUnityAdsFailedToLoad(UnityAds.UnityAdsLoadError error, String message) {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsFailedToLoad(this.placementId, error, message);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsFailedToLoad(this.placementId, error, message));
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnityAdsAdLoaded() {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsAdLoaded(this.placementId);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsAdLoaded(this.placementId));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.show;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.graphics.Point;
|
||||
import android.os.Build;
|
||||
import android.text.TextUtils;
|
||||
|
@ -14,7 +16,7 @@ import com.unity3d.services.core.misc.Utilities;
|
|||
import com.unity3d.services.core.properties.ClientProperties;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationError;
|
||||
import com.unity3d.services.core.request.metrics.AdOperationMetric;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.webview.bridge.CallbackStatus;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
@ -32,12 +34,12 @@ public class ShowModule extends AdModule<IShowOperation, ShowOperationState> imp
|
|||
|
||||
public static IShowModule getInstance() {
|
||||
if (instance == null) {
|
||||
instance = new ShowModuleDecoratorTimeout(new ShowModule(SDKMetrics.getInstance()), new ConfigurationReader());
|
||||
instance = new ShowModuleDecoratorTimeout(new ShowModule(Utilities.getService(SDKMetricsSender.class)), new ConfigurationReader());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
public ShowModule(ISDKMetrics sdkMetrics) {
|
||||
public ShowModule(SDKMetricsSender sdkMetrics) {
|
||||
super(sdkMetrics);
|
||||
}
|
||||
|
||||
|
@ -67,16 +69,17 @@ public class ShowModule extends AdModule<IShowOperation, ShowOperationState> imp
|
|||
remove(state.id);
|
||||
}
|
||||
}));
|
||||
Activity activity = state.activity.get();
|
||||
|
||||
ClientProperties.setActivity(state.activity);
|
||||
ClientProperties.setActivity(activity);
|
||||
|
||||
Display defaultDisplay = ((WindowManager)state.activity.getSystemService(state.activity.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
Display defaultDisplay = ((WindowManager)activity.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
JSONObject parameters = new JSONObject();
|
||||
JSONObject options = new JSONObject();
|
||||
JSONObject display = new JSONObject();
|
||||
|
||||
try {
|
||||
display.put("requestedOrientation", state.activity.getRequestedOrientation());
|
||||
display.put("requestedOrientation", activity.getRequestedOrientation());
|
||||
display.put("rotation", defaultDisplay.getRotation());
|
||||
if (Build.VERSION.SDK_INT >= 13) {
|
||||
Point displaySize = new Point();
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.show;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.webview.bridge.IWebViewBridgeInvoker;
|
||||
|
||||
public class ShowModuleDecorator implements IShowModule {
|
||||
|
@ -17,7 +17,7 @@ public class ShowModuleDecorator implements IShowModule {
|
|||
}
|
||||
|
||||
@Override
|
||||
public ISDKMetrics getMetricSender() {
|
||||
public SDKMetricsSender getMetricSender() {
|
||||
return _showModule.getMetricSender();
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.unity3d.services.ads.operation.show;
|
||||
|
||||
import static com.unity3d.services.core.misc.Utilities.wrapCustomerListener;
|
||||
|
||||
import android.app.Activity;
|
||||
|
||||
import com.unity3d.ads.IUnityAdsShowListener;
|
||||
|
@ -8,39 +10,47 @@ import com.unity3d.ads.UnityAdsShowOptions;
|
|||
import com.unity3d.services.ads.operation.OperationState;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
public class ShowOperationState extends OperationState {
|
||||
public Activity activity;
|
||||
public WeakReference<Activity> activity;
|
||||
public IUnityAdsShowListener listener;
|
||||
public UnityAdsShowOptions showOptions;
|
||||
|
||||
public ShowOperationState(String placementId, IUnityAdsShowListener listener, Activity activity, UnityAdsShowOptions showOptions, Configuration configuration) {
|
||||
super(placementId, configuration);
|
||||
this.listener = listener;
|
||||
this.activity = activity;
|
||||
this.activity = new WeakReference<>(activity);
|
||||
this.showOptions = showOptions;
|
||||
}
|
||||
|
||||
public void onUnityAdsShowFailure(UnityAds.UnityAdsShowError error, String message) {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsShowFailure(this.placementId, error, message);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsShowFailure(this.placementId, error, message));
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnityAdsShowClick() {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsShowClick(this.placementId);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsShowClick(this.placementId));
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnityAdsShowStart(String placementId) {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsShowStart(placementId);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsShowStart(placementId));
|
||||
}
|
||||
}
|
||||
|
||||
public void onUnityAdsShowComplete(UnityAds.UnityAdsShowCompletionState state) {
|
||||
if (listener != null) {
|
||||
listener.onUnityAdsShowComplete(this.placementId, state);
|
||||
wrapCustomerListener(() ->
|
||||
listener.onUnityAdsShowComplete(this.placementId, state));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -1,257 +0,0 @@
|
|||
package com.unity3d.services.ads.token;
|
||||
|
||||
import static com.unity3d.services.core.device.TokenType.TOKEN_NATIVE;
|
||||
import static com.unity3d.services.core.device.TokenType.TOKEN_REMOTE;
|
||||
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.GMA;
|
||||
import com.unity3d.services.ads.gmascar.managers.IBiddingManager;
|
||||
import com.unity3d.services.ads.gmascar.utils.ScarConstants;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.TokenType;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderBuilderWithExtras;
|
||||
import com.unity3d.services.core.device.reader.GameSessionIdReader;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.InitializationStatusReader;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.ISDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetrics;
|
||||
import com.unity3d.services.core.request.metrics.TSIMetric;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class AsyncTokenStorage {
|
||||
private final List<AsyncTokenStorage.TokenListenerState> _tokenListeners = new LinkedList<>();
|
||||
private final Handler _handler;
|
||||
private boolean _tokenAvailable = false;
|
||||
private boolean _configurationWasSet = false;
|
||||
private Configuration _configuration = new Configuration();
|
||||
private INativeTokenGenerator _nativeTokenGenerator;
|
||||
private final InitializationStatusReader _initStatusReader = new InitializationStatusReader();
|
||||
private final ISDKMetrics _sdkMetrics;
|
||||
private DeviceInfoReaderBuilderWithExtras _deviceInfoReaderBuilderWithExtras;
|
||||
private TokenStorage _tokenStorage;
|
||||
|
||||
private static AsyncTokenStorage _instance;
|
||||
|
||||
public static AsyncTokenStorage getInstance() {
|
||||
if (_instance == null) {
|
||||
_instance = new AsyncTokenStorage(
|
||||
null,
|
||||
new Handler(Looper.getMainLooper()),
|
||||
SDKMetrics.getInstance(),
|
||||
TokenStorage.getInstance());
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
class TokenListenerState
|
||||
{
|
||||
public IBiddingManager biddingManager;
|
||||
public Runnable runnable;
|
||||
public boolean invoked;
|
||||
public TokenType tokenType;
|
||||
}
|
||||
|
||||
public AsyncTokenStorage(INativeTokenGenerator nativeTokenGenerator, Handler handler, ISDKMetrics sdkMetrics, TokenStorage tokenStorage) {
|
||||
_handler = handler;
|
||||
_nativeTokenGenerator = nativeTokenGenerator;
|
||||
_sdkMetrics = sdkMetrics;
|
||||
_tokenStorage = tokenStorage;
|
||||
}
|
||||
|
||||
public synchronized void setConfiguration(Configuration configuration) {
|
||||
_configuration = configuration;
|
||||
_configurationWasSet = isValidConfig(_configuration);
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_nativeTokenGenerator == null) {
|
||||
_deviceInfoReaderBuilderWithExtras = new DeviceInfoReaderBuilderWithExtras(new ConfigurationReader(), PrivacyConfigStorage.getInstance(), GameSessionIdReader.getInstance());
|
||||
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
_nativeTokenGenerator = new NativeTokenGenerator(executorService, _deviceInfoReaderBuilderWithExtras);
|
||||
|
||||
if (configuration.getExperiments().shouldNativeTokenAwaitPrivacy()) {
|
||||
_nativeTokenGenerator = new NativeTokenGeneratorWithPrivacyAwait(executorService, _nativeTokenGenerator, configuration.getPrivacyRequestWaitTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<TokenListenerState> tempList = new ArrayList<>(_tokenListeners);
|
||||
for(TokenListenerState state: tempList) {
|
||||
handleTokenInvocation(state);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onTokenAvailable() {
|
||||
_tokenAvailable = true;
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifyListenersTokenReady();
|
||||
}
|
||||
|
||||
public synchronized void getToken(IBiddingManager biddingManager) {
|
||||
if (SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.INITIALIZED_FAILED) {
|
||||
biddingManager.onUnityAdsTokenReady(null);
|
||||
sendTokenMetrics(null, TOKEN_REMOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.NOT_INITIALIZED) {
|
||||
biddingManager.onUnityAdsTokenReady(null);
|
||||
sendTokenMetrics(null, TOKEN_REMOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
final AsyncTokenStorage.TokenListenerState state = addTimeoutHandler(biddingManager);
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleTokenInvocation(state);
|
||||
}
|
||||
|
||||
private synchronized AsyncTokenStorage.TokenListenerState addTimeoutHandler(IBiddingManager biddingManager) {
|
||||
final AsyncTokenStorage.TokenListenerState state = new AsyncTokenStorage.TokenListenerState();
|
||||
state.biddingManager = biddingManager;
|
||||
state.tokenType = TOKEN_REMOTE;
|
||||
state.runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyTokenReady(state, null);
|
||||
}
|
||||
};
|
||||
_tokenListeners.add(state);
|
||||
_handler.postDelayed(state.runnable, _configuration.getTokenTimeout());
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private synchronized void notifyListenersTokenReady() {
|
||||
while(!_tokenListeners.isEmpty()) {
|
||||
String token = _tokenStorage.getToken();
|
||||
|
||||
if (token == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
notifyTokenReady(_tokenListeners.get(0), token);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTokenInvocation(final AsyncTokenStorage.TokenListenerState state) {
|
||||
if (state.invoked) {
|
||||
return;
|
||||
}
|
||||
state.invoked = true;
|
||||
|
||||
if (!_tokenAvailable) {
|
||||
state.tokenType = TOKEN_NATIVE;
|
||||
|
||||
if (GMA.getInstance().hasSCARBiddingSupport() && _deviceInfoReaderBuilderWithExtras != null) {
|
||||
Map<String, String> extras = new HashMap<>();
|
||||
extras.put(ScarConstants.TOKEN_ID_KEY, state.biddingManager.getTokenIdentifier());
|
||||
_deviceInfoReaderBuilderWithExtras.setExtras(extras);
|
||||
}
|
||||
|
||||
_nativeTokenGenerator.generateToken(new INativeTokenGeneratorListener() {
|
||||
@Override
|
||||
public void onReady(final String token) {
|
||||
_handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyTokenReady(state, token);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.tokenType = TOKEN_REMOTE;
|
||||
String token = _tokenStorage.getToken();
|
||||
|
||||
if (token == null || token.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifyTokenReady(state, token);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void notifyTokenReady(AsyncTokenStorage.TokenListenerState state, String token) {
|
||||
if (_tokenListeners.remove(state)) {
|
||||
|
||||
// If SCAR token identifier exists and token is generated by the webView, then the
|
||||
// scar identifier is to be prepended to the token <ScarID>:<unityToken>. Otherwise
|
||||
// scarID will be included in the token map<String, String> payload.
|
||||
String formattedToken = state.tokenType == TOKEN_REMOTE
|
||||
? state.biddingManager.getFormattedToken(token)
|
||||
: token;
|
||||
|
||||
state.biddingManager.onUnityAdsTokenReady(formattedToken);
|
||||
|
||||
try {
|
||||
_handler.removeCallbacks(state.runnable);
|
||||
} catch (Exception ex) {
|
||||
DeviceLog.exception("Failed to remove callback from a handler", ex);
|
||||
}
|
||||
}
|
||||
sendTokenMetrics(token, state.tokenType);
|
||||
}
|
||||
|
||||
private void sendTokenMetrics(String token, TokenType type) {
|
||||
switch (type) {
|
||||
case TOKEN_NATIVE:
|
||||
sendNativeTokenMetrics(token);
|
||||
break;
|
||||
case TOKEN_REMOTE:
|
||||
sendRemoteTokenMetrics(token);
|
||||
break;
|
||||
default:
|
||||
DeviceLog.error("Unknown token type passed to sendTokenMetrics");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNativeTokenMetrics(String token) {
|
||||
if (_sdkMetrics == null) return;
|
||||
if (token == null) {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newNativeGeneratedTokenNull(getMetricTags()));
|
||||
} else {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newNativeGeneratedTokenAvailable(getMetricTags()));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRemoteTokenMetrics(String token) {
|
||||
if (_sdkMetrics == null) return;
|
||||
if (token == null || token.isEmpty()) {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newAsyncTokenNull(getMetricTags()));
|
||||
} else {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newAsyncTokenAvailable(getMetricTags()));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getMetricTags() {
|
||||
Map<String, String> tags = new HashMap<>();
|
||||
tags.put("state", _initStatusReader.getInitializationStateString(SdkProperties.getCurrentInitializationState()));
|
||||
return tags;
|
||||
}
|
||||
|
||||
private boolean isValidConfig(Configuration configuration) {
|
||||
return configuration != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package com.unity3d.services.ads.token
|
||||
|
||||
import com.unity3d.services.ads.gmascar.managers.IBiddingManager
|
||||
import com.unity3d.services.core.configuration.Configuration
|
||||
|
||||
interface AsyncTokenStorage {
|
||||
fun setConfiguration(configuration: Configuration?)
|
||||
fun onTokenAvailable()
|
||||
fun getToken(biddingManager: IBiddingManager?)
|
||||
}
|
|
@ -0,0 +1,242 @@
|
|||
package com.unity3d.services.ads.token;
|
||||
|
||||
import static com.unity3d.services.core.device.TokenType.TOKEN_NATIVE;
|
||||
import static com.unity3d.services.core.device.TokenType.TOKEN_REMOTE;
|
||||
|
||||
import android.os.Handler;
|
||||
|
||||
import com.unity3d.services.ads.gmascar.GMA;
|
||||
import com.unity3d.services.ads.gmascar.managers.IBiddingManager;
|
||||
import com.unity3d.services.ads.gmascar.utils.ScarConstants;
|
||||
import com.unity3d.services.core.configuration.Configuration;
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.TokenType;
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderBuilderWithExtras;
|
||||
import com.unity3d.services.core.device.reader.GameSessionIdReader;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
import com.unity3d.services.core.properties.InitializationStatusReader;
|
||||
import com.unity3d.services.core.properties.SdkProperties;
|
||||
import com.unity3d.services.core.request.metrics.SDKMetricsSender;
|
||||
import com.unity3d.services.core.request.metrics.TSIMetric;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class InMemoryAsyncTokenStorage implements AsyncTokenStorage {
|
||||
private final List<InMemoryAsyncTokenStorage.TokenListenerState> _tokenListeners = new LinkedList<>();
|
||||
private final Handler _handler;
|
||||
private boolean _tokenAvailable = false;
|
||||
private boolean _configurationWasSet = false;
|
||||
private Configuration _configuration = new Configuration();
|
||||
private INativeTokenGenerator _nativeTokenGenerator;
|
||||
private final InitializationStatusReader _initStatusReader = new InitializationStatusReader();
|
||||
private final SDKMetricsSender _sdkMetrics;
|
||||
private DeviceInfoReaderBuilderWithExtras _deviceInfoReaderBuilderWithExtras;
|
||||
private TokenStorage _tokenStorage;
|
||||
|
||||
class TokenListenerState
|
||||
{
|
||||
public IBiddingManager biddingManager;
|
||||
public Runnable runnable;
|
||||
public boolean invoked;
|
||||
public TokenType tokenType;
|
||||
}
|
||||
|
||||
public InMemoryAsyncTokenStorage(INativeTokenGenerator nativeTokenGenerator, Handler handler, SDKMetricsSender sdkMetrics, TokenStorage tokenStorage) {
|
||||
_handler = handler;
|
||||
_nativeTokenGenerator = nativeTokenGenerator;
|
||||
_sdkMetrics = sdkMetrics;
|
||||
_tokenStorage = tokenStorage;
|
||||
}
|
||||
|
||||
public synchronized void setConfiguration(Configuration configuration) {
|
||||
_configuration = configuration;
|
||||
_configurationWasSet = isValidConfig(_configuration);
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_nativeTokenGenerator == null) {
|
||||
_deviceInfoReaderBuilderWithExtras = new DeviceInfoReaderBuilderWithExtras(new ConfigurationReader(), PrivacyConfigStorage.getInstance(), GameSessionIdReader.getInstance());
|
||||
|
||||
ExecutorService executorService = Executors.newSingleThreadExecutor();
|
||||
_nativeTokenGenerator = new NativeTokenGenerator(executorService, _deviceInfoReaderBuilderWithExtras);
|
||||
|
||||
if (configuration.getExperiments().shouldNativeTokenAwaitPrivacy()) {
|
||||
_nativeTokenGenerator = new NativeTokenGeneratorWithPrivacyAwait(executorService, _nativeTokenGenerator, configuration.getPrivacyRequestWaitTimeout());
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<TokenListenerState> tempList = new ArrayList<>(_tokenListeners);
|
||||
for(TokenListenerState state: tempList) {
|
||||
handleTokenInvocation(state);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void onTokenAvailable() {
|
||||
_tokenAvailable = true;
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifyListenersTokenReady();
|
||||
}
|
||||
|
||||
public synchronized void getToken(IBiddingManager biddingManager) {
|
||||
if (SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.INITIALIZED_FAILED) {
|
||||
biddingManager.onUnityAdsTokenReady(null);
|
||||
sendTokenMetrics(null, TOKEN_REMOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
if (SdkProperties.getCurrentInitializationState() == SdkProperties.InitializationState.NOT_INITIALIZED) {
|
||||
biddingManager.onUnityAdsTokenReady(null);
|
||||
sendTokenMetrics(null, TOKEN_REMOTE);
|
||||
return;
|
||||
}
|
||||
|
||||
final InMemoryAsyncTokenStorage.TokenListenerState state = addTimeoutHandler(biddingManager);
|
||||
|
||||
if (!_configurationWasSet) {
|
||||
return;
|
||||
}
|
||||
|
||||
handleTokenInvocation(state);
|
||||
}
|
||||
|
||||
private synchronized InMemoryAsyncTokenStorage.TokenListenerState addTimeoutHandler(IBiddingManager biddingManager) {
|
||||
final InMemoryAsyncTokenStorage.TokenListenerState state = new InMemoryAsyncTokenStorage.TokenListenerState();
|
||||
state.biddingManager = biddingManager;
|
||||
state.tokenType = TOKEN_REMOTE;
|
||||
state.runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyTokenReady(state, null);
|
||||
}
|
||||
};
|
||||
_tokenListeners.add(state);
|
||||
_handler.postDelayed(state.runnable, _configuration.getTokenTimeout());
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
private synchronized void notifyListenersTokenReady() {
|
||||
while(!_tokenListeners.isEmpty()) {
|
||||
String token = _tokenStorage.getToken();
|
||||
|
||||
if (token == null) {
|
||||
break;
|
||||
}
|
||||
|
||||
notifyTokenReady(_tokenListeners.get(0), token);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleTokenInvocation(final InMemoryAsyncTokenStorage.TokenListenerState state) {
|
||||
if (state.invoked) {
|
||||
return;
|
||||
}
|
||||
state.invoked = true;
|
||||
|
||||
if (!_tokenAvailable) {
|
||||
state.tokenType = TOKEN_NATIVE;
|
||||
|
||||
if (GMA.getInstance().hasSCARBiddingSupport() && _deviceInfoReaderBuilderWithExtras != null) {
|
||||
Map<String, String> extras = new HashMap<>();
|
||||
extras.put(ScarConstants.TOKEN_ID_KEY, state.biddingManager.getTokenIdentifier());
|
||||
_deviceInfoReaderBuilderWithExtras.setExtras(extras);
|
||||
}
|
||||
|
||||
_nativeTokenGenerator.generateToken(new INativeTokenGeneratorListener() {
|
||||
@Override
|
||||
public void onReady(final String token) {
|
||||
_handler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
notifyTokenReady(state, token);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
state.tokenType = TOKEN_REMOTE;
|
||||
String token = _tokenStorage.getToken();
|
||||
|
||||
if (token == null || token.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
notifyTokenReady(state, token);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void notifyTokenReady(InMemoryAsyncTokenStorage.TokenListenerState state, String token) {
|
||||
if (_tokenListeners.remove(state)) {
|
||||
|
||||
// If SCAR token identifier exists and token is generated by the webView, then the
|
||||
// scar identifier is to be prepended to the token <ScarID>:<unityToken>. Otherwise
|
||||
// scarID will be included in the token map<String, String> payload.
|
||||
String formattedToken = state.tokenType == TOKEN_REMOTE
|
||||
? state.biddingManager.getFormattedToken(token)
|
||||
: token;
|
||||
|
||||
state.biddingManager.onUnityAdsTokenReady(formattedToken);
|
||||
|
||||
try {
|
||||
_handler.removeCallbacks(state.runnable);
|
||||
} catch (Exception ex) {
|
||||
DeviceLog.exception("Failed to remove callback from a handler", ex);
|
||||
}
|
||||
}
|
||||
sendTokenMetrics(token, state.tokenType);
|
||||
}
|
||||
|
||||
private void sendTokenMetrics(String token, TokenType type) {
|
||||
switch (type) {
|
||||
case TOKEN_NATIVE:
|
||||
sendNativeTokenMetrics(token);
|
||||
break;
|
||||
case TOKEN_REMOTE:
|
||||
sendRemoteTokenMetrics(token);
|
||||
break;
|
||||
default:
|
||||
DeviceLog.error("Unknown token type passed to sendTokenMetrics");
|
||||
}
|
||||
}
|
||||
|
||||
private void sendNativeTokenMetrics(String token) {
|
||||
if (_sdkMetrics == null) return;
|
||||
if (token == null) {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newNativeGeneratedTokenNull(getMetricTags()));
|
||||
} else {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newNativeGeneratedTokenAvailable(getMetricTags()));
|
||||
}
|
||||
}
|
||||
|
||||
private void sendRemoteTokenMetrics(String token) {
|
||||
if (_sdkMetrics == null) return;
|
||||
if (token == null || token.isEmpty()) {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newAsyncTokenNull(getMetricTags()));
|
||||
} else {
|
||||
_sdkMetrics.sendMetric(TSIMetric.newAsyncTokenAvailable(getMetricTags()));
|
||||
}
|
||||
}
|
||||
|
||||
private Map<String, String> getMetricTags() {
|
||||
Map<String, String> tags = new HashMap<>();
|
||||
tags.put("state", _initStatusReader.getInitializationStateString(SdkProperties.getCurrentInitializationState()));
|
||||
return tags;
|
||||
}
|
||||
|
||||
private boolean isValidConfig(Configuration configuration) {
|
||||
return configuration != null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
package com.unity3d.services.ads.token
|
||||
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader
|
||||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderBuilder
|
||||
import com.unity3d.services.core.device.reader.GameSessionIdReader
|
||||
import com.unity3d.services.core.di.IServiceComponent
|
||||
import com.unity3d.services.core.di.inject
|
||||
import com.unity3d.services.core.webview.WebViewApp
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.getAndUpdate
|
||||
import kotlinx.coroutines.flow.update
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
class InMemoryTokenStorage : TokenStorage, IServiceComponent {
|
||||
private val queue = ConcurrentLinkedQueue<String>()
|
||||
private val accessCounter = MutableStateFlow(-1)
|
||||
private val initToken = MutableStateFlow<String?>(null)
|
||||
private val executorService = Executors.newSingleThreadExecutor()
|
||||
private val asyncTokenStorage: AsyncTokenStorage by inject() // todo: remove this dependency when AsyncTokenStorage is rewrote to Kotlin (use flow instead of callback)
|
||||
|
||||
@Throws(JSONException::class)
|
||||
override fun createTokens(tokens: JSONArray) {
|
||||
deleteTokens()
|
||||
appendTokens(tokens)
|
||||
}
|
||||
|
||||
@Throws(JSONException::class)
|
||||
override fun appendTokens(tokens: JSONArray) {
|
||||
// -1 means deleteTokens was called before and queue should be considered as non initialized
|
||||
accessCounter.compareAndSet(-1, 0)
|
||||
|
||||
val tokenLength = tokens.length()
|
||||
for (i in 0 until tokenLength) {
|
||||
queue.add(tokens.getString(i))
|
||||
}
|
||||
|
||||
if (tokenLength > 0) {
|
||||
triggerTokenAvailable(false)
|
||||
asyncTokenStorage.onTokenAvailable()
|
||||
}
|
||||
}
|
||||
|
||||
override fun deleteTokens() {
|
||||
queue.clear()
|
||||
accessCounter.update { -1 }
|
||||
}
|
||||
|
||||
override val token: String?
|
||||
get() {
|
||||
if (accessCounter.value == -1) {
|
||||
return initToken.value
|
||||
}
|
||||
|
||||
if (queue.isEmpty()) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.QUEUE_EMPTY)
|
||||
return null
|
||||
}
|
||||
|
||||
val accesses = accessCounter.getAndUpdate { it + 1 }
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.TOKEN_ACCESS, accesses)
|
||||
return queue.poll()
|
||||
}
|
||||
|
||||
override val nativeGeneratedToken: Unit
|
||||
get() {
|
||||
val nativeTokenGenerator = NativeTokenGenerator(
|
||||
executorService,
|
||||
DeviceInfoReaderBuilder(
|
||||
ConfigurationReader(),
|
||||
PrivacyConfigStorage.getInstance(),
|
||||
GameSessionIdReader.getInstance()
|
||||
),
|
||||
null
|
||||
)
|
||||
nativeTokenGenerator.generateToken { token ->
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.TOKEN_NATIVE_DATA, token)
|
||||
}
|
||||
}
|
||||
|
||||
override fun setInitToken(value: String?) {
|
||||
if (value == null) return
|
||||
|
||||
initToken.update { value }
|
||||
|
||||
triggerTokenAvailable(true)
|
||||
asyncTokenStorage.onTokenAvailable()
|
||||
}
|
||||
|
||||
private fun triggerTokenAvailable(withConfig: Boolean) {
|
||||
InitializeEventsMetricSender.getInstance().sdkTokenDidBecomeAvailableWithConfig(withConfig)
|
||||
}
|
||||
}
|
|
@ -2,7 +2,7 @@ package com.unity3d.services.ads.token;
|
|||
|
||||
import android.util.Base64;
|
||||
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.builder.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderCompressor;
|
||||
import com.unity3d.services.core.device.reader.IDeviceInfoReader;
|
||||
import com.unity3d.services.core.log.DeviceLog;
|
||||
|
|
|
@ -1,137 +0,0 @@
|
|||
package com.unity3d.services.ads.token;
|
||||
|
||||
|
||||
import com.unity3d.services.core.configuration.ConfigurationReader;
|
||||
import com.unity3d.services.core.configuration.InitializeEventsMetricSender;
|
||||
import com.unity3d.services.core.configuration.PrivacyConfigStorage;
|
||||
import com.unity3d.services.core.device.reader.DeviceInfoReaderBuilder;
|
||||
import com.unity3d.services.core.device.reader.GameSessionIdReader;
|
||||
import com.unity3d.services.core.webview.WebViewApp;
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
public class TokenStorage {
|
||||
private static TokenStorage _instance;
|
||||
public static TokenStorage getInstance() {
|
||||
if (_instance == null) {
|
||||
_instance = new TokenStorage();
|
||||
}
|
||||
return _instance;
|
||||
}
|
||||
|
||||
private final Object _lock = new Object();
|
||||
private ConcurrentLinkedQueue<String> _queue;
|
||||
private int _accessCounter = 0;
|
||||
private boolean _peekMode = false;
|
||||
private String _initToken = null;
|
||||
private final ExecutorService _executorService = Executors.newSingleThreadExecutor();
|
||||
|
||||
private TokenStorage() {
|
||||
}
|
||||
|
||||
public void createTokens(JSONArray tokens) throws JSONException {
|
||||
boolean shouldTriggerEvent;
|
||||
synchronized (_lock) {
|
||||
_queue = new ConcurrentLinkedQueue<>();
|
||||
_accessCounter = 0;
|
||||
|
||||
for (int i = 0; i < tokens.length(); i++) {
|
||||
_queue.add(tokens.getString(i));
|
||||
}
|
||||
|
||||
shouldTriggerEvent = !_queue.isEmpty();
|
||||
}
|
||||
|
||||
if (shouldTriggerEvent) {
|
||||
triggerTokenAvailable(false);
|
||||
AsyncTokenStorage.getInstance().onTokenAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
public void appendTokens(JSONArray tokens) throws JSONException {
|
||||
boolean shouldTriggerEvent;
|
||||
synchronized (_lock) {
|
||||
if (_queue == null) {
|
||||
_queue = new ConcurrentLinkedQueue<>();
|
||||
_accessCounter = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < tokens.length(); i++) {
|
||||
_queue.add(tokens.getString(i));
|
||||
}
|
||||
|
||||
shouldTriggerEvent = !_queue.isEmpty();
|
||||
}
|
||||
|
||||
if (shouldTriggerEvent) {
|
||||
triggerTokenAvailable(false);
|
||||
AsyncTokenStorage.getInstance().onTokenAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteTokens() {
|
||||
synchronized (_lock) {
|
||||
_queue = null;
|
||||
_accessCounter = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public String getToken() {
|
||||
synchronized (_lock) {
|
||||
if (_queue == null) {
|
||||
return _initToken;
|
||||
}
|
||||
|
||||
if (_queue.isEmpty()) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.QUEUE_EMPTY);
|
||||
return null;
|
||||
} else if (_peekMode) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.TOKEN_ACCESS, _accessCounter++);
|
||||
return _queue.peek();
|
||||
} else {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.TOKEN_ACCESS, _accessCounter++);
|
||||
return _queue.poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setPeekMode(boolean mode) {
|
||||
synchronized (_lock) {
|
||||
_peekMode = mode;
|
||||
}
|
||||
}
|
||||
|
||||
public void getNativeGeneratedToken() {
|
||||
NativeTokenGenerator nativeTokenGenerator = new NativeTokenGenerator(_executorService, new DeviceInfoReaderBuilder(new ConfigurationReader(), PrivacyConfigStorage.getInstance(), GameSessionIdReader.getInstance()), null);
|
||||
nativeTokenGenerator.generateToken(new INativeTokenGeneratorListener() {
|
||||
@Override
|
||||
public void onReady(String token) {
|
||||
WebViewApp.getCurrentApp().sendEvent(WebViewEventCategory.TOKEN, TokenEvent.TOKEN_NATIVE_DATA, token);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setInitToken(String value) {
|
||||
boolean shouldTriggerEvent;
|
||||
synchronized (_lock) {
|
||||
_initToken = value;
|
||||
shouldTriggerEvent = _initToken != null;
|
||||
}
|
||||
|
||||
if (shouldTriggerEvent) {
|
||||
triggerTokenAvailable(true);
|
||||
AsyncTokenStorage.getInstance().onTokenAvailable();
|
||||
}
|
||||
}
|
||||
|
||||
private void triggerTokenAvailable(Boolean withConfig) {
|
||||
InitializeEventsMetricSender.getInstance().sdkTokenDidBecomeAvailableWithConfig(withConfig);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package com.unity3d.services.ads.token
|
||||
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONException
|
||||
|
||||
interface TokenStorage {
|
||||
val token: String?
|
||||
val nativeGeneratedToken: Unit
|
||||
|
||||
@Throws(JSONException::class)
|
||||
fun createTokens(tokens: JSONArray)
|
||||
@Throws(JSONException::class)
|
||||
fun appendTokens(tokens: JSONArray)
|
||||
fun deleteTokens()
|
||||
fun setInitToken(value: String?)
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsErrors {
|
||||
ERROR_EXCEPTION,
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsEvents {
|
||||
NOT_AVAILABLE,
|
||||
TOPICS_AVAILABLE,
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
import android.adservices.topics.GetTopicsResponse
|
||||
import android.adservices.topics.Topic
|
||||
import android.annotation.SuppressLint
|
||||
import android.os.OutcomeReceiver
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import org.json.JSONArray
|
||||
import org.json.JSONObject
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class TopicsReceiver(private val eventSender: IEventSender) : OutcomeReceiver<GetTopicsResponse, Exception> {
|
||||
override fun onResult(result: GetTopicsResponse) {
|
||||
val resultArray = JSONArray()
|
||||
result.topics.forEach {
|
||||
resultArray.put(formatTopic(it))
|
||||
}
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.TOPICS_AVAILABLE, resultArray.toString())
|
||||
}
|
||||
|
||||
override fun onError(error: Exception) {
|
||||
DeviceLog.debug("GetTopics exception: $error")
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.NOT_AVAILABLE, TopicsErrors.ERROR_EXCEPTION, error.toString())
|
||||
}
|
||||
|
||||
fun formatTopic(topic: Topic): JSONObject {
|
||||
val resultObject = JSONObject()
|
||||
resultObject.put("taxonomyVersion", topic.taxonomyVersion)
|
||||
resultObject.put("modelVersion", topic.modelVersion)
|
||||
resultObject.put("topicId", topic.topicId)
|
||||
return resultObject
|
||||
}
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
import android.adservices.AdServicesState
|
||||
import android.adservices.topics.GetTopicsRequest
|
||||
import android.adservices.topics.TopicsManager
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.os.ext.SdkExtensions
|
||||
import com.unity3d.services.core.device.Device
|
||||
import com.unity3d.services.core.domain.ISDKDispatchers
|
||||
import com.unity3d.services.core.log.DeviceLog
|
||||
import com.unity3d.services.core.webview.WebViewEventCategory
|
||||
import com.unity3d.services.core.webview.bridge.IEventSender
|
||||
import kotlinx.coroutines.asExecutor
|
||||
|
||||
@SuppressLint("NewApi", "MissingPermission")
|
||||
class TopicsService(context: Context, private val dispatchers: ISDKDispatchers, private val eventSender: IEventSender) {
|
||||
private val topicsManager: TopicsManager? = getTopicsManager(context)
|
||||
|
||||
fun checkAvailability(): TopicsStatus {
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return TopicsStatus.ERROR_API_BELOW_33
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return TopicsStatus.ERROR_EXTENSION_BELOW_4
|
||||
}
|
||||
|
||||
if (topicsManager == null) {
|
||||
return TopicsStatus.ERROR_TOPICSMANAGER_NULL
|
||||
}
|
||||
|
||||
if (!AdServicesState.isAdServicesStateEnabled()) {
|
||||
return TopicsStatus.ERROR_AD_SERVICES_DISABLED
|
||||
}
|
||||
|
||||
return TopicsStatus.TOPICS_AVAILABLE
|
||||
}
|
||||
|
||||
fun getTopics(adsSdkName: String, shouldRecordObservation: Boolean) {
|
||||
val callback = TopicsReceiver(eventSender)
|
||||
val topicsRequest = GetTopicsRequest.Builder().setAdsSdkName(adsSdkName).setShouldRecordObservation(shouldRecordObservation).build()
|
||||
try {
|
||||
topicsManager?.getTopics(topicsRequest, dispatchers.default.asExecutor(), callback)
|
||||
} catch (error: Exception) {
|
||||
eventSender.sendEvent(WebViewEventCategory.TOPICS, TopicsEvents.NOT_AVAILABLE, TopicsErrors.ERROR_EXCEPTION, error.toString())
|
||||
DeviceLog.debug("Failed to get topics with error: $error")
|
||||
}
|
||||
}
|
||||
|
||||
private fun getTopicsManager(context: Context): TopicsManager? {
|
||||
// accessing TopicsManager without API level and extension version checks can crash old Android devices
|
||||
// also accessing SdkExtensions below API level 30 causes exception so check API level first
|
||||
if (Device.getApiLevel() < 33) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (SdkExtensions.getExtensionVersion(SdkExtensions.AD_SERVICES) < 4) {
|
||||
return null
|
||||
}
|
||||
|
||||
return context.getSystemService(TopicsManager::class.java)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package com.unity3d.services.ads.topics
|
||||
|
||||
enum class TopicsStatus {
|
||||
TOPICS_AVAILABLE,
|
||||
ERROR_TOPICSMANAGER_NULL,
|
||||
ERROR_API_BELOW_33,
|
||||
ERROR_EXTENSION_BELOW_4,
|
||||
ERROR_AD_SERVICES_DISABLED,
|
||||
}
|
|
@ -479,7 +479,11 @@ public class WebPlayerView extends WebView {
|
|||
// possible Google might reject the app as an unsafe implementation.
|
||||
// https://support.google.com/faqs/answer/7071387?hl=en
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
DeviceLog.error("Received SSL error for '%s': %s", error.getUrl(), error.toString());
|
||||
if (error != null) {
|
||||
DeviceLog.error("Received SSL error for '%s': %s", error.getUrl(), error.toString());
|
||||
} else {
|
||||
DeviceLog.error("Received unknown SSL error: SslError was null");
|
||||
}
|
||||
|
||||
if (shouldSendEvent("onReceivedSslError")) {
|
||||
String url = "";
|
||||
|
|
|
@ -21,11 +21,6 @@ public class AnalyticsModuleConfiguration implements IModuleConfiguration {
|
|||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initModuleState(Configuration configuration) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean initErrorState(Configuration configuration, ErrorState state, String message) {
|
||||
return true;
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
package com.unity3d.services.banners;
|
||||
|
||||
import com.unity3d.ads.UnityAds;
|
||||
import com.unity3d.services.ads.operation.load.ILoadModule;
|
||||
import com.unity3d.services.ads.operation.load.LoadBannerModule;
|
||||
import com.unity3d.services.core.misc.Utilities;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
@ -82,18 +85,7 @@ public class BannerViewCache {
|
|||
}
|
||||
|
||||
public synchronized void triggerBannerErrorEvent(String bannerAdId, final BannerErrorInfo bannerErrorInfo) {
|
||||
final BannerView bannerView = this.getBannerView(bannerAdId);
|
||||
if (bannerView != null && bannerView.getListener() != null) {
|
||||
final BannerView.IListener listener = bannerView.getListener();
|
||||
Utilities.runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (listener != null) {
|
||||
listener.onBannerFailedToLoad(bannerView, bannerErrorInfo);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
LoadBannerModule.getInstance().onUnityAdsFailedToLoad(bannerAdId, UnityAds.UnityAdsLoadError.INTERNAL_ERROR, bannerErrorInfo.errorMessage);
|
||||
}
|
||||
|
||||
public synchronized void triggerBannerLeftApplicationEvent(String bannerAdId) {
|
||||
|
|
Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше
Загрузка…
Ссылка в новой задаче