# カスタムレイアウト広告

カスタムレイアウトはアプリ内部の指定された位置に広告を表示する、最も標準的な広告フォーマットです。 フィード画面やコンテンツ内の好きな位置に掲載可能です。 カスタムレイアウトは複数のフォーマットを統合したフォーマットになっています。

# 広告オブジェクトの準備

カスタムレイアウト広告を表示するには、FiveAdCustomLayoutオブジェクトを作る必要があります。

以下のようなコードでFiveAdCustomLayoutオブジェクトを生成します。 your-slot-idは登録したスロットIDで置きかえてください。

int width = Screen.width;
customLayout = new FiveAdCustomLayout("your-slot-id", width);

カスタムレイアウト広告の広告枠のアスペクト比はサーバ側の設定に保存されています。 そのため、広告オブジェクトには幅のみを渡すようなAPIとなっています。

# 広告のロード

広告を表示するにはロードを行う必要があります。 FiveSDKは広告のロード成功・失敗をFiveAdLoadListenerを通して通知します。 そのため、広告オブジェクトには必ずFiveAdLoadListenerインターフェースを実装したオブジェクトをSetLoadListenerで登録してください。

FiveAdLoadListenerの登録と広告のロードは以下のようにして行います。

customLayout.SetLoadListener(this);
customLayout.LoadAdAsync();

上記のコードでは、thisFiveAdLoadListenerインターフェースを実装しているものとしています。

# 広告の表示

広告がロードされると、登録したFiveAdLoadListenerインターフェースのOnFiveAdLoadメソッドが呼ばれます。 この段階で座標を指定して広告オブジェクトのAddメソッドを呼ぶと、広告が表示されます。

public void OnFiveAdLoad(FiveAdInterface f) {
  // (x, y) は広告を表示する座標
  customLayout.Add(x, y);
}

# ハードウェアアクセラレーションの有効化 (Android限定)

Androidの場合、カスタムレイアウト広告の表示にはハードウェアアクセラレーションの有効化が必要です。 Assets/Editorディレクトリに以下の内容のUnityAndroidManifestSetHardwareAccelerated.csファイルを設置してください。

// Assets/Editor/UnityAndroidManifestSetHardwareAccelerated.cs
/*
MIT License
Copyright (c) 2018 Yury Habets
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
https://github.com/Over17/UnityAndroidManifestCallback
*/

using System.IO;
using System.Text;
using System.Xml;
using UnityEditor.Android;

public class ModifyUnityAndroidAppManifestSample : IPostGenerateGradleAndroidProject
{
    public void OnPostGenerateGradleAndroidProject(string basePath)
    {
        var androidManifest = new AndroidManifest(GetManifestPath(basePath));
        androidManifest.SetHardwareAccelerated(true);
        androidManifest.Save();
    }

    public int callbackOrder { get { return 1; } }

    private string _manifestFilePath;

    private string GetManifestPath(string basePath)
    {
        if (string.IsNullOrEmpty(_manifestFilePath))
        {
            var pathBuilder = new StringBuilder(basePath);
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("src");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("main");
            pathBuilder.Append(Path.DirectorySeparatorChar).Append("AndroidManifest.xml");
            _manifestFilePath = pathBuilder.ToString();
        }
        return _manifestFilePath;
    }
}

internal class AndroidXmlDocument : XmlDocument
{
    private string m_Path;
    protected XmlNamespaceManager nsMgr;
    public readonly string AndroidXmlNamespace = "http://schemas.android.com/apk/res/android";
    public AndroidXmlDocument(string path)
    {
        m_Path = path;
        using (var reader = new XmlTextReader(m_Path))
        {
            reader.Read();
            Load(reader);
        }
        nsMgr = new XmlNamespaceManager(NameTable);
        nsMgr.AddNamespace("android", AndroidXmlNamespace);
    }

    public string Save()
    {
        return SaveAs(m_Path);
    }

    public string SaveAs(string path)
    {
        using (var writer = new XmlTextWriter(path, new UTF8Encoding(false)))
        {
            writer.Formatting = Formatting.Indented;
            Save(writer);
        }
        return path;
    }
}


internal class AndroidManifest : AndroidXmlDocument
{
    private readonly XmlElement ApplicationElement;

    public AndroidManifest(string path) : base(path)
    {
        ApplicationElement = SelectSingleNode("/manifest/application") as XmlElement;
    }

    private XmlAttribute CreateAndroidAttribute(string key, string value)
    {
        XmlAttribute attr = CreateAttribute("android", key, AndroidXmlNamespace);
        attr.Value = value;
        return attr;
    }

    internal XmlNode GetActivityWithLaunchIntent()
    {
        return SelectSingleNode("/manifest/application/activity[intent-filter/action/@android:name='android.intent.action.MAIN' and " +
                "intent-filter/category/@android:name='android.intent.category.LAUNCHER']", nsMgr);
    }

   internal void SetHardwareAccelerated(bool enabled)
   {
        var activity = GetActivityWithLaunchIntent() as XmlElement;
        activity.SetAttribute("android:hardwareAccelerated", (enabled) ? "true" : "false");
   }
}