概要
ネイティブ広告は、アプリのデザインに合わせて広告UIを自由にカスタマイズできる広告フォーマットです。広告素材(画像、動画)、タイトル、説明、CTAボタンなどの要素を個別に配置して、自然なユーザー体験を提供できます。主な機能
- 完全なUIカスタマイズ:アプリのデザインシステムに合わせて広告レイアウトを自由に構成
- 様々なメディアサポート:画像および動画広告素材サポート
- 柔軟なクリック領域設定:全体クリックまたは個別要素別クリック処理可能
- プロフィール情報表示:広告主プロフィールロゴ、名前、リンクサポート
クラスとインターフェース
AdropNativeAd
ネイティブ広告をロードして管理するメインクラスです。広告ユニットID(コンソールで発行)
コンテキストターゲティング用のID(オプション)
広告イベントを処理するリスナー
カスタムクリック処理の使用有無
主なプロパティ
| プロパティ | タイプ | 説明 |
|---|---|---|
headline | String | 広告タイトル |
body | String | 広告本文 |
icon | String | アイコン画像URL |
cover | String | カバー画像URL |
advertiser | String | 非推奨。 代わりにprofile.displayNameを使用してください。 |
advertiserURL | String | 非推奨。 代わりにprofile.linkを使用してください。 |
accountTag | JSONObject | 非推奨。 サポート終了。 |
creativeTag | JSONObject | 非推奨。 サポート終了。 |
callToAction | String | 行動喚起文言(例:「今すぐ確認」) |
profile | AdropNativeAdProfile | 広告主プロフィール情報 |
isLoaded | Boolean | 広告ロード完了状態 |
isDestroyed | Boolean | 広告削除状態 |
AdropNativeAdView
ネイティブ広告を表示するコンテナビューです。全体領域クリックの有効化有無。
trueに設定すると広告ビュー全体領域でクリックイベントが発生します。主なメソッド
| メソッド | 説明 |
|---|---|
setIconView(view, listener) | アイコン画像ビュー設定(ImageViewタイプ) |
setHeadLineView(view, listener) | タイトルテキストビュー設定(TextViewタイプ) |
setBodyView(view) | 本文テキストビュー設定(TextViewタイプ) |
setMediaView(view) | メディアコンテナビュー設定(AdropMediaViewタイプ) |
setAdvertiserView(view, listener) | 広告主名テキストビュー設定(TextViewタイプ) |
setCallToActionView(view) | CTAボタンまたはテキストビュー設定 |
setProfileLogoView(view, listener) | プロフィールロゴ画像ビュー設定(ImageViewタイプ) |
setProfileNameView(view, listener) | プロフィール名テキストビュー設定(TextViewタイプ) |
setNativeAd(ad) | 広告データをビューにバインド |
destroy() | リソース解放 |
AdropMediaView
広告画像または動画を表示するメディアコンテナビューです。<io.adrop.ads.nativeAd.AdropMediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="200dp" />
動画クリエイティブの場合、必ず
AdropNativeAdView.setMediaView(...)を通じてAdropMediaViewをバインドする必要があります。ad.asset URLを読み取り、独自プレイヤー(ExoPlayer、MediaPlayerまたはサードパーティライブラリ)で直接再生すると、SDKの動画トラッキングパイプラインを経由しなくなり、VTRが計測されず、onAdVideoStart / onAdVideoEndコールバックも呼び出されません。動画トラッキングとVTRセクションを参照してください。AdropNativeAdListener
広告イベントを処理するインターフェースです。interface AdropNativeAdListener {
fun onAdReceived(ad: AdropNativeAd)
fun onAdClicked(ad: AdropNativeAd)
fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode)
fun onAdImpression(ad: AdropNativeAd) // オプション実装
fun onAdVideoStart(ad: AdropNativeAd) // オプション実装
fun onAdVideoEnd(ad: AdropNativeAd) // オプション実装
}
AdropNativeAdProfile
広告主プロフィール情報を含むデータクラスです。| プロパティ | タイプ | 説明 |
|---|---|---|
displayLogo | String | プロフィールロゴ画像URL |
displayName | String | プロフィール表示名 |
link | String | プロフィールリンクURL |
実装ガイド
1. XMLレイアウト設定
ネイティブ広告を表示するレイアウトを定義します。AdropNativeAdViewをルートとして、内部に広告要素を配置します。
res/layout/native_ad_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<io.adrop.ads.nativeAd.AdropNativeAdView
android:id="@+id/native_ad_view"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp">
<!-- プロフィール領域 -->
<ImageView
android:id="@+id/ad_profile_logo"
android:layout_width="48dp"
android:layout_height="48dp"
android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ad_profile_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintStart_toEndOf="@id/ad_profile_logo"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/ad_badge"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="4dp"
android:text="広告"
android:textSize="12sp"
app:layout_constraintStart_toEndOf="@id/ad_profile_logo"
app:layout_constraintTop_toBottomOf="@id/ad_profile_name" />
<!-- メディア領域 -->
<io.adrop.ads.nativeAd.AdropMediaView
android:id="@+id/ad_media"
android:layout_width="match_parent"
android:layout_height="200dp"
android:layout_marginTop="12dp"
app:layout_constraintTop_toBottomOf="@id/ad_profile_logo" />
<!-- 広告コンテンツ -->
<TextView
android:id="@+id/ad_headline"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textSize="18sp"
android:textStyle="bold"
app:layout_constraintTop_toBottomOf="@id/ad_media" />
<TextView
android:id="@+id/ad_body"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textSize="14sp"
app:layout_constraintTop_toBottomOf="@id/ad_headline" />
<!-- 下部領域 -->
<TextView
android:id="@+id/ad_advertiser"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:textSize="14sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/ad_body" />
<Button
android:id="@+id/ad_call_to_action"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@id/ad_body" />
</androidx.constraintlayout.widget.ConstraintLayout>
</io.adrop.ads.nativeAd.AdropNativeAdView>
2. 広告のロードと表示(Kotlin)
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import io.adrop.ads.model.AdropErrorCode
import io.adrop.ads.nativeAd.AdropMediaView
import io.adrop.ads.nativeAd.AdropNativeAd
import io.adrop.ads.nativeAd.AdropNativeAdListener
import io.adrop.ads.nativeAd.AdropNativeAdView
class NativeAdActivity : AppCompatActivity() {
private lateinit var nativeAd: AdropNativeAd
private lateinit var nativeAdView: AdropNativeAdView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_native_ad)
nativeAdView = findViewById(R.id.native_ad_view)
loadNativeAd()
}
private fun loadNativeAd() {
// 1. ネイティブ広告インスタンス作成
nativeAd = AdropNativeAd(
context = this,
unitId = "YOUR_UNIT_ID" // 実際のユニットIDに置き換え
)
// 2. リスナー設定
nativeAd.listener = object : AdropNativeAdListener {
override fun onAdReceived(ad: AdropNativeAd) {
Log.d("Adrop", "広告受信成功")
populateNativeAdView(ad)
}
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
Log.e("Adrop", "広告受信失敗:$errorCode")
}
override fun onAdClicked(ad: AdropNativeAd) {
Log.d("Adrop", "広告クリック")
}
override fun onAdImpression(ad: AdropNativeAd) {
Log.d("Adrop", "広告インプレッション")
}
override fun onAdVideoStart(ad: AdropNativeAd) {
Log.d("Adrop", "広告動画再生開始")
}
override fun onAdVideoEnd(ad: AdropNativeAd) {
Log.d("Adrop", "広告動画再生終了")
}
}
// 3. 広告ロード
nativeAd.load()
}
private fun populateNativeAdView(ad: AdropNativeAd) {
// プロフィール設定
val profileLogoView = findViewById<ImageView>(R.id.ad_profile_logo)
Glide.with(this).load(ad.profile.displayLogo).into(profileLogoView)
nativeAdView.setProfileLogoView(profileLogoView)
val profileNameView = findViewById<TextView>(R.id.ad_profile_name)
profileNameView.text = ad.profile.displayName
nativeAdView.setProfileNameView(profileNameView)
// タイトル設定
val headlineView = findViewById<TextView>(R.id.ad_headline)
headlineView.text = ad.headline
nativeAdView.setHeadLineView(headlineView)
// メディア設定
val mediaView = findViewById<AdropMediaView>(R.id.ad_media)
nativeAdView.setMediaView(mediaView)
// 本文設定
val bodyView = findViewById<TextView>(R.id.ad_body)
bodyView.text = ad.body
nativeAdView.setBodyView(bodyView)
// 広告主設定
val advertiserView = findViewById<TextView>(R.id.ad_advertiser)
advertiserView.text = ad.profile.displayName
nativeAdView.setAdvertiserView(advertiserView)
// CTAボタン設定
val ctaView = findViewById<Button>(R.id.ad_call_to_action)
ctaView.text = ad.callToAction
nativeAdView.setCallToActionView(ctaView)
// 広告データバインド
nativeAdView.setNativeAd(ad)
}
override fun onDestroy() {
// リソース解放
nativeAdView.destroy()
nativeAd.destroy()
super.onDestroy()
}
}
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.bumptech.glide.Glide
import io.adrop.ads.model.AdropErrorCode
import io.adrop.ads.nativeAd.AdropMediaView
import io.adrop.ads.nativeAd.AdropNativeAd
import io.adrop.ads.nativeAd.AdropNativeAdListener
import io.adrop.ads.nativeAd.AdropNativeAdView
class NativeAdFragment : Fragment() {
private var nativeAd: AdropNativeAd? = null
private var nativeAdView: AdropNativeAdView? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return inflater.inflate(R.layout.fragment_native_ad, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
nativeAdView = view.findViewById(R.id.native_ad_view)
loadNativeAd()
}
private fun loadNativeAd() {
nativeAd = AdropNativeAd(
context = requireContext(),
unitId = "YOUR_UNIT_ID"
)
nativeAd?.listener = object : AdropNativeAdListener {
override fun onAdReceived(ad: AdropNativeAd) {
populateNativeAdView(ad)
}
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
Log.e("Adrop", "広告ロード失敗:$errorCode")
}
override fun onAdClicked(ad: AdropNativeAd) {
Log.d("Adrop", "広告クリック")
}
}
nativeAd?.load()
}
private fun populateNativeAdView(ad: AdropNativeAd) {
val view = requireView()
// プロフィールロゴ
val profileLogo = view.findViewById<ImageView>(R.id.ad_profile_logo)
Glide.with(this).load(ad.profile.displayLogo).into(profileLogo)
nativeAdView?.setProfileLogoView(profileLogo)
// プロフィール名
val profileName = view.findViewById<TextView>(R.id.ad_profile_name)
profileName.text = ad.profile.displayName
nativeAdView?.setProfileNameView(profileName)
// タイトル
val headline = view.findViewById<TextView>(R.id.ad_headline)
headline.text = ad.headline
nativeAdView?.setHeadLineView(headline)
// メディア
val media = view.findViewById<AdropMediaView>(R.id.ad_media)
nativeAdView?.setMediaView(media)
// 本文
val body = view.findViewById<TextView>(R.id.ad_body)
body.text = ad.body
nativeAdView?.setBodyView(body)
// 広告主
val advertiser = view.findViewById<TextView>(R.id.ad_advertiser)
advertiser.text = ad.profile.displayName
nativeAdView?.setAdvertiserView(advertiser)
// CTA
val cta = view.findViewById<Button>(R.id.ad_call_to_action)
cta.text = ad.callToAction
nativeAdView?.setCallToActionView(cta)
// バインド
nativeAdView?.setNativeAd(ad)
}
override fun onDestroyView() {
nativeAdView?.destroy()
nativeAd?.destroy()
super.onDestroyView()
}
}
3. 広告のロードと表示(Java)
Java
import android.os.Bundle;
import android.util.Log;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import io.adrop.ads.model.AdropErrorCode;
import io.adrop.ads.nativeAd.AdropMediaView;
import io.adrop.ads.nativeAd.AdropNativeAd;
import io.adrop.ads.nativeAd.AdropNativeAdListener;
import io.adrop.ads.nativeAd.AdropNativeAdView;
public class NativeAdActivity extends AppCompatActivity {
private AdropNativeAd nativeAd;
private AdropNativeAdView nativeAdView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_native_ad);
nativeAdView = findViewById(R.id.native_ad_view);
loadNativeAd();
}
private void loadNativeAd() {
// 1. ネイティブ広告インスタンス作成
nativeAd = new AdropNativeAd(
this,
"YOUR_UNIT_ID", // 実際のユニットIDに置き換え
null // contextId(オプション)
);
// 2. リスナー設定
nativeAd.setListener(new AdropNativeAdListener() {
@Override
public void onAdReceived(AdropNativeAd ad) {
Log.d("Adrop", "広告受信成功");
populateNativeAdView(ad);
}
@Override
public void onAdFailedToReceive(AdropNativeAd ad, AdropErrorCode errorCode) {
Log.e("Adrop", "広告受信失敗:" + errorCode);
}
@Override
public void onAdClicked(AdropNativeAd ad) {
Log.d("Adrop", "広告クリック");
}
@Override
public void onAdImpression(AdropNativeAd ad) {
Log.d("Adrop", "広告インプレッション");
}
@Override
public void onAdVideoStart(AdropNativeAd ad) {
Log.d("Adrop", "広告動画再生開始");
}
@Override
public void onAdVideoEnd(AdropNativeAd ad) {
Log.d("Adrop", "広告動画再生終了");
}
});
// 3. 広告ロード
nativeAd.load();
}
private void populateNativeAdView(AdropNativeAd ad) {
// プロフィールロゴ設定
ImageView profileLogoView = findViewById(R.id.ad_profile_logo);
Glide.with(this).load(ad.getProfile().getDisplayLogo()).into(profileLogoView);
nativeAdView.setProfileLogoView(profileLogoView, null);
// プロフィール名設定
TextView profileNameView = findViewById(R.id.ad_profile_name);
profileNameView.setText(ad.getProfile().getDisplayName());
nativeAdView.setProfileNameView(profileNameView, null);
// タイトル設定
TextView headlineView = findViewById(R.id.ad_headline);
headlineView.setText(ad.getHeadline());
nativeAdView.setHeadLineView(headlineView, null);
// メディア設定
AdropMediaView mediaView = findViewById(R.id.ad_media);
nativeAdView.setMediaView(mediaView);
// 本文設定
TextView bodyView = findViewById(R.id.ad_body);
bodyView.setText(ad.getBody());
nativeAdView.setBodyView(bodyView);
// 広告主設定
TextView advertiserView = findViewById(R.id.ad_advertiser);
advertiserView.setText(ad.getProfile().getDisplayName());
nativeAdView.setAdvertiserView(advertiserView, null);
// CTAボタン設定
Button ctaView = findViewById(R.id.ad_call_to_action);
ctaView.setText(ad.getCallToAction());
nativeAdView.setCallToActionView(ctaView);
// 広告データバインド
nativeAdView.setNativeAd(ad);
}
@Override
protected void onDestroy() {
// リソース解放
if (nativeAdView != null) {
nativeAdView.destroy();
}
if (nativeAd != null) {
nativeAd.destroy();
}
super.onDestroy();
}
}
高度な機能
全体クリック領域設定
広告ビュー全体領域でクリックイベントが発生するよう設定できます。nativeAdView.isEntireClick = true
nativeAdView.setEntireClick(true);
isEntireClickをtrueに設定すると広告ビュー全体がクリック可能な領域になります。個別要素のクリックリスナーは動作しません。個別要素クリックリスナー
特定の広告要素にカスタムクリックリスナーを設定できます。// 広告主クリック時のカスタム動作
nativeAdView.setAdvertiserView(advertiserView) {
Log.d("Adrop", "広告主クリック")
// カスタム動作実装
}
// プロフィールロゴクリック時のカスタム動作
nativeAdView.setProfileLogoView(profileLogoView) {
Log.d("Adrop", "プロフィールロゴクリック")
// カスタム動作実装
}
// 広告主クリック時のカスタム動作
nativeAdView.setAdvertiserView(advertiserView, new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Adrop", "広告主クリック");
// カスタム動作実装
}
});
// プロフィールロゴクリック時のカスタム動作
nativeAdView.setProfileLogoView(profileLogoView, new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.d("Adrop", "プロフィールロゴクリック");
// カスタム動作実装
}
});
コンテキストターゲティング
特定のコンテキストに合った広告をリクエストできます。val nativeAd = AdropNativeAd(
context = this,
unitId = "YOUR_UNIT_ID",
contextId = "SPORTS_NEWS" // コンテキストID
)
AdropNativeAd nativeAd = new AdropNativeAd(
this,
"YOUR_UNIT_ID",
"SPORTS_NEWS" // コンテキストID
);
RecyclerViewでの使用
RecyclerViewのアイテムとしてネイティブ広告を表示できます。RecyclerView Adapter
class ContentAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
companion object {
const val VIEW_TYPE_CONTENT = 0
const val VIEW_TYPE_AD = 1
const val AD_INTERVAL = 5 // 5アイテムごとに広告表示
}
private val items = mutableListOf<Any>()
private val nativeAds = mutableMapOf<Int, AdropNativeAd>()
override fun getItemViewType(position: Int): Int {
return if (position % (AD_INTERVAL + 1) == AD_INTERVAL) {
VIEW_TYPE_AD
} else {
VIEW_TYPE_CONTENT
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
return when (viewType) {
VIEW_TYPE_AD -> {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_native_ad, parent, false)
NativeAdViewHolder(view)
}
else -> {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_content, parent, false)
ContentViewHolder(view)
}
}
}
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
when (holder) {
is NativeAdViewHolder -> loadNativeAd(holder, position)
is ContentViewHolder -> holder.bind(items[position])
}
}
private fun loadNativeAd(holder: NativeAdViewHolder, position: Int) {
// 既にロードした広告があれば再利用
nativeAds[position]?.let { ad ->
if (ad.isLoaded) {
holder.bind(ad)
return
}
}
// 新しい広告をロード
val nativeAd = AdropNativeAd(holder.itemView.context, "YOUR_UNIT_ID")
nativeAd.listener = object : AdropNativeAdListener {
override fun onAdReceived(ad: AdropNativeAd) {
nativeAds[position] = ad
holder.bind(ad)
}
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
Log.e("Adrop", "広告ロード失敗:$errorCode")
}
override fun onAdClicked(ad: AdropNativeAd) {
Log.d("Adrop", "広告クリック")
}
}
nativeAd.load()
}
class NativeAdViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
private val nativeAdView: AdropNativeAdView = itemView.findViewById(R.id.native_ad_view)
fun bind(ad: AdropNativeAd) {
val profileLogo = itemView.findViewById<ImageView>(R.id.ad_profile_logo)
Glide.with(itemView.context).load(ad.profile.displayLogo).into(profileLogo)
nativeAdView.setProfileLogoView(profileLogo)
val profileName = itemView.findViewById<TextView>(R.id.ad_profile_name)
profileName.text = ad.profile.displayName
nativeAdView.setProfileNameView(profileName)
val headline = itemView.findViewById<TextView>(R.id.ad_headline)
headline.text = ad.headline
nativeAdView.setHeadLineView(headline)
val media = itemView.findViewById<AdropMediaView>(R.id.ad_media)
nativeAdView.setMediaView(media)
val body = itemView.findViewById<TextView>(R.id.ad_body)
body.text = ad.body
nativeAdView.setBodyView(body)
val advertiser = itemView.findViewById<TextView>(R.id.ad_advertiser)
advertiser.text = ad.profile.displayName
nativeAdView.setAdvertiserView(advertiser)
val cta = itemView.findViewById<Button>(R.id.ad_call_to_action)
cta.text = ad.callToAction
nativeAdView.setCallToActionView(cta)
nativeAdView.setNativeAd(ad)
}
}
fun destroy() {
nativeAds.values.forEach { it.destroy() }
nativeAds.clear()
}
}
テストユニットID
開発およびテスト時に以下のテストユニットIDを使用してください。| フォーマット | テストユニットID |
|---|---|
| ネイティブ(画像) | PUBLIC_TEST_UNIT_ID_NATIVE |
| ネイティブ動画(16:9) | PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_16_9 |
| ネイティブ動画(9:16) | PUBLIC_TEST_UNIT_ID_NATIVE_VIDEO_9_16 |
本番リリース前に必ず実際のユニットIDに置き換えてください。
ライフサイクル管理
Activity/Fragmentでのリソース解放
ネイティブ広告はメモリリークを防ぐために使用終了後に必ず解放する必要があります。override fun onDestroy() {
nativeAdView.destroy()
nativeAd.destroy()
super.onDestroy()
}
override fun onDestroyView() {
nativeAdView?.destroy()
nativeAd?.destroy()
super.onDestroyView()
}
@Override
protected void onDestroy() {
if (nativeAdView != null) {
nativeAdView.destroy();
}
if (nativeAd != null) {
nativeAd.destroy();
}
super.onDestroy();
}
RecyclerViewでのリソース解放
RecyclerView Adapterで広告を使用する場合、ActivityやFragmentが終了する時にすべての広告を解放する必要があります。override fun onDestroy() {
adapter.destroy()
super.onDestroy()
}
動画トラッキングとVTR
Adropはネイティブ広告の動画指標 — VTR(動画完了率)、onAdVideoStart、onAdVideoEnd — を、SDKメディアコンテナ(AdropNativeAdView.setMediaView(...)でバインドされたAdropMediaView)内で動画がレンダリングされる場合にのみ収集します。
AdropNativeAd.assetプロパティは元の画像または動画ファイルのURLを返します。これはサムネイル表示や媒体社独自分析などの補助メタデータとして公開されており、再生を直接行うためのものではありません。
動画ネイティブ広告の
asset URLを独自の動画プレイヤー(ExoPlayer、MediaPlayerまたはサードパーティプレイヤー)に直接渡さないでください。SDKメディアコンテナを経由しないと以下の現象が発生します。- 該当面でVTR(動画完了率)が収集されません。
onAdVideoStart/onAdVideoEndコールバックが呼び出されません。- 該当ユニットの動画パフォーマンス集計が欠落または0として報告されます。
onAdClicked)とインプレッション(onAdImpression)トラッキングはコンテナビューに接続されているため引き続き動作しますが、動画関連シグナルは失われます。推奨パターン
動画ネイティブ広告には必ずSDKメディアコンテナをバインドしてください。val mediaView = findViewById<AdropMediaView>(R.id.ad_media)
nativeAdView.setMediaView(mediaView) // 動画トラッキングのため必須
nativeAdView.setNativeAd(ad)
AdropMediaView mediaView = findViewById(R.id.ad_media);
nativeAdView.setMediaView(mediaView); // 動画トラッキングのため必須
nativeAdView.setNativeAd(ad);
特定の面がどうしても独自プレイヤーを使う必要があり、VTRが計測されないことを許容する場合、広告を
AdropNativeAdViewにバインドしたままにすることで、クリックとインプレッションのアトリビューションは引き続き確保できます。ただしその面を社内レポートで非VTRインベントリとして分類し、SDKが計測した動画パフォーマンスと混在させないでください。ベストプラクティス
1. 必要な要素のみ表示
すべての広告要素を表示する必要はありません。アプリのデザインに合わせて必要な要素のみ選択的に使用してください。// 最小構成例(メディア + CTAのみ使用)
nativeAdView.setMediaView(mediaView)
nativeAdView.setCallToActionView(ctaView)
nativeAdView.setNativeAd(ad)
2. 画像ロードライブラリの使用
アイコン、カバー、プロフィール画像を表示する際はGlide、Coilなどの画像ロードライブラリを使用してください。// Glide使用例
Glide.with(context)
.load(ad.icon)
.placeholder(R.drawable.placeholder)
.error(R.drawable.error)
.into(iconView)
3. 広告ビューの再利用
RecyclerViewで広告を表示する際は広告インスタンスをキャッシュして再利用してください。4. 適切な広告配置
ユーザー体験を損なわない範囲で自然に広告を配置してください。- コンテンツフィード:5〜10アイテムごとに1つの広告
- 詳細画面:コンテンツ下部に配置
- スクロールビュー:自然なコンテンツフローに合わせて配置
5. エラー処理
広告ロード失敗に備えて適切なフォールバック処理を実装してください。override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
when (errorCode) {
AdropErrorCode.ERROR_CODE_AD_NO_FILL -> {
// 広告なし - 広告領域を非表示
nativeAdView.visibility = View.GONE
}
AdropErrorCode.ERROR_CODE_NETWORK -> {
// ネットワークエラー - リトライロジック
Handler(Looper.getMainLooper()).postDelayed({
nativeAd.load()
}, 3000)
}
else -> {
Log.e("Adrop", "広告ロード失敗:$errorCode")
}
}
}
完全な例
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.ImageView
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.bumptech.glide.Glide
import io.adrop.ads.model.AdropErrorCode
import io.adrop.ads.nativeAd.AdropMediaView
import io.adrop.ads.nativeAd.AdropNativeAd
import io.adrop.ads.nativeAd.AdropNativeAdListener
import io.adrop.ads.nativeAd.AdropNativeAdView
class NativeAdExampleActivity : AppCompatActivity() {
private lateinit var nativeAd: AdropNativeAd
private lateinit var nativeAdView: AdropNativeAdView
private lateinit var loadingView: View
private lateinit var errorView: View
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_native_ad_example)
nativeAdView = findViewById(R.id.native_ad_view)
loadingView = findViewById(R.id.loading_view)
errorView = findViewById(R.id.error_view)
findViewById<Button>(R.id.retry_button).setOnClickListener {
loadNativeAd()
}
loadNativeAd()
}
private fun loadNativeAd() {
showLoading()
nativeAd = AdropNativeAd(
context = this,
unitId = "PUBLIC_TEST_UNIT_ID_NATIVE"
)
nativeAd.listener = object : AdropNativeAdListener {
override fun onAdReceived(ad: AdropNativeAd) {
Log.d("Adrop", "広告受信:unitId=${ad.unitId}, txId=${ad.txId}")
populateNativeAdView(ad)
showAd()
}
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
Log.e("Adrop", "広告受信失敗:$errorCode")
showError()
}
override fun onAdClicked(ad: AdropNativeAd) {
Log.d("Adrop", "広告クリック:txId=${ad.txId}")
}
override fun onAdImpression(ad: AdropNativeAd) {
Log.d("Adrop", "広告インプレッション:txId=${ad.txId}")
}
}
nativeAd.load()
}
private fun populateNativeAdView(ad: AdropNativeAd) {
// 全体クリック領域を有効化(オプション)
// nativeAdView.isEntireClick = true
// プロフィールロゴ
val profileLogoView = findViewById<ImageView>(R.id.ad_profile_logo)
Glide.with(this)
.load(ad.profile.displayLogo)
.circleCrop()
.into(profileLogoView)
nativeAdView.setProfileLogoView(profileLogoView)
// プロフィール名
val profileNameView = findViewById<TextView>(R.id.ad_profile_name)
profileNameView.text = ad.profile.displayName
nativeAdView.setProfileNameView(profileNameView)
// タイトル
val headlineView = findViewById<TextView>(R.id.ad_headline)
headlineView.text = ad.headline
nativeAdView.setHeadLineView(headlineView)
// メディア(画像または動画)
val mediaView = findViewById<AdropMediaView>(R.id.ad_media)
nativeAdView.setMediaView(mediaView)
// 本文
val bodyView = findViewById<TextView>(R.id.ad_body)
bodyView.text = ad.body
nativeAdView.setBodyView(bodyView)
// 広告主
val advertiserView = findViewById<TextView>(R.id.ad_advertiser)
advertiserView.text = ad.profile.displayName
nativeAdView.setAdvertiserView(advertiserView) {
Log.d("Adrop", "広告主クリック:${ad.profile.displayName}")
}
// CTAボタン
val ctaView = findViewById<Button>(R.id.ad_call_to_action)
ctaView.text = ad.callToAction
nativeAdView.setCallToActionView(ctaView)
// 広告データバインド
nativeAdView.setNativeAd(ad)
}
private fun showLoading() {
loadingView.visibility = View.VISIBLE
nativeAdView.visibility = View.GONE
errorView.visibility = View.GONE
}
private fun showAd() {
loadingView.visibility = View.GONE
nativeAdView.visibility = View.VISIBLE
errorView.visibility = View.GONE
}
private fun showError() {
loadingView.visibility = View.GONE
nativeAdView.visibility = View.GONE
errorView.visibility = View.VISIBLE
}
override fun onDestroy() {
nativeAdView.destroy()
nativeAd.destroy()
super.onDestroy()
}
}
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.bumptech.glide.Glide;
import io.adrop.ads.model.AdropErrorCode;
import io.adrop.ads.nativeAd.AdropMediaView;
import io.adrop.ads.nativeAd.AdropNativeAd;
import io.adrop.ads.nativeAd.AdropNativeAdListener;
import io.adrop.ads.nativeAd.AdropNativeAdView;
public class NativeAdExampleActivity extends AppCompatActivity {
private AdropNativeAd nativeAd;
private AdropNativeAdView nativeAdView;
private View loadingView;
private View errorView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_native_ad_example);
nativeAdView = findViewById(R.id.native_ad_view);
loadingView = findViewById(R.id.loading_view);
errorView = findViewById(R.id.error_view);
findViewById(R.id.retry_button).setOnClickListener(v -> loadNativeAd());
loadNativeAd();
}
private void loadNativeAd() {
showLoading();
nativeAd = new AdropNativeAd(
this,
"PUBLIC_TEST_UNIT_ID_NATIVE",
null
);
nativeAd.setListener(new AdropNativeAdListener() {
@Override
public void onAdReceived(AdropNativeAd ad) {
Log.d("Adrop", "広告受信:unitId=" + ad.getUnitId() + ", txId=" + ad.getTxId());
populateNativeAdView(ad);
showAd();
}
@Override
public void onAdFailedToReceive(AdropNativeAd ad, AdropErrorCode errorCode) {
Log.e("Adrop", "広告受信失敗:" + errorCode);
showError();
}
@Override
public void onAdClicked(AdropNativeAd ad) {
Log.d("Adrop", "広告クリック:txId=" + ad.getTxId());
}
@Override
public void onAdImpression(AdropNativeAd ad) {
Log.d("Adrop", "広告インプレッション:txId=" + ad.getTxId());
}
});
nativeAd.load();
}
private void populateNativeAdView(AdropNativeAd ad) {
// プロフィールロゴ
ImageView profileLogoView = findViewById(R.id.ad_profile_logo);
Glide.with(this)
.load(ad.getProfile().getDisplayLogo())
.circleCrop()
.into(profileLogoView);
nativeAdView.setProfileLogoView(profileLogoView, null);
// プロフィール名
TextView profileNameView = findViewById(R.id.ad_profile_name);
profileNameView.setText(ad.getProfile().getDisplayName());
nativeAdView.setProfileNameView(profileNameView, null);
// タイトル
TextView headlineView = findViewById(R.id.ad_headline);
headlineView.setText(ad.getHeadline());
nativeAdView.setHeadLineView(headlineView, null);
// メディア
AdropMediaView mediaView = findViewById(R.id.ad_media);
nativeAdView.setMediaView(mediaView);
// 本文
TextView bodyView = findViewById(R.id.ad_body);
bodyView.setText(ad.getBody());
nativeAdView.setBodyView(bodyView);
// 広告主
TextView advertiserView = findViewById(R.id.ad_advertiser);
advertiserView.setText(ad.getProfile().getDisplayName());
nativeAdView.setAdvertiserView(advertiserView, v -> {
Log.d("Adrop", "広告主クリック:" + ad.getProfile().getDisplayName());
});
// CTAボタン
Button ctaView = findViewById(R.id.ad_call_to_action);
ctaView.setText(ad.getCallToAction());
nativeAdView.setCallToActionView(ctaView);
// 広告データバインド
nativeAdView.setNativeAd(ad);
}
private void showLoading() {
loadingView.setVisibility(View.VISIBLE);
nativeAdView.setVisibility(View.GONE);
errorView.setVisibility(View.GONE);
}
private void showAd() {
loadingView.setVisibility(View.GONE);
nativeAdView.setVisibility(View.VISIBLE);
errorView.setVisibility(View.GONE);
}
private void showError() {
loadingView.setVisibility(View.GONE);
nativeAdView.setVisibility(View.GONE);
errorView.setVisibility(View.VISIBLE);
}
@Override
protected void onDestroy() {
if (nativeAdView != null) {
nativeAdView.destroy();
}
if (nativeAd != null) {
nativeAd.destroy();
}
super.onDestroy();
}
}
一括ロード (loads)
AdropNativeAd.loads()を使用すると、1回の呼び出しで複数のネイティブ広告をまとめてリクエストできます。フィード・カルーセル・ページネーションリストへ挿入する広告プールのプリフェッチに有用です。
シグネチャ
AdropNativeAd.loads(
context: Context,
unitId: String,
contextId: String? = null,
listener: AdropNativeAdListener,
)
AdropNativeAd.loads(context, "YOUR_UNIT_ID", null, listener);
使用方法
AdropNativeAd.loads(
context = this,
unitId = "YOUR_UNIT_ID",
contextId = null,
listener = object : AdropNativeAdListener {
// バッチ成功 — 各広告はレンダリング完了状態で渡されます。
override fun onAdsReceived(ads: List<AdropNativeAd>) {
ads.forEach { ad ->
// AdropNativeAdViewへバインドするか、ライフサイクル用に保持
bindToView(ad)
}
}
// バッチ失敗
override fun onAdsFailedToReceive(errorCode: AdropErrorCode) {
Log.e("Adrop", "バッチロード失敗: $errorCode")
}
// 単体用コールバックはloads経路では呼ばれません。
override fun onAdReceived(ad: AdropNativeAd) { /* batch path */ }
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {}
// クリック/インプレッション/動画コールバックは各インスタンスで通常通り呼ばれます。
override fun onAdClicked(ad: AdropNativeAd) {
Log.d("Adrop", "ネイティブクリック: ${ad.creativeId}")
}
override fun onAdImpression(ad: AdropNativeAd) {
Log.d("Adrop", "ネイティブインプレッション: ${ad.creativeId}")
}
},
)
AdropNativeAd.loads(this, "YOUR_UNIT_ID", null, new AdropNativeAdListener() {
@Override
public void onAdsReceived(@NotNull List<AdropNativeAd> ads) {
for (AdropNativeAd ad : ads) {
bindToView(ad);
}
}
@Override
public void onAdsFailedToReceive(@NotNull AdropErrorCode errorCode) {
Log.e("Adrop", "バッチロード失敗: " + errorCode);
}
@Override
public void onAdReceived(@NotNull AdropNativeAd ad) { }
@Override
public void onAdFailedToReceive(@NotNull AdropNativeAd ad, @NotNull AdropErrorCode errorCode) { }
@Override
public void onAdClicked(@NotNull AdropNativeAd ad) {
Log.d("Adrop", "ネイティブクリック: " + ad.getCreativeId());
}
@Override
public void onAdImpression(@NotNull AdropNativeAd ad) {
Log.d("Adrop", "ネイティブインプレッション: " + ad.getCreativeId());
}
});
リスナーコールバック
| コールバック | 呼び出されるタイミング |
|---|---|
onAdsReceived(ads) | バッチ配信完了。すべての広告が完全にレンダリングされた状態で渡されます。 |
onAdsFailedToReceive(errorCode) | リクエスト拒否、ネットワーク失敗、または表示可能な広告がなかった場合 (ERROR_CODE_AD_NO_FILL)。 |
onAdClicked / onAdImpression / onAdVideoStart / onAdVideoEnd | 単体load()と同様に、各広告ごとに呼ばれます。 |
単体
onAdReceived / onAdFailedToReceiveコールバックはloads()経路では呼ばれません。バッチ結果は必ずonAdsReceived / onAdsFailedToReceiveで受け取ってください。制約事項
- 呼び出しあたり最大5個。 サーバーがそれ以上を返しても先頭の5個のみ配信されます。
- バックフィルは適用されません。 ダイレクト広告が埋まらない場合、バックフィル設定に関わらず
onAdsFailedToReceiveがERROR_CODE_AD_NO_FILLで呼ばれます。 onAdsReceived内でdestroy()を呼ばないでください。 各広告をAdropNativeAdView.setNativeAd(...)でバインドするか、ライフサイクル用に保持し、親Activity.onDestroy()(または同等のタイミング)でdestroy()してください。AdropBanner.loads()と異なり、ネイティブバッチはすべての広告のレンダリングが完了するまで待機してからonAdsReceivedを呼びます。配信時点で各インスタンスは完全にレンダリングされています。
バックフィル広告
バックフィル広告が有効な場合、ダイレクト広告がない時に自動的にバックフィル広告がロードされます。isBackfilledプロパティでバックフィル広告かどうかを確認できます。
nativeAd.listener = object : AdropNativeAdListener {
override fun onAdReceived(ad: AdropNativeAd) {
if (ad.isBackfilled) {
println("バックフィル広告がロードされました")
} else {
println("ダイレクト広告がロードされました")
}
}
override fun onAdFailedToReceive(ad: AdropNativeAd, errorCode: AdropErrorCode) {
when (errorCode) {
AdropErrorCode.ERROR_CODE_AD_NO_FILL -> {
println("ダイレクト広告なし、バックフィル広告をリクエスト中...")
}
AdropErrorCode.ERROR_CODE_AD_BACKFILL_NO_FILL -> {
println("バックフィル広告も利用不可")
}
else -> {
println("広告ロード失敗: $errorCode")
}
}
}
}
nativeAd.setListener(new AdropNativeAdListener() {
@Override
public void onAdReceived(AdropNativeAd ad) {
if (ad.isBackfilled()) {
System.out.println("バックフィル広告がロードされました");
} else {
System.out.println("ダイレクト広告がロードされました");
}
}
@Override
public void onAdFailedToReceive(AdropNativeAd ad, AdropErrorCode errorCode) {
if (errorCode == AdropErrorCode.ERROR_CODE_AD_NO_FILL) {
System.out.println("ダイレクト広告なし、バックフィル広告をリクエスト中...");
} else if (errorCode == AdropErrorCode.ERROR_CODE_AD_BACKFILL_NO_FILL) {
System.out.println("バックフィル広告も利用不可");
} else {
System.out.println("広告ロード失敗: " + errorCode);
}
}
});
AdChoicesの位置調整
バックフィルネイティブ広告で、AdChoicesマークを表示するコーナーを指定できます。load()呼び出し前にAdropNativeAdインスタンスのpreferredAdChoicesPositionを設定してください。
import io.adrop.ads.nativeAd.AdropAdChoicesPosition
import io.adrop.ads.nativeAd.AdropNativeAd
val nativeAd = AdropNativeAd(this, "YOUR_UNIT_ID")
nativeAd.preferredAdChoicesPosition = AdropAdChoicesPosition.BOTTOM_RIGHT
nativeAd.load()
import io.adrop.ads.nativeAd.AdropAdChoicesPosition;
import io.adrop.ads.nativeAd.AdropNativeAd;
AdropNativeAd nativeAd = new AdropNativeAd(this, "YOUR_UNIT_ID");
nativeAd.setPreferredAdChoicesPosition(AdropAdChoicesPosition.BOTTOM_RIGHT);
nativeAd.load();
| 値 | 説明 |
|---|---|
AdropAdChoicesPosition.TOP_LEFT | 左上 |
AdropAdChoicesPosition.TOP_RIGHT | 右上(デフォルト) |
AdropAdChoicesPosition.BOTTOM_LEFT | 左下 |
AdropAdChoicesPosition.BOTTOM_RIGHT | 右下 |
この設定はバックフィルネットワークに渡される希望位置のヒントで、バックフィルネイティブ広告にのみ適用されます — ダイレクト広告には影響しません。必ず
load()呼び出し前に設定する必要があり、バックフィルネットワークがポリシー上別の位置に表示する場合があります。バックフィル広告を使用するには、
io.adrop:adrop-ads-backfill依存関係を追加する必要があります。はじめにを参照してください。次のステップ
バナー広告
バナー広告を実装
インタースティシャル広告
インタースティシャル広告を実装
ターゲティング設定
ユーザー属性とコンテキストターゲティング
リファレンス
クラス、リスナー、エラーコード