创建自定义事件

借助自定义事件,使用 AdMob 中介的发布商可以为支持的广告联盟以外的第三方广告联盟添加广告瀑布流中介。本指南介绍了如何在 Unity 项目中使用针对 Android 和 iOS 构建的现有自定义事件。

前提条件

  • 完成入门指南的学习。您的 Unity 应用应该已经导入了 Google 移动广告 Unity 插件。

  • 已针对 Android 和 iOS 构建了自定义事件适配器 (adapter)。如需创建自定义事件适配器,请参阅我们面向 AndroidiOS 的自定义事件指南。

定义自定义事件

为了让自定义事件参与中介,您必须在 AdMob 网站界面中定义自定义事件。将自定义事件添加到您的 Android 中介组和 iOS 中介组。

以下屏幕截图显示的是自定义事件示例的部分设置:

如何填写参数
类名称 (iOS)

对于 iOS,请输入实现自定义事件的类的名称。

如果您的类是用 Swift 实现的,则您需要添加其应用 / 框架模块名称作为类名称的前缀(如 appName.className)。

如果项目中包含多个目标,或者项目名称与目标名称不一致,则需要包含目标名称。如果包含目标名称,看起来将如下所示:appName_targetName.className。此外,请务必将短划线等任何非字母数字字符替换为下划线。

类名称 (Android) 对于 Android,请确保您为 Class Name 指定的值是 Android 的完全限定 (fully qualified) 类名称(如 com.google.ads.mediation.sample.customevent.SampleCustomEvent)。
标签 为事件输入一个唯一名称。
参数 如果您想要向自定义事件传递字符串参数,例如广告单元 ID。

导入自定义事件库

您可能需要导入额外的库,自定义事件才能正常运行。例如,您可能需要添加以下库:

  • Android 第三方 SDK
  • Android 第三方自定义事件
  • iOS 第三方广告 SDK
  • iOS 第三方自定义事件

库类型

您可以通过如下多种方式将 Android 或 iOS 代码导入 Unity 项目:

  • 使用 External Dependency Manager for Unity 导入预构建的 Android 或 iOS 工件
  • 导入 AAR 插件和 Android 库
  • 导入 Java 和 Kotlin 源文件
  • 导入 iOS 源文件和静态库

根据您使用的库的打包方式,您可能需要为每个库使用不同的导入策略。下文将更详细地介绍每种策略。

(推荐)导入预构建的 Android 或 iOS 工件

使用 External Dependency Manager for Unity 从 Maven 或 CocoaPods 导入预构建的工件。此插件包含在 GoogleMobileAds 插件中。

如需导入现有工件,请创建一个配置文件来定义您的导入。文件名和路径须满足以下要求:

  • 文件必须位于 /Editor/ 文件夹中。
  • 文件名必须以 Dependencies.xml 结尾。

例如,要为虚构的广告联盟 AdPub 导入自定义事件适配器,请创建以下文件:

Assets/AdPub/Editor/AdPubDependencies.xml

接下来,在 AdPubDependencies.xml 文件中定义依赖项。如需了解关于如何配置导入项的规则,请参阅 External Dependency Manager for Unity 入门。以下代码段包含用于虚构的“AdPub”广告联盟的 Android 和 iOS SDK 以及自定义事件库。

Assets/AdPub/Editor/AdPubDependencies.xml

<dependencies>
  <androidPackages>
    <androidPackage spec="com.adpub.android:adpub-sdk:1.0.0" />
    <androidPackage spec="com.adpub.android:adpub-custom-event:1.0.0">
      <repositories>
        <repository>https://repo.maven.apache.org/maven2/</repository>
        <repository>https://dl.google.com/dl/android/maven2/</repository>
      </repositories>
    </androidPackage>
  </androidPackages>
  <iosPods>
    <iosPod name="AdPubSDK" version="1.0" />
    <iosPod name="AdPubCustomEvent" version="1.0">
      <sources>
        <source>https://github.com/CocoaPods/Specs</source>
      </sources>
    </iosPod>
  </iosPods>
</dependencies>

如果您的自定义事件工件中已包含所需广告联盟 SDK 的依赖项,则您无需明确定义 SDK 依赖项:示例

External Dependency Manager 会自动监控配置变更并解析依赖项。您还可以使用以下菜单命令执行手动解析:

Assets > External Dependency Manager > Android Resolver > Force Resolve

导入 AAR 插件和 Android 库

Unity 支持导入 *.aar 文件以及 Android 库项目。如果您的 Android 自定义事件以这种方式打包,请参阅 AAR 插件和 Android 库,了解如何将这些文件添加到 Unity 项目中。

导入 Java 和 Kotlin 源文件

从 Unity 2018.2 或更高版本开始,如果您的 Android 自定义事件代码包含未编译的 *.java*.kt 文件,您可以使用 Java 或 Kotlin 源文件作为插件

导入 iOS 源文件和静态库

Unity 支持 *.framework 工件、*.h*.m 源文件。如需了解如何导入 iOS 工件和源文件,请参阅 Unity 原生插件指南

使用广告检查器测试自定义事件

广告检查器可用于测试自定义事件是否已正确导入您的应用。广告检查器只用手势即可打开,也可以用最少的代码以编程方式打开。

(可选)从 C# 脚本调用第三方 SDK 原生方法

第三方广告联盟 SDK 可能有特殊要求,需要直接调用 Android 或 iOS 方法。直接调用这些方法的流程如下所示:

  1. 为平台客户端定义通用接口
  2. 为不支持的平台实现默认客户端
  3. 实现用于调用 Android 方法的 Android 客户端
  4. 实现用于调用 iOS 方法的 iOS 客户端
  5. 实现客户端工厂,以有条件地在 iOS 和 Android 客户端之间切换
  6. 定义用于访问所有第三方广告联盟 SDK 功能的 API

下一部分将介绍如何在可在 Android 和 iOS 上调用方法的 C# API 中为名为“AdPub”的虚构广告联盟实现上述步骤:

AndroidiOS
package com.adpub.android;

public class AdPubSdk
{
    public static void setHasUserConsent(boolean hasUserConsent);
}
@interface AdPubSdk : NSObject
+ (void)setHasUserConsent:(BOOL)hasUserConsent;
@end

为平台客户端定义通用接口

创建一个 IAdPubClient 接口,在其中使用一个方法来表示底层的 Android 和 iOS API。

Assets/AdPub/Common/IAdPubClient.cs

namespace AdPub.Common
{
    public interface IAdPubClient
    {
        ///<summary>
        /// Sets a flag indicating if the app has user consent for advertisement.
        ///</summary>
        void SetHasUserConsent(bool hasUserConsent);
    }
}

为不支持的平台定义默认客户端

创建一个 DefaultClient 类,用于实现仅记录方法名称的 IAdPubClient 接口。在 Unity 编辑器中以及除 Android 或 iOS 以外的所有平台上使用此实现。

Assets/AdPub/Common/DefaultClient.cs

namespace AdPub.Common
{
    public class DefaultClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
            Debug.Log("SetHasUserConsent was called.");
        }
    }
}

实现 iOS 平台客户端

创建一个 iOSAdPubClient 类,用于在 iOS 上实现 IAdPubClient 接口。此实现使用 InteropServices 调用 iOS AdPubSdk 类中的 setHasUserConsent() 方法。

Assets/AdPub/Platforms/iOS/iOSAdPubClient.cs

// Wrap this class in a conditional operator to make sure it only runs on iOS.
#if UNITY_IOS

// Reference InteropServices to include the DLLImportAttribute type.
using System.Runtime.InteropServices;

using AdPub.Common;

namespace AdPub.Platforms.Android
{
    public class iOSAdPubClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
            GADUAdPubSetHasUserConsent(hasUserConsent);
        }

        [DllImport("__Internal")]
        internal static extern void GADUAdPubSetHasUserConsent(bool hasUserConsent);
    }
}
#endif

接下来,实现上面定义的 GADUAdPubSetHasUserConsent() 方法。使用 C 方法 GADUAdPubSetHasUserConsent() 创建 AdPubClientBridge.m,以处理来自 Unity 的方法调用,然后调用 AdPubSDK

AdPubClientBridge 是一个 iOS 源文件,必须位于 Plugins/iOS 文件夹中(如 Unity 原生插件指南中所述)。

Assets/AdPub/Plugins/iOS/AdPubClientBridge.m

#import <AdPubSDK/AdPubSDK.h>

void GADUAdPubSetHasUserConsent(BOOL hasUserConsent) {
  [AdPubSDK setHasUserConsent:hasUserConsent];
}

实现 Android 平台客户端

创建一个 AndroidAdPubCient 类,用于在 Android 上实现 IAdPubClient 接口。此实现使用 Android Java 帮助程序类调用 Android 静态方法 setHasUserConsent()

由于 Android Java 帮助程序类仅在 Android 运行时可用,您可以使用 UNITY_ANDROID 编译器指令封装该类(如代码段所示),以防止出现编译错误。或者,您也可以在 Unity 2017.4 及更高版本上使用 Assembly 定义来解决此问题。

Assets/AdPub/Platforms/Android/AndroidAdPubClient.cs

// Wrap this class in a conditional operator to make sure it only runs on Android.
#if UNITY_ANDROID

// Reference the UnityEngine namespace which contains the JNI Helper classes.
using UnityEngine;

using AdPub.Common;

namespace AdPub.Platforms.Android
{
    public class AndroidAdPubClient : IAdPubClient
    {
        public void SetHasUserConsent(bool hasUserConsent)
        {
             // Make a reference to the com.adpub.AdPubSDK.
            AndroidJavaClass adPubSdk = new AndroidJavaClass("com.adpub.AdPubSdk");

            // Call the native setHasUserConsent method of com.adpub.AdPubSDK.
            adPubSdk.CallStatic("setHasUserConsent", hasUserConsent);
        }
    }
}
#endif

创建工厂方法,以返回正确的客户端实现

现在您已针对每个平台实现了客户端,接下来请创建 AdPubClientFactory 类,以根据运行时平台返回 IAdPubClient 接口的正确实现。此类使用编译器指令返回正确的 IAdPubClient 客户端。

Assets/AdPub/Common/AdPubClientFactory.cs

namespace AdPub.Common
{
    public class AdPubClientFactory
    {
        // Return the correct platform client.
        public static IAdPubClient GetClient()
        {
#if   !UNITY_EDITOR && UNITY_ANDROID
            return new AdPub.Platforms.Android.AndroidAdPubClient();
#elif !UNITY_EDITOR && UNITY_IOS
            return new AdPub.Platforms.iOS.iOSAdPubClient();
#else
            // Returned for the Unity Editor and unsupported platforms.
            return new DefaultClient();
#endif
        }
    }
}

为每个接口方法定义一个公共 API

创建一个 AdPubApi 类,该类具有针对 IAdPubClient 接口中的每个客户端方法的方法调用。此类使用 AdPubClientFactory 获取 IAdPubClient 的实例,并调用该客户端以实现底层 SDK 功能。

Assets/AdPub/AdPubApi.cs

using AdPub.Common;

namespace AdPub
{
    public class AdPubApi
    {
        private static readonly IAdPubClient client = GetAdPubClient();

        // Returns the correct client for the current runtime platform.
        private static IAdPubClient GetAdPubClient()
        {
            return AdPubClientFactory.GetClient();
        }

        // Sets the user consent using the underlying SDK functionality.
        public static void SetHasUserConsent(bool hasUserConsent)
        {
            client.SetHasUserConsent(hasUserConsent);
        }
    }
}

调用新定义的 API

调用上面定义的 API 的方法如下:

Assets/Scripts/AdPubController.cs

using UnityEngine;
using AdPub;

public class AdPubController : MonoBehaviour
{
    // TODO: Get consent from the user and update this userConsent field.
    public bool userConsent;

    // Called on startup of the GameObject it's assigned to.
    public void Start()
    {
        // Pass the user consent to AdPub.
        AdPubApi.SetHasUserConsent(userConsent);
    }
}

其他第三方广告联盟适配器示例

如需了解用于实现 C# API 以封装 iOS 和 Android 方法调用的第三方中介适配器的其他示例,请访问 Google 移动广告 Unity 插件 GitHub 库