1+ package co .optable .demoappjava .ui ;
2+
3+ import android .os .Bundle ;
4+ import android .view .LayoutInflater ;
5+ import android .view .View ;
6+ import android .view .ViewGroup ;
7+ import android .widget .TextView ;
8+ import androidx .annotation .NonNull ;
9+ import androidx .annotation .Nullable ;
10+ import androidx .fragment .app .Fragment ;
11+ import co .optable .android_sdk .OptableSDK ;
12+ import co .optable .demoappjava .MainActivity ;
13+ import co .optable .demoappjava .R ;
14+ import com .google .android .gms .ads .AdListener ;
15+ import com .google .android .gms .ads .LoadAdError ;
16+ import com .google .android .gms .ads .admanager .AdManagerAdRequest ;
17+ import com .google .android .gms .ads .admanager .AdManagerAdView ;
18+ import org .jetbrains .annotations .NotNull ;
19+ import org .prebid .mobile .BannerAdUnit ;
20+ import org .prebid .mobile .ExternalUserId ;
21+ import org .prebid .mobile .TargetingParams ;
22+
23+ import java .util .*;
24+
25+ public class PrebidBannerFragment extends Fragment {
26+
27+ private static final String GAM_AD_UNIT_ID = "/21808260008/prebid_demo_app_original_api_banner" ;
28+ private static final String PREBID_CONFIG_ID = "prebid-demo-banner-320-50" ;
29+ private static final int WIDTH = 320 ;
30+ private static final int HEIGHT = 50 ;
31+
32+ private AdManagerAdView adView ;
33+ private BannerAdUnit prebidAdUnit ;
34+
35+ private ViewGroup adContainer ;
36+ private TextView statusTextView ;
37+
38+ @ Override
39+ public View onCreateView (@ NonNull LayoutInflater inflater , ViewGroup container , Bundle savedInstanceState ) {
40+ View root = inflater .inflate (R .layout .fragment_prebid , container , false );
41+ initUi (root );
42+ return root ;
43+ }
44+
45+ private void initUi (View root ) {
46+ statusTextView = root .findViewById (R .id .statusTextView );
47+ adContainer = root .findViewById (R .id .adContainer );
48+
49+ root .findViewById (R .id .btnLoadBanner ).setOnClickListener (view -> onClickLoadAd ());
50+ root .findViewById (R .id .btnCachedBanner ).setOnClickListener (view -> onClickCachedBanner ());
51+ root .findViewById (R .id .btnClearCache ).setOnClickListener (view -> onClickClearCache ());
52+ }
53+
54+ /**
55+ * Loads targeting data and then the GAM banner
56+ */
57+ private void onClickLoadAd () {
58+ statusTextView .setText ("" );
59+
60+ MainActivity .OPTABLE
61+ .targeting ()
62+ .observe (getViewLifecycleOwner (), result -> {
63+ AdManagerAdRequest .Builder adRequestBuilder = new AdManagerAdRequest .Builder ();
64+
65+ if (result .getStatus () == OptableSDK .Status .SUCCESS ) {
66+ HashMap <String , List <String >> data = result .getData ();
67+ changeStatusText ("Loaded Optable targeting data" , data );
68+
69+ if (data != null ) {
70+ for (String key : data .keySet ()) {
71+ List <String > values = data .get (key );
72+ if (values == null ) continue ;
73+ adRequestBuilder .addCustomTargeting (key , values );
74+ }
75+ }
76+ } else {
77+ changeStatusText ("Error loading Optable targeting data: " + result .getMessage (), null );
78+ }
79+
80+ loadPrebidAd (adRequestBuilder , result .getData ());
81+ profile ();
82+ witness ();
83+ });
84+ }
85+
86+ private void loadPrebidAd (AdManagerAdRequest .Builder adRequestBuilder , @ Nullable HashMap <String , List <String >> optableTargeting ) {
87+ prebidAdUnit = new BannerAdUnit (PREBID_CONFIG_ID , WIDTH , HEIGHT );
88+ applyOptableToPrebid (optableTargeting );
89+ prebidAdUnit .fetchDemand (adRequestBuilder , resultCode -> {
90+ appendStatusText ("Prebid ads loading status: " + resultCode .toString ());
91+ loadGamAd (adRequestBuilder );
92+ });
93+ }
94+
95+ private void applyOptableToPrebid (HashMap <String , List <String >> optableTargeting ) {
96+ if (optableTargeting != null ) {
97+ List <ExternalUserId .UniqueId > uniqueIds = new ArrayList <>();
98+ for (Map .Entry <String , List <String >> entry : optableTargeting .entrySet ()) {
99+ List <String > value = entry .getValue ();
100+ if (value == null ) continue ;
101+ for (String id : value ) {
102+ uniqueIds .add (new ExternalUserId .UniqueId (id , 1 ));
103+ }
104+ }
105+ List <ExternalUserId > externalUserIds = new ArrayList <>();
106+ externalUserIds .add (new ExternalUserId ("optable.com" , uniqueIds ));
107+ TargetingParams .setExternalUserIds (externalUserIds );
108+ }
109+ }
110+
111+ private void loadGamAd (AdManagerAdRequest .Builder adRequestBuilder ) {
112+ adContainer .removeAllViews ();
113+
114+ AdManagerAdRequest adRequest = adRequestBuilder .build ();
115+
116+ adView = new AdManagerAdView (requireContext ());
117+ adView .setAdUnitId (GAM_AD_UNIT_ID );
118+ adView .setAdSizes (new com .google .android .gms .ads .AdSize (WIDTH , HEIGHT ));
119+ adView .setAdListener (new AdListener () {
120+ @ Override
121+ public void onAdLoaded () {
122+ super .onAdLoaded ();
123+ appendStatusText ("Google ad loaded" );
124+ }
125+
126+ @ Override
127+ public void onAdFailedToLoad (@ NonNull @ NotNull LoadAdError loadAdError ) {
128+ appendStatusText ("Google ad failed to load: " + loadAdError .getMessage ());
129+ }
130+ });
131+ adView .loadAd (adRequest );
132+
133+ adContainer .addView (adView );
134+ }
135+
136+ /**
137+ * Loads targeting data from cache and then the GAM banner
138+ */
139+ private void onClickCachedBanner () {
140+ statusTextView .setText ("" );
141+
142+ AdManagerAdRequest .Builder adRequestBuilder = new AdManagerAdRequest .Builder ();
143+ HashMap <String , List <String >> data = MainActivity .OPTABLE .targetingFromCache ();
144+
145+ if (data != null ) {
146+ changeStatusText ("Loaded Optable cached targeting data" , data );
147+ for (String key : data .keySet ()) {
148+ List <String > values = data .get (key );
149+ if (values == null ) continue ;
150+ adRequestBuilder .addCustomTargeting (key , values );
151+ }
152+ } else {
153+ changeStatusText ("Targeting data cache empty." , null );
154+ }
155+
156+ loadPrebidAd (adRequestBuilder , data );
157+ profile ();
158+ witness ();
159+ }
160+
161+ /**
162+ * Clears targeting data cache.
163+ */
164+ private void onClickClearCache () {
165+ statusTextView .setText ("Clearing targeting data cache.\n \n " );
166+ MainActivity .OPTABLE .targetingClearCache ();
167+ }
168+
169+ private void profile () {
170+ HashMap <String , Object > traits = new HashMap <>();
171+ traits .put ("gender" , "F" );
172+ traits .put ("age" , 38 );
173+ traits .put ("hasAccount" , true );
174+
175+ MainActivity .OPTABLE
176+ .profile (traits )
177+ .observe (getViewLifecycleOwner (), result -> {
178+ if (result .getStatus () == OptableSDK .Status .SUCCESS ) {
179+ appendStatusText ("Success calling profile API to set traits on user." );
180+ } else {
181+ appendStatusText ("Error during sending profile: " + result .getMessage ());
182+ }
183+ });
184+ }
185+
186+ private void witness () {
187+ HashMap <String , Object > eventProperties = new HashMap <>();
188+ eventProperties .put ("exampleKey" , "exampleValue" );
189+ eventProperties .put ("exampleKey2" , 123 );
190+ eventProperties .put ("exampleKey3" , false );
191+
192+ MainActivity .OPTABLE
193+ .witness ("GAMBannerFragment.loadAdButtonClicked" , eventProperties )
194+ .observe (getViewLifecycleOwner (), result -> {
195+ if (result .getStatus () == OptableSDK .Status .SUCCESS ) {
196+ appendStatusText ("Success calling witness API to log loadAdButtonClicked event." );
197+ } else {
198+ appendStatusText ("Error during sending witness: " + result .getMessage ());
199+ }
200+ });
201+ }
202+
203+ private void changeStatusText (@ NonNull String message , @ Nullable HashMap <String , List <String >> optableResponse ) {
204+ StringBuilder formattedMessage = new StringBuilder (message );
205+ if (optableResponse != null ) {
206+ formattedMessage .append ("\n \n Targeting data: " );
207+ for (Map .Entry <String , ? extends Collection <?>> entry : optableResponse .entrySet ()) {
208+ formattedMessage .append (entry .getKey ())
209+ .append (" = " )
210+ .append (entry .getValue ())
211+ .append ("\n " );
212+ }
213+ }
214+ statusTextView .setText (formattedMessage .toString ());
215+ }
216+
217+ private void appendStatusText (@ NonNull String message ) {
218+ statusTextView .append ("\n \n " + message );
219+ }
220+
221+ }
0 commit comments