---
description: Là 1 Plugin dùng để tùy biến hiển thị Ads loại NativeAd của MAX
---

# MAX NativeAd

## 1. Điều kiện sử dụng.

* Trong game cần phải tích hơp Applovin SDK

## 2. Download Plugin

* Download [tại đây](https://gitlab.com/cscmobistudios/gsm-sdk/-/tree/main/Unity/CSCMobiPlugin/MaxNativeAd).

## 3. Sử dụng

### 3.1 Thiết lập thông số.

* Vào **CSCMobiPlugin -> MaxNativeAd -> Prefabs**, kéo prefab **MaxNativeAdSetting** vào Scene đầu game
* Các thông số trong **MaxNativeAdSetting**:
  * **Ad Unit Id**: Là UnitId của Max NativeAd, được cung cấp theo từng game.
  * **Container Count**: Là số lượng các vùng có thể chứa NativeAd khác nhau trong game. Mỗi vùng chứa sẽ có 1 NativeAd. Id của các vùng chứa sẽ tính từ 0 -> Container Count -1;\
    \- Ví dụ: Container Count = 5. Thì sẽ có 5 vùng chứa ads, và ContainterId từ 0->4;\
    \- _Các vùng chứa có id cao sẽ có khả năng đè lên vùng chứa có id thấp._
  * **Show Toast**: là cờ bật tắt để sẽ mục đích debug, kiểm tra xem các lệnh đã được call từ unity vào android native chưa.
  * **Capture Ads Delay Miniseconds**: Là sau khi quảng cáo được hiển thị, thì sẽ delay 1 khoảng thời gian (tính bằng milisecond) quảng cáo đó sẽ được chụp tạo thành 1 ảnh.

### 3.2 Thực thi NativeAd đơn giản

* Trường hợp này không sử dung Pool, để load quảng cáo sẵn
* Sample: Xem Scene `Assets->CSCPlugin->MaxNativeAd->Sample->Scenes->`` `**`Main`**

#### 3.2.1 Tạo class kế thừa từ BaseMaxNativeAd.

```csharp
using CSCMobi.Max.Plugins;

public class MaxNativeAdExample : BaseMaxNativeAd
{

    protected override void Awake()
    {
        base.Awake();
        InitListener();
    }
    void InitListener()
    {
        //Được kích hoạt khi quảng cáo được load thành công
        onNativeAdLoaded = OnNativeAdLoaded; 
        //Được kích hoạt khi load quảng cáo không thành công
        onNativeAdLoadFail = OnNativeAdLoadFail; 
        //Được kích hoạt khi 1 quảng cáo hiển thị quá lâu, bị hết hạn
        onNativeAdExpired = OnNativeAdExpired;
        //Được kích hoạt khi quảng cáo được click
        onNativeAdClicked = OnNativeAdClicked;
        //Được kích hoạt khi nhà quảng cáo trả tiền cho lượt hiển thị
        onAdRevenuePaid = OnAdRevenuePaid;
        //Được kích hoạt khi có bất kì lỗi gì trong quá trình sử dụng NativeAd
        onError = OnError;
    }
    //.......... other coding

 
}
```

<figure><img src="https://2104621774-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgeyYu23aXsOKQRAzehmS%2Fuploads%2FqKEFfuuMwQtmxI4Iw5rw%2Fimage.png?alt=media&#x26;token=116228f6-d75d-4e9b-b88d-0f85c800b894" alt=""><figcaption></figcaption></figure>

* Trong Inspector sẽ có các thuộc tính sau
  * **Auto Init**: Trường hợp muốn load quảng cáo từ Pool thì để bằng False. Ngược lại, muốn tự load quảng cáo thì đặt bằng True.
  * **ContainerId**: là id xác định vùng chứa quảng cáo.
  * **Root Canvas**: Là Canvas gốc của 1 Scene
  * **Ad Template**: Là các mẫu quảng cáo được hiển thị, hiện tại có 3 mẫu:
    * Small: là loại hiển thị như dạng banner (Kích thước tiêu chuẩn 360x180)
    * Small Rectangle: là loại hiển thị dạng 1 media content (150x150)
    * Medium: là loại hiển thị đầu đủ (360x250)
  * **Ad Container**: Là 1 GameObject khung chứa quảng cáo. Trong AdContainer cần có 1 RawImage, để khi quảng cáo hiển thị, sẽ được chụp lại và đưa vào RawImage này.

#### 3.2.2 Load quảng cáo

* Sử dụng method: **LoadAd** để thực hiện yêu cầu quảng cáo từ nền tảng

```csharp
  protected override void Start()
  {
      base.Start();
      //Load quảng cáo
      LoadAd();
  }
```

#### 3.2.3 Hiển thị quảng cáo

* Sử dụng method: **ShowAds** để thực hiện hiển thị quảng cáo lên 1 vùng chứa

```csharp
    protected void OnNativeAdLoaded(int idAds, MaxAd maxAd)
    {
        //Hiện quảng cáo sau khi load thành công
        ShowAds();
    }
```

#### 3.2.4 Ẩn quảng cáo

* Sử dụng method: **HideAds** để thực hiện ẩn một quảng cáo

```csharp
public override void LoadAd()
{
    //Ẩn quảng cáo hiện tại trước khi load một quảng cáo khác
    HideAds();
    base.LoadAd();
}
```

#### 3.2.5 Toàn bộ code mẫu

```csharp
using CSCMobi.Max.Plugins;
using UnityEngine;

public class MaxNativeAdExample : BaseMaxNativeAd
{

    protected override void Awake()
    {
        base.Awake();
        InitListener();
    }
    protected override void Start()
    {
        base.Start();
        //Load quảng cáo
        LoadAd();
    }
    void InitListener()
    {
        onNativeAdLoaded = OnNativeAdLoaded;
        onNativeAdLoadFail = OnNativeAdLoadFail;
        onNativeAdExpired = OnNativeAdExpired;
        onNativeAdClicked = OnNativeAdClicked;
        onAdRevenuePaid = OnAdRevenuePaid;
        onAdsCaptured = OnAdsCaptured;
        onError = OnError;
    }
    public override void LoadAd()
    {
        //Ẩn quảng cáo hiện tại trước khi load một quảng cáo khác
        HideAds();
        base.LoadAd();
    }
    protected void OnNativeAdLoaded(int idAds, MaxAd maxAd)
    {
        //Hiện quảng cáo sau khi load thành công
        ShowAds();
        //Load tiếp quảng cáo sau 30s
        Invoke("LoadAd", 30);
    }
    protected void OnNativeAdLoadFail(int idAds, string error)
    {
        string info = $"OnNativeAdLoadFail Error: {error}";
        Debug.LogWarning(info);
        Invoke("LoadAd", 5);
    }
    protected void OnAdRevenuePaid(int idAds, MaxAd maxAd)
    {
        string info = $"OnAdRevenuePaid Network: {maxAd.getNetworkName()} AdFormat: {maxAd.GetFormat()} Revenue:{maxAd.getRevenue()}";
        Debug.Log(info);
    }

    protected void OnNativeAdClicked(int idAds, MaxAd maxAd)
    {
        string info = $"OnNativeAdClicked";
        Debug.LogWarning(info);
    }

    protected void OnNativeAdExpired(int idAds, MaxAd maxAd)
    {
        //Load quảng cáo mới khi quảng cáo cũ bị hết hạn
        LoadAd();
    }
    protected void OnError(string error)
    {
        Debug.LogError(error);
    }

    protected void OnAdsCaptured(int idAds, string containerBase64)
    {
        //Thực hiện gì đó khi quảng cáo đã được chụp lại thành 1 ảnh base64
    }

 
    protected override void OnBeginMoving()
    {
        //Khi bắt đầu adContainer chuyển động thì ẩn quảng cáo
        HideAds();
    }

    protected override void OnBeginPause()
    {
        //Khi adContainer bắt đầu dừng chuyển động thì hiển thị quảng cáo từ native, để hiển thị lên vùng chứa ad.
        ShowAds();
    }

 
}

```

Settings:

<figure><img src="https://2104621774-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FgeyYu23aXsOKQRAzehmS%2Fuploads%2Fgm6XQyFjcDy4bumhuX2W%2Fimage.png?alt=media&#x26;token=cf2fc122-4120-4422-a29d-2f3e87d03a15" alt=""><figcaption></figcaption></figure>

### 3.3. Cơ chế Pool

* Sử dụng cơ chế pool để có thể load quảng cáo trước, từ lúc bắt đầu vào game, sau đó chỉ việc hiển thị thì giúp giảm độ trễ khi hiển thị quảng cáo
* Sample: Xem Scene `Assets->CSCPlugin->MaxNativeAd->Sample->Scenes->`` `**`TestPool`**

#### 3.3.1 Thiết lập các vị trí quảng cáo.

* Ví dụ trong game có X vị trí có thể hiển thị quảng cáo
* Mỗi vị trí thì sẽ có id được tính từ 0->X-1  , mỗi vị trí sẽ có template quảng cáo tương ứng.

Code mẫu:

* Cần có 1 class quản lý Pool và kế thừa từ class **`MaxNativeAdPoolManager`**
* Thực thi method **GetContainters** (Trả về danh sách các vị trí quảng cáo)

```csharp
using CSCMobi.Max.Plugins;
using System.Collections.Generic;
using TMPro;
using UnityEngine;

public class MaxNativeAdPoolManagerSample : MaxNativeAdPoolManager
{
    static MaxNativeAdPoolManagerSample instance;
    public static MaxNativeAdPoolManagerSample Instance => instance;

    protected override Dictionary<int, MaxNativeAdTemplateType> GetContainters()
    {
        //Thiết lập các vị trí quảng cáo
        Dictionary<int, MaxNativeAdTemplateType> dict = new Dictionary<int, MaxNativeAdTemplateType>();
        dict.Add(0, MaxNativeAdTemplateType.Medium); //Vị trí số 0, template quảng cáo Medium
        dict.Add(1, MaxNativeAdTemplateType.Medium); //Vị trí số 1, template quảng cáo Medium
        return dict;
    }

    protected override void Awake()
    {
        if (instance != null)
        {
            Destroy(gameObject);
        }
        else
        {
            instance = this;
            DontDestroyOnLoad(gameObject);
        }
        base.Awake();

    }
    private void FixedUpdate()
    {
        txtPoolCount.text = $"Pool: {GetAvailableSize()}";
        txtNotAvailableCount.text = $"Queue: {GetQueueSize()}";
        txtUsingCount.text = $"Used: {GetUsedCount()}";
    }
}

```

#### 3.3.2 Hiển thị quảng cáo từ trong Pool

* Mỗi một đối tượng quảng cáo cần kế thừa từ class BaseMaxNativeAd

Code Mẫu:

```csharp
public class MaxNativeAdMedium : BaseMaxNativeAd
{
}
```

#### 3.3.3 Đăng ký và hủy sự kiện có quảng cáo trong pool

* Khi trong Pool thực hiện load quảng cáo thành công thì sẽ kích hoạt OnHasPool

Code mẫu:

```csharp
protected override void Start()
{  
    base.Start();
    RegisterPool();
}
/// <summary>
/// Đăng ký sự kiện khi có quảng cáo trong Pool
/// </summary>
private void RegisterPool()
{
    MaxNativeAdPoolManagerSample.Instance.onHasPool += OnHasPool;
}
/// <summary>
/// Hủy đăng ký sự kiện có quảng cáo trong Pool
/// </summary>
private void UnRegisterPool()
{
    MaxNativeAdPoolManagerSample.Instance.onHasPool -= OnHasPool;
}
private void OnHasPool(int containerId)
{
    if (nativeAd != null) return;
    if (this.containerId == containerId)
    {
        LoadFromPool();
    }

}
private void OnDestroy()
{
    //Khi bị destroy thì ngừng đăng ký nhận pool
    UnRegisterPool();
    
}
```

#### 3.3.4 Load quảng cáo từ trong Pool

* Thực hiện kiểm tra xem trong pool có quảng cáo thì lấy ra và hiển thị

Code mẫu:

```csharp
bool LoadFromPool()
{
    MaxNativeAd newAd = MaxNativeAdPoolManagerSample.Instance.GetMaxNativeAdFromPool(containerId);
    if (newAd != null)
    {
        loadPoolCount++;
        maxController.SendMessageText($"LoadFromPool {loadPoolCount}");
        SetMaxNativeAd(newAd);
        ShowAds();
        return true;
    }
    return false;
}
```

#### 3.3.5 Load mới quảng cáo

* Sau một thời gian hiển thị ví dụ khoảng 30 phút, thì có thể thực hiện load mới quảng cáo
* Nếu pool sẵn có thì sẽ hiển thị được luôn, ngược lại thì phải chờ queue load quảng cáo

Code mẫu:

```csharp
 private void LoadNewAd()
 {
     if (nativeAd != null)
     {
         bool result = MaxNativeAdPoolManagerSample.Instance.AddToQueue(nativeAd);
         if (result)
         {
             HideAds(); //Ẩn bỏ quảng cáo hiện tại trước
             if (!LoadFromPool())
             {
                 nativeAd = null;
             }
         }
     }

 }
```

## 4. Bản chất của Plugin

* Ở unity có 1 GameObject là AdContainer, được xác định trên 1 màn hình
* Plugin sẽ xác định được tọa độ và kích thước thật của AdContainer  trên màn hình
* Sau đó, khi gọi ShowAds, thì AndroidNative sẽ tạo 1 FrameLayout với kích thước tương ứng AdContainer và hiển thị đè lên đúng vị trí của AdContainer, giống như 1 miếng tem dán lên màn hình.
* Chính vì vậy, khi AdContainer di chuyển, thì nên call HideAds() để ẩn nativead, và khi dừng lại thì hiển thi lên

Lưu ý:

* <mark style="color:red;">NativeAd hiển thị không liên quan unity gameObject, vậy nên cần ẩn hiện quảng cáo phù hợp để tránh bị lỗi, quảng cáo cứ hiển thị đè lên các đối tượng trong game</mark>
