diff --git a/ChangeLog.txt b/ChangeLog.txt index a284ac125..8684b8b40 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,5 +1,22 @@ Google Mobile Ads Unity Plugin Change Log +************* +Version 3.9.0 +************* + +- Implemented workaround for issue where ad views are rendered in incorrect +position. +- Resolved compatibility issues with Gradle 4. +- Resovled comnpatilbity issues with older versions of Xcode. +- Added API for video ad volume control. +- Added AdColony mediation support package. +- Added AppLovin mediation support package. + +Built and tested with: +- Google Play services 11.6.0 +- Google Mobile Ads iOS SDK 7.25.0 +- Unity Jar Resolver 1.2.59.0 + ************* Version 3.8.0 ************* diff --git a/mediation/AdColony/build.gradle b/mediation/AdColony/build.gradle new file mode 100644 index 000000000..26d2c037b --- /dev/null +++ b/mediation/AdColony/build.gradle @@ -0,0 +1,68 @@ +/* +* Gradle file to build a Unity package to add AdColony mediation support to the Google Mobile Ads Unity plugin. +* Usage: ./gradlew exportPackage +*/ + +defaultTasks 'exportPackage' + +// Project level variables. +project.ext { + unity_exe = System.getProperty("UNITY_EXE") + if (unity_exe == null || unity_exe.isEmpty()) { + unity_exe = System.getenv("UNITY_EXE") + } + if (unity_exe == null || unity_exe.isEmpty()) { + unity_exe = '/Applications/Unity/Unity.app/Contents/MacOS/Unity' + } + + if (!file(unity_exe).exists()) { + throw new GradleException('Unable to locate installation of Unity. Please create a ' + + 'UNITY_EXE environment variable and point it to your Unity installation.') + } + + pluginSource = file('source/plugin').absolutePath + pluginBuildDir = file('temp/plugin-build-dir').absolutePath + buildPath = file('temp').absolutePath + exportPath = file('GoogleMobileAdsAdColonyMediation.unitypackage').absolutePath +} + +// Build unity package using through command line interface. +// Create new unity project with files in temporary build directory and export files to a unity package. +// Command line usage and arguments documented at http://docs.unity3d.com/Manual/CommandLineArguments.html. +task exportPackage(type: Exec) { + description = "Creates and exports the Plugin unity package" + executable "${unity_exe}" + args "-g.building", + "-batchmode", + "-projectPath", "${pluginBuildDir}", + "-logFile", "temp/unity.log", + "-exportPackage", + "Assets/GoogleMobileAds/Editor", + "Assets/Plugins", + "${exportPath}", + "-quit" + + ignoreExitValue true + + doLast { + if (execResult.getExitValue() != 0) { + copy { + from "temp/" + into "./" + include "unity.log" + } + } + } +} + +task createTempBuildFolder(type: Copy) { + from { "${pluginSource}" } + into { "${pluginBuildDir}" } +} + +task clearTempBuildFolder(type: Delete) { + delete { "${buildPath}" } +} + +exportPackage.dependsOn(createTempBuildFolder) +exportPackage.finalizedBy(clearTempBuildFolder) diff --git a/mediation/AdColony/source/plugin/Assets/GoogleMobileAds/Editor/AdColonyMediationDependencies.xml b/mediation/AdColony/source/plugin/Assets/GoogleMobileAds/Editor/AdColonyMediationDependencies.xml new file mode 100644 index 000000000..4ba8310f0 --- /dev/null +++ b/mediation/AdColony/source/plugin/Assets/GoogleMobileAds/Editor/AdColonyMediationDependencies.xml @@ -0,0 +1,23 @@ + + + + + https://adcolony.bintray.com/AdColony + + + + + https://adcolony.bintray.com/AdColony + + + + + + + + https://github.com/CocoaPods/Specs + + + + + diff --git a/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/AndroidManifest.xml b/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/AndroidManifest.xml new file mode 100644 index 000000000..1db8ea5b1 --- /dev/null +++ b/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/AndroidManifest.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/project.properties b/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/project.properties new file mode 100644 index 000000000..799d1bf81 --- /dev/null +++ b/mediation/AdColony/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAdColonyMediation/project.properties @@ -0,0 +1,2 @@ +target=android-19 +android.library=true \ No newline at end of file diff --git a/mediation/AppLovin/build.gradle b/mediation/AppLovin/build.gradle new file mode 100644 index 000000000..d3b2ddac1 --- /dev/null +++ b/mediation/AppLovin/build.gradle @@ -0,0 +1,68 @@ +/* +* Gradle file to build a Unity package to add AppLovin mediation support to the Google Mobile Ads Unity plugin. +* Usage: ./gradlew exportPackage +*/ + +defaultTasks 'exportPackage' + +// Project level variables. +project.ext { + unity_exe = System.getProperty("UNITY_EXE") + if (unity_exe == null || unity_exe.isEmpty()) { + unity_exe = System.getenv("UNITY_EXE") + } + if (unity_exe == null || unity_exe.isEmpty()) { + unity_exe = '/Applications/Unity/Unity.app/Contents/MacOS/Unity' + } + + if (!file(unity_exe).exists()) { + throw new GradleException('Unable to locate installation of Unity. Please create a ' + + 'UNITY_EXE environment variable and point it to your Unity installation.') + } + + pluginSource = file('source/plugin').absolutePath + pluginBuildDir = file('temp/plugin-build-dir').absolutePath + buildPath = file('temp').absolutePath + exportPath = file('GoogleMobileAdsAppLovinMediation.unitypackage').absolutePath +} + +// Build unity package using through command line interface. +// Create new unity project with files in temporary build directory and export files to a unity package. +// Command line usage and arguments documented at http://docs.unity3d.com/Manual/CommandLineArguments.html. +task exportPackage(type: Exec) { + description = "Creates and exports the Plugin unity package" + executable "${unity_exe}" + args "-g.building", + "-batchmode", + "-projectPath", "${pluginBuildDir}", + "-logFile", "temp/unity.log", + "-exportPackage", + "Assets/GoogleMobileAds/Editor", + "Assets/Plugins", + "${exportPath}", + "-quit" + + ignoreExitValue true + + doLast { + if (execResult.getExitValue() != 0) { + copy { + from "temp/" + into "./" + include "unity.log" + } + } + } +} + +task createTempBuildFolder(type: Copy) { + from { "${pluginSource}" } + into { "${pluginBuildDir}" } +} + +task clearTempBuildFolder(type: Delete) { + delete { "${buildPath}" } +} + +exportPackage.dependsOn(createTempBuildFolder) +exportPackage.finalizedBy(clearTempBuildFolder) diff --git a/mediation/AppLovin/source/plugin/Assets/GoogleMobileAds/Editor/AppLovinMediationDependencies.xml b/mediation/AppLovin/source/plugin/Assets/GoogleMobileAds/Editor/AppLovinMediationDependencies.xml new file mode 100644 index 000000000..0d3407ea8 --- /dev/null +++ b/mediation/AppLovin/source/plugin/Assets/GoogleMobileAds/Editor/AppLovinMediationDependencies.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + https://github.com/CocoaPods/Specs + + + + + diff --git a/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/AndroidManifest.xml b/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/AndroidManifest.xml new file mode 100644 index 000000000..27ebd7582 --- /dev/null +++ b/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/AndroidManifest.xml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + diff --git a/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/project.properties b/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/project.properties new file mode 100644 index 000000000..799d1bf81 --- /dev/null +++ b/mediation/AppLovin/source/plugin/Assets/Plugins/Android/GoogleMobileAdsAppLovinMediation/project.properties @@ -0,0 +1,2 @@ +target=android-19 +android.library=true \ No newline at end of file diff --git a/mediation/Vungle/build.gradle b/mediation/Vungle/build.gradle index 9003a72a1..fc1e778a1 100644 --- a/mediation/Vungle/build.gradle +++ b/mediation/Vungle/build.gradle @@ -1,5 +1,4 @@ /* -/* * Gradle file to build a Unity package to add Vungle mediation support to the Google Mobile Ads Unity plugin. * Usage: ./gradlew exportPackage */ @@ -17,7 +16,7 @@ project.ext { } if (!file(unity_exe).exists()) { - throw new GradleException('Unable to locate installation of Unity. Please create a' + + throw new GradleException('Unable to locate installation of Unity. Please create a ' + 'UNITY_EXE environment variable and point it to your Unity installation.') } @@ -29,13 +28,13 @@ project.ext { // Build jar from android plugin source files using existing Gradle build file. task buildAndroidPluginJar(type: GradleBuild) { - buildFile = 'source/android-library/app/build.gradle' + buildFile = 'source/android-library/vungle/build.gradle' tasks = ['build'] } // Move android plugin jar to temporary build directory. task copyAndroidLibraryJar(type: Copy) { - from("source/android-library/app/build/intermediates/bundles/release/") + from("source/android-library/vungle/build/intermediates/bundles/release/") into("${pluginBuildDir}/Assets/Plugins/Android/") include('classes.jar') rename('classes.jar', 'vungle-extras-library.jar') diff --git a/mediation/Vungle/source/android-library/build.gradle b/mediation/Vungle/source/android-library/build.gradle index b486acc90..c7ae573ff 100644 --- a/mediation/Vungle/source/android-library/build.gradle +++ b/mediation/Vungle/source/android-library/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0' + classpath 'com.android.tools.build:gradle:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -14,12 +15,7 @@ buildscript { allprojects { repositories { + google() jcenter() - maven { - url 'https://maven.google.com' - } - flatDir { - dirs 'libs' - } } } diff --git a/mediation/Vungle/source/android-library/settings.gradle b/mediation/Vungle/source/android-library/settings.gradle index e7b4def49..e58e01c14 100644 --- a/mediation/Vungle/source/android-library/settings.gradle +++ b/mediation/Vungle/source/android-library/settings.gradle @@ -1 +1,4 @@ -include ':app' +include 'vungle' +include 'app' +project(':app').projectDir = new File('${projectDir}/../../../../../source/android-library/app') + diff --git a/mediation/Vungle/source/android-library/app/.gitignore b/mediation/Vungle/source/android-library/vungle/.gitignore similarity index 100% rename from mediation/Vungle/source/android-library/app/.gitignore rename to mediation/Vungle/source/android-library/vungle/.gitignore diff --git a/mediation/Vungle/source/android-library/app/build.gradle b/mediation/Vungle/source/android-library/vungle/build.gradle similarity index 51% rename from mediation/Vungle/source/android-library/app/build.gradle rename to mediation/Vungle/source/android-library/vungle/build.gradle index 4f119bb45..fd9965c4f 100644 --- a/mediation/Vungle/source/android-library/app/build.gradle +++ b/mediation/Vungle/source/android-library/vungle/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion 26 - buildToolsVersion "22.0.1" defaultConfig { minSdkVersion 14 @@ -23,22 +22,8 @@ android { } dependencies { - compile files('libs/unity-plugin-library.jar') - compile 'com.google.ads.mediation:vungle:5.1.0.0' -} - -// Build jar from android plugin source files using existing Gradle build file. -task buildAndroidPluginJar(type: GradleBuild) { - buildFile = '../../../../../source/android-library/app/build.gradle' - tasks = ['build'] -} - -// Move android plugin jar to libs directory. -task copyAndroidLibraryJar(type: Copy) { - from("../../../../../source/android-library/app/build/intermediates/bundles/release/") - into("libs") - include('classes.jar') - rename('classes.jar', 'unity-plugin-library.jar') + api project(':app') + api 'com.google.ads.mediation:vungle:5.3.0.0' } task clearJar(type: Delete) { @@ -53,4 +38,3 @@ task makeJar(type: Copy) { } makeJar.dependsOn(clearJar, build) -preBuild.dependsOn(copyAndroidLibraryJar, buildAndroidPluginJar) diff --git a/mediation/Vungle/source/android-library/app/proguard-rules.pro b/mediation/Vungle/source/android-library/vungle/proguard-rules.pro similarity index 100% rename from mediation/Vungle/source/android-library/app/proguard-rules.pro rename to mediation/Vungle/source/android-library/vungle/proguard-rules.pro diff --git a/mediation/Vungle/source/android-library/app/src/main/AndroidManifest.xml b/mediation/Vungle/source/android-library/vungle/src/main/AndroidManifest.xml similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/AndroidManifest.xml rename to mediation/Vungle/source/android-library/vungle/src/main/AndroidManifest.xml diff --git a/mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityExtrasBuilder.java b/mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityExtrasBuilder.java similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityExtrasBuilder.java rename to mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityExtrasBuilder.java diff --git a/mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityInterstitialExtrasBuilder.java b/mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityInterstitialExtrasBuilder.java similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityInterstitialExtrasBuilder.java rename to mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityInterstitialExtrasBuilder.java diff --git a/mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityRewardedVideoExtrasBuilder.java b/mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityRewardedVideoExtrasBuilder.java similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/java/com/google/unity/mediation/vungle/VungleUnityRewardedVideoExtrasBuilder.java rename to mediation/Vungle/source/android-library/vungle/src/main/java/com/google/unity/mediation/vungle/VungleUnityRewardedVideoExtrasBuilder.java diff --git a/mediation/Vungle/source/android-library/app/src/main/res/mipmap-hdpi/ic_launcher.png b/mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/mipmap-hdpi/ic_launcher.png rename to mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-hdpi/ic_launcher.png diff --git a/mediation/Vungle/source/android-library/app/src/main/res/mipmap-mdpi/ic_launcher.png b/mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/mipmap-mdpi/ic_launcher.png rename to mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-mdpi/ic_launcher.png diff --git a/mediation/Vungle/source/android-library/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-xhdpi/ic_launcher.png diff --git a/mediation/Vungle/source/android-library/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to mediation/Vungle/source/android-library/vungle/src/main/res/mipmap-xxhdpi/ic_launcher.png diff --git a/mediation/Vungle/source/android-library/app/src/main/res/values/strings.xml b/mediation/Vungle/source/android-library/vungle/src/main/res/values/strings.xml similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/values/strings.xml rename to mediation/Vungle/source/android-library/vungle/src/main/res/values/strings.xml diff --git a/mediation/Vungle/source/android-library/app/src/main/res/values/styles.xml b/mediation/Vungle/source/android-library/vungle/src/main/res/values/styles.xml similarity index 100% rename from mediation/Vungle/source/android-library/app/src/main/res/values/styles.xml rename to mediation/Vungle/source/android-library/vungle/src/main/res/values/styles.xml diff --git a/source/android-library/app/build.gradle b/source/android-library/app/build.gradle index 1031ffe1e..21099c181 100644 --- a/source/android-library/app/build.gradle +++ b/source/android-library/app/build.gradle @@ -2,7 +2,6 @@ apply plugin: 'com.android.library' android { compileSdkVersion 26 - buildToolsVersion "22.0.1" defaultConfig { minSdkVersion 14 @@ -23,9 +22,9 @@ android { } dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:26.0.0' - compile 'com.google.android.gms:play-services-ads:11.4.0' + api fileTree(dir: 'libs', include: ['*.jar']) + api 'com.android.support:appcompat-v7:26.1.0' + api 'com.google.android.gms:play-services-ads:11.6.0' } task clearJar(type: Delete) { diff --git a/source/android-library/app/src/main/java/com/google/unity/ads/Banner.java b/source/android-library/app/src/main/java/com/google/unity/ads/Banner.java index d7f021137..e01206f25 100644 --- a/source/android-library/app/src/main/java/com/google/unity/ads/Banner.java +++ b/source/android-library/app/src/main/java/com/google/unity/ads/Banner.java @@ -17,6 +17,7 @@ import android.app.Activity; import android.graphics.Color; +import android.os.Build; import android.util.Log; import android.view.Gravity; import android.view.View; @@ -24,7 +25,6 @@ import android.view.ViewParent; import android.view.WindowManager; import android.widget.PopupWindow; - import com.google.android.gms.ads.AdListener; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdSize; @@ -203,15 +203,38 @@ private void createPopupWindow() { } private void showPopUpWindow() { + View anchorView = mUnityPlayerActivity.getWindow().getDecorView().getRootView(); + if (this.mPositionCode == PluginUtils.POSITION_CUSTOM) { - mPopupWindow.showAtLocation( - mUnityPlayerActivity.getWindow().getDecorView().getRootView(), - Gravity.NO_GRAVITY, (int) PluginUtils.convertDpToPixel(mHorizontalOffset), - (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + // Android Nougat has a PopUpWindow bug gravity doesn't position views as expected. + // Using offset values as a workaround. On certain devices (ie. Samsung S8) calls to + // update() cause the PopUpWindow to be rendered at the top of the screen. Using + // showAsDropDown() instead of showAtLocation() (when possible) avoids this issue. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + mPopupWindow.showAsDropDown(anchorView, + (int) PluginUtils.convertDpToPixel(mHorizontalOffset), + -anchorView.getHeight() + + (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + } else { + mPopupWindow.showAtLocation( + anchorView, Gravity.NO_GRAVITY, + (int) PluginUtils.convertDpToPixel(mHorizontalOffset), + (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + } } else { - mPopupWindow.showAtLocation(mUnityPlayerActivity.getWindow().getDecorView() - .getRootView(), - PluginUtils.getLayoutGravityForPositionCode(mPositionCode), 0, 0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int adViewWidth = mAdView.getAdSize().getWidthInPixels(mUnityPlayerActivity); + int adViewHeight = mAdView.getAdSize().getHeightInPixels(mUnityPlayerActivity); + + mPopupWindow.showAsDropDown(anchorView, + PluginUtils.getHorizontalOffsetForPositionCode(mPositionCode, adViewWidth, + anchorView.getWidth()), + PluginUtils.getVerticalOffsetForPositionCode(mPositionCode, adViewHeight, + anchorView.getHeight())); + } else { + mPopupWindow.showAtLocation(anchorView, + PluginUtils.getLayoutGravityForPositionCode(mPositionCode), 0, 0); + } } } diff --git a/source/android-library/app/src/main/java/com/google/unity/ads/NativeExpressAd.java b/source/android-library/app/src/main/java/com/google/unity/ads/NativeExpressAd.java index 428eff07d..852a8a253 100644 --- a/source/android-library/app/src/main/java/com/google/unity/ads/NativeExpressAd.java +++ b/source/android-library/app/src/main/java/com/google/unity/ads/NativeExpressAd.java @@ -17,6 +17,7 @@ import android.app.Activity; import android.graphics.Color; +import android.os.Build; import android.util.Log; import android.view.Gravity; import android.view.View; @@ -24,7 +25,6 @@ import android.view.ViewParent; import android.view.WindowManager; import android.widget.PopupWindow; - import com.google.android.gms.ads.AdListener; import com.google.android.gms.ads.AdRequest; import com.google.android.gms.ads.AdSize; @@ -199,15 +199,38 @@ public void createPopupWindow() { } private void showPopUpWindow() { + View anchorView = mUnityPlayerActivity.getWindow().getDecorView().getRootView(); + if (this.mPositionCode == PluginUtils.POSITION_CUSTOM) { - mPopupWindow.showAtLocation( - mUnityPlayerActivity.getWindow().getDecorView().getRootView(), - Gravity.NO_GRAVITY, (int) PluginUtils.convertDpToPixel(mHorizontalOffset), - (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + // Android Nougat has a PopUpWindow bug gravity doesn't position views as expected. + // Using offset values as a workaround. On certain devices (ie. Samsung S8) calls to + // update() cause the PopUpWindow to be rendered at the top of the screen. Using + // showAsDropDown() instead of showAtLocation() (when possible) avoids this issue. + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + mPopupWindow.showAsDropDown(anchorView, + (int) PluginUtils.convertDpToPixel(mHorizontalOffset), + -anchorView.getHeight() + + (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + } else { + mPopupWindow.showAtLocation( + anchorView, Gravity.NO_GRAVITY, + (int) PluginUtils.convertDpToPixel(mHorizontalOffset), + (int) PluginUtils.convertDpToPixel(mVerticalOffset)); + } } else { - mPopupWindow.showAtLocation(mUnityPlayerActivity.getWindow().getDecorView() - .getRootView(), - PluginUtils.getLayoutGravityForPositionCode(mPositionCode), 0, 0); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { + int adViewWidth = mAdView.getAdSize().getWidthInPixels(mUnityPlayerActivity); + int adViewHeight = mAdView.getAdSize().getHeightInPixels(mUnityPlayerActivity); + + mPopupWindow.showAsDropDown(anchorView, + PluginUtils.getHorizontalOffsetForPositionCode(mPositionCode, adViewWidth, + anchorView.getWidth()), + PluginUtils.getVerticalOffsetForPositionCode(mPositionCode, adViewHeight, + anchorView.getHeight())); + } else { + mPopupWindow.showAtLocation(anchorView, + PluginUtils.getLayoutGravityForPositionCode(mPositionCode), 0, 0); + } } } diff --git a/source/android-library/app/src/main/java/com/google/unity/ads/PluginUtils.java b/source/android-library/app/src/main/java/com/google/unity/ads/PluginUtils.java index 00226b23b..fa16f3c07 100644 --- a/source/android-library/app/src/main/java/com/google/unity/ads/PluginUtils.java +++ b/source/android-library/app/src/main/java/com/google/unity/ads/PluginUtils.java @@ -135,16 +135,68 @@ public static int getLayoutGravityForPositionCode(int positionCode) { return gravity; } + public static int getHorizontalOffsetForPositionCode(int positionCode, int viewWidth, + int anchorWidth) { + int offset; + switch (positionCode) { + case POSITION_TOP_LEFT: + case POSITION_BOTTOM_LEFT: + offset = 0; + break; + case POSITION_TOP_RIGHT: + case POSITION_BOTTOM_RIGHT: + offset = anchorWidth - viewWidth; + break; + case POSITION_TOP: + case POSITION_BOTTOM: + case POSITION_CENTER: + offset = (anchorWidth - viewWidth) / 2; + break; + // Make the center position the default horizontal position. + default: + Log.w(LOGTAG, "Attempted to position ad with invalid ad " + + "position. Using default center horizontal position."); + offset = (anchorWidth - viewWidth) / 2; + } + + return offset; + } + + public static int getVerticalOffsetForPositionCode(int positionCode, int viewHeight, + int anchorHeight) { + int offset; + switch (positionCode) { + case POSITION_TOP: + case POSITION_TOP_LEFT: + case POSITION_TOP_RIGHT: + offset = -anchorHeight; + break; + case POSITION_CENTER: + offset = (-anchorHeight - viewHeight) / 2; + break; + case POSITION_BOTTOM: + case POSITION_BOTTOM_LEFT: + case POSITION_BOTTOM_RIGHT: + offset = -viewHeight; + break; + // Make the bottom position the default vertical position. + default: + Log.w(LOGTAG, "Attempted to position ad with invalid ad " + + "position. Using default bottom vertical position."); + offset = -viewHeight; + } + + return offset; + } + public static float convertPixelsToDp(float px) { DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); - float dp = px / metrics.density; - return dp; + return px / metrics.density; } public static float convertDpToPixel(float dp) { DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics(); - float px = dp * metrics.density; - return px; + return dp * metrics.density; } public static void setPopUpWindowLayoutType(PopupWindow popupWindow, int layoutType) { diff --git a/source/android-library/build.gradle b/source/android-library/build.gradle index f1aded488..c7ae573ff 100644 --- a/source/android-library/build.gradle +++ b/source/android-library/build.gradle @@ -2,10 +2,11 @@ buildscript { repositories { + google() jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.0' + classpath 'com.android.tools.build:gradle:3.0.0' // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files @@ -14,9 +15,7 @@ buildscript { allprojects { repositories { + google() jcenter() - maven { - url 'https://maven.google.com' - } } } diff --git a/source/plugin/Assets/GoogleMobileAds/Api/AdRequest.cs b/source/plugin/Assets/GoogleMobileAds/Api/AdRequest.cs index 935787a8c..9ecbc491c 100644 --- a/source/plugin/Assets/GoogleMobileAds/Api/AdRequest.cs +++ b/source/plugin/Assets/GoogleMobileAds/Api/AdRequest.cs @@ -21,7 +21,7 @@ namespace GoogleMobileAds.Api { public class AdRequest { - public const string Version = "3.8.0"; + public const string Version = "3.9.0"; public const string TestDeviceSimulator = "SIMULATOR"; private AdRequest(Builder builder) diff --git a/source/plugin/Assets/GoogleMobileAds/Api/MobileAds.cs b/source/plugin/Assets/GoogleMobileAds/Api/MobileAds.cs index 0b7dd941c..cdd36254c 100644 --- a/source/plugin/Assets/GoogleMobileAds/Api/MobileAds.cs +++ b/source/plugin/Assets/GoogleMobileAds/Api/MobileAds.cs @@ -28,6 +28,16 @@ public static void Initialize(string appId) client.Initialize(appId); } + public static void SetApplicationMuted(bool muted) + { + client.SetApplicationMuted(muted); + } + + public static void SetApplicationVolume(float volume) + { + client.SetApplicationVolume(volume); + } + private static IMobileAdsClient GetMobileAdsClient() { Type googleMobileAdsClientFactory = Type.GetType( @@ -38,4 +48,4 @@ private static IMobileAdsClient GetMobileAdsClient() return (IMobileAdsClient)method.Invoke(null, null); } } -} \ No newline at end of file +} diff --git a/source/plugin/Assets/GoogleMobileAds/Common/DummyClient.cs b/source/plugin/Assets/GoogleMobileAds/Common/DummyClient.cs index 7e25efb55..bb26ef9e0 100644 --- a/source/plugin/Assets/GoogleMobileAds/Common/DummyClient.cs +++ b/source/plugin/Assets/GoogleMobileAds/Common/DummyClient.cs @@ -29,7 +29,7 @@ public DummyClient() } // Disable warnings for unused dummy ad events. -#pragma warning disable 67 + #pragma warning disable 67 public event EventHandler OnAdLoaded; @@ -47,7 +47,7 @@ public DummyClient() public event EventHandler OnCustomNativeTemplateAdLoaded; -#pragma warning restore 67 + #pragma warning restore 67 public string UserId { @@ -68,6 +68,16 @@ public void Initialize(string appId) Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name); } + public void SetApplicationMuted(bool muted) + { + Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name); + } + + public void SetApplicationVolume(float volume) + { + Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name); + } + public void CreateBannerView(string adUnitId, AdSize adSize, AdPosition position) { Debug.Log("Dummy " + MethodBase.GetCurrentMethod().Name); diff --git a/source/plugin/Assets/GoogleMobileAds/Common/IMobileAdsClient.cs b/source/plugin/Assets/GoogleMobileAds/Common/IMobileAdsClient.cs index 6d1c39dc7..1f6226869 100644 --- a/source/plugin/Assets/GoogleMobileAds/Common/IMobileAdsClient.cs +++ b/source/plugin/Assets/GoogleMobileAds/Common/IMobileAdsClient.cs @@ -12,10 +12,22 @@ // See the License for the specific language governing permissions and // limitations under the License. -namespace GoogleMobileAds.Common { +namespace GoogleMobileAds.Common +{ public interface IMobileAdsClient { // Initialize the Mobile Ads SDK. void Initialize(string appId); + + // The application’s audio volume. Affects audio volumes of all ads relative + // to other audio output. Valid ad volume values range from 0.0 (silent) to 1.0 + // (current device volume). Use this method only if your application has its own + // volume controls (e.g., custom music or sound effect volumes). Defaults to 1.0. + void SetApplicationVolume(float volume); + + // Indicates if the application’s audio is muted. Affects initial mute state for + // all ads. Use this method only if your application has its own volume controls + // (e.g., custom music or sound effect muting). Defaults to false. + void SetApplicationMuted(bool muted); } } diff --git a/source/plugin/Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml b/source/plugin/Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml index 1e70f8496..d1434da53 100644 --- a/source/plugin/Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml +++ b/source/plugin/Assets/GoogleMobileAds/Editor/GoogleMobileAdsDependencies.xml @@ -1,6 +1,6 @@ - + https://maven.google.com diff --git a/source/plugin/Assets/GoogleMobileAds/Platforms/Android/MobileAdsClient.cs b/source/plugin/Assets/GoogleMobileAds/Platforms/Android/MobileAdsClient.cs index 50df4bf9f..0b229db05 100644 --- a/source/plugin/Assets/GoogleMobileAds/Platforms/Android/MobileAdsClient.cs +++ b/source/plugin/Assets/GoogleMobileAds/Platforms/Android/MobileAdsClient.cs @@ -42,6 +42,18 @@ public void Initialize(string appId) AndroidJavaClass mobileAdsClass = new AndroidJavaClass(Utils.MobileAdsClassName); mobileAdsClass.CallStatic("initialize", activity, appId); } + + public void SetApplicationVolume(float volume) + { + AndroidJavaClass mobileAdsClass = new AndroidJavaClass(Utils.MobileAdsClassName); + mobileAdsClass.CallStatic("setAppVolume", volume); + } + + public void SetApplicationMuted(bool muted) + { + AndroidJavaClass mobileAdsClass = new AndroidJavaClass(Utils.MobileAdsClassName); + mobileAdsClass.CallStatic("setAppMuted", muted); + } } } diff --git a/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/Externs.cs b/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/Externs.cs index 74b4533dd..57cabdfd8 100644 --- a/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/Externs.cs +++ b/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/Externs.cs @@ -27,6 +27,12 @@ internal class Externs [DllImport("__Internal")] internal static extern void GADUInitialize(string key); + [DllImport("__Internal")] + internal static extern void GADUSetApplicationVolume(float volume); + + [DllImport("__Internal")] + internal static extern void GADUSetApplicationMuted(bool muted); + [DllImport("__Internal")] internal static extern IntPtr GADUCreateRequest(); diff --git a/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/MobileAdsClient.cs b/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/MobileAdsClient.cs index 50a76cd73..9e3182ec4 100644 --- a/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/MobileAdsClient.cs +++ b/source/plugin/Assets/GoogleMobileAds/Platforms/iOS/MobileAdsClient.cs @@ -38,6 +38,16 @@ public void Initialize(string appId) { Externs.GADUInitialize(appId); } + + public void SetApplicationVolume(float volume) + { + Externs.GADUSetApplicationVolume(volume); + } + + public void SetApplicationMuted(bool muted) + { + Externs.GADUSetApplicationMuted(muted); + } } } diff --git a/source/plugin/Assets/Plugins/iOS/GADUInterface.m b/source/plugin/Assets/Plugins/iOS/GADUInterface.m index 530ca95c9..df54e1f25 100644 --- a/source/plugin/Assets/Plugins/iOS/GADUInterface.m +++ b/source/plugin/Assets/Plugins/iOS/GADUInterface.m @@ -50,6 +50,22 @@ void GADUInitialize(const char *appId) { [GADMobileAds configureWithApplicationID:GADUStringFromUTF8String(appId)]; } +// The application’s audio volume. Affects audio volumes of all ads relative to +// other audio output. Valid ad volume values range from 0.0 (silent) to 1.0 +// (current device volume). Use this method only if your application has its own +// volume controls (e.g., custom music or sound effect volumes). Defaults +// to 1.0. +void GADUSetApplicationVolume(float volume) { + [[GADMobileAds sharedInstance] setApplicationVolume:volume]; +} + +// Indicates if the application’s audio is muted. Affects initial mute state for +// all ads. Use this method only if your application has its own volume controls +// (e.g., custom music or sound effect muting). Defaults to NO. +void GADUSetApplicationMuted(BOOL muted) { + [[GADMobileAds sharedInstance] setApplicationMuted:muted]; +} + /// Creates a GADBannerView with the specified width, height, and position. Returns a reference to /// the GADUBannerView. GADUTypeBannerRef GADUCreateBannerView(GADUTypeBannerClientRef *bannerClient, const char *adUnitID, diff --git a/source/plugin/Assets/Plugins/iOS/GADUPluginUtil.m b/source/plugin/Assets/Plugins/iOS/GADUPluginUtil.m index da6902f2d..16584284a 100644 --- a/source/plugin/Assets/Plugins/iOS/GADUPluginUtil.m +++ b/source/plugin/Assets/Plugins/iOS/GADUPluginUtil.m @@ -4,8 +4,24 @@ #import "UnityAppController.h" +@interface UIView (unityStub) +@property UILayoutGuide *safeAreaLayoutGuide; +@end + @implementation GADUPluginUtil +static BOOL IsOperatingSystemAtLeastVersion(NSInteger majorVersion) { + NSProcessInfo *processInfo = NSProcessInfo.processInfo; + if ([processInfo respondsToSelector:@selector(isOperatingSystemAtLeastVersion:)]) { + // iOS 8+. + NSOperatingSystemVersion version = {majorVersion}; + return [processInfo isOperatingSystemAtLeastVersion:version]; + } else { + // pre-iOS 8. App supports iOS 7+, so this process must be running on iOS 7. + return majorVersion >= 7; + } +} + + (UIViewController *)unityGLViewController { return ((UnityAppController *)[UIApplication sharedApplication].delegate).rootViewController; } @@ -14,7 +30,7 @@ + (void)positionView:(UIView *)view inParentView:(UIView *)parentView adPosition:(GADAdPosition)adPosition { CGRect parentBounds = parentView.bounds; - if (@available(iOS 11, *)) { + if (IsOperatingSystemAtLeastVersion(11)) { parentBounds = parentView.safeAreaLayoutGuide.layoutFrame; } CGFloat top = CGRectGetMinY(parentBounds) + CGRectGetMidY(view.bounds);