diff --git a/Java/app/build.gradle b/Java/app/build.gradle index e8124ee..ecd627c 100644 --- a/Java/app/build.gradle +++ b/Java/app/build.gradle @@ -41,7 +41,8 @@ dependencies { implementation 'androidx.annotation:annotation:1.1.0' //Taboola - implementation 'com.taboola:android-sdk:4.0.0' + implementation 'com.taboola:android-sdk-beta:meta-unified-1.0.3-654-6d9c2e10d' + implementation 'com.squareup.retrofit2:converter-gson:2.9.0' } \ No newline at end of file diff --git a/Java/app/src/main/assets/fonts/arial_bold.ttf b/Java/app/src/main/assets/fonts/arial_bold.ttf new file mode 100644 index 0000000..addc76c Binary files /dev/null and b/Java/app/src/main/assets/fonts/arial_bold.ttf differ diff --git a/Java/app/src/main/java/com/taboola/sdk4example/Const.java b/Java/app/src/main/java/com/taboola/sdk4example/Const.java index 23ccda9..ba66c3e 100644 --- a/Java/app/src/main/java/com/taboola/sdk4example/Const.java +++ b/Java/app/src/main/java/com/taboola/sdk4example/Const.java @@ -23,4 +23,12 @@ public class Const { public static final String FEED_PLACEMENT_NAME = "Feed without video"; public static final String FEED_MODE = "thumbs-feed-01"; public static final String DARK_MODE = "darkMode"; + + //Meta widget 1x1 + public static final String META_WIDGET_PLACEMENT_NAME = "Below Article Thumbnails"; + public static final String META_WIDGET_MODE = "meta-widget-1x1"; + + //Meta Feed + public static final String META_FEED_PLACEMENT_NAME = "Feed without video"; + public static final String META_FEED_MODE = "alternating-thumbnails-a"; } diff --git a/Java/app/src/main/java/com/taboola/sdk4example/MetaConst.java b/Java/app/src/main/java/com/taboola/sdk4example/MetaConst.java new file mode 100644 index 0000000..6fa8f76 --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/MetaConst.java @@ -0,0 +1,22 @@ +package com.taboola.sdk4example; + +public class MetaConst { + + public static final String META_PUBLISHER_NAME = "sdk-tester-meta"; + public static final String AUDIENCE_NETWORK_APP_ID = "1097593608162039"; + public static final String AUDIENCE_NETWORK_PLACEMENT_ID = "1097593608162039_1097982098123190"; + public static final String AUDIENCE_NETWORK_CAROUSEL_PLACEMENT_ID = "1097593608162039_1288555252399206"; + public static final String AUDIENCE_NETWORK_APPLICATION_ID_KEY = "audienceNetworkApplicationId"; + public static final String AUDIENCE_NETWORK_PLACEMENT_ID_KEY = "audienceNetworkPlacementId"; + public static final String ENABLE_META_DEMAND_DEBUG_KEY = "enableMetaDemandDebug"; + public static final String DEFAULT_LAYOUT_KEY = "default"; + public static final String TEST_LAYOUT_IMAGE_LINK_TYPE = "image_link"; + public static final String TEST_LAYOUT_CAROUSEL_TYPE = "carousel"; + // UI customization + public static final String ELEMENT_TYPE_BRANDING = "branding"; + public static final String DARK_NODE = "darkMode"; + public static final String TYPEFACE_ARIAL_BOLD = "arial_bold"; + public static final int TEXT_FONT_SIZE = 20; + public static final int NUMBER_OF_LINES = 2; + public static final float AMOUNT_OF_SPACE_BETWEEN_LINES = 0.5f; +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/SDKClassicMenuFragment.java b/Java/app/src/main/java/com/taboola/sdk4example/SDKClassicMenuFragment.java index 361080f..2398b4d 100644 --- a/Java/app/src/main/java/com/taboola/sdk4example/SDKClassicMenuFragment.java +++ b/Java/app/src/main/java/com/taboola/sdk4example/SDKClassicMenuFragment.java @@ -2,21 +2,25 @@ import android.content.Context; import android.os.Bundle; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; - import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; + import com.taboola.sdk4example.sdk_classic.FeedLazyLoadInsideRecyclerViewFragment; import com.taboola.sdk4example.sdk_classic.FeedWithMiddleArticleDarkModeInsideRecyclerViewFragment; import com.taboola.sdk4example.sdk_classic.FeedWithMiddleArticleInsideListViewFragment; import com.taboola.sdk4example.sdk_classic.FeedWithMiddleArticleInsideRecyclerViewFragment; import com.taboola.sdk4example.sdk_classic.FeedWithMiddleArticleInsideScrollViewFragment; +import com.taboola.sdk4example.sdk_classic.MetaAdCarouselFragment; +import com.taboola.sdk4example.sdk_classic.MetaAdInsideScrollViewFragment; +import com.taboola.sdk4example.sdk_classic.MetaAdUICustomization; +import com.taboola.sdk4example.sdk_classic.MetaClassicUnitFragment; +import com.taboola.sdk4example.sdk_classic.MetaClassicUnitFragmentUICustomization; import com.taboola.sdk4example.sdk_classic.OCClickHandlerFragment; import com.taboola.sdk4example.sdk_classic.PullToRefreshFragment; import com.taboola.sdk4example.sdk_classic.RecyclerViewPreloadFragment; @@ -65,6 +69,11 @@ public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceStat addButton(getString(R.string.std_feed_pull_to_refresh), R.id.std_feed_pull_to_refresh, viewGroup); addButton(getString(R.string.std_feed_lazy_loading_rv), R.id.std_feed_lazy_loading_rv, viewGroup); addButton(getString(R.string.std_mid_article_with_feed_dark_mode_rv), R.id.std_mid_article_with_feed_dark_mode_rv, viewGroup); + addButton(getString(R.string.std_meta), R.id.std_meta_ad, viewGroup); + addButton(getString(R.string.std_meta_ad_UI_customization), R.id.std_meta_ad_UI_customization, viewGroup); + addButton(getString(R.string.std_meta_tbl_classic_unit_ad_UI_customization), R.id.std_meta_tbl_classic_unit_ad_UI_customization, viewGroup); + addButton(getString(R.string.std_meta_classic_unit), R.id.std_meta_classic_unit, viewGroup); + addButton(getString(R.string.std_meta_carousel), R.id.std_meta_carousel, viewGroup); } @@ -104,6 +113,21 @@ public void onClick(View v) { case R.id.std_mid_article_with_feed_dark_mode_rv: fragmentToOpen = new FeedWithMiddleArticleDarkModeInsideRecyclerViewFragment(); break; + case R.id.std_meta_ad: + fragmentToOpen = new MetaAdInsideScrollViewFragment(); + break; + case R.id.std_meta_classic_unit: + fragmentToOpen = new MetaClassicUnitFragment(); + break; + case R.id.std_meta_ad_UI_customization: + fragmentToOpen = new MetaAdUICustomization(); + break; + case R.id.std_meta_tbl_classic_unit_ad_UI_customization: + fragmentToOpen = new MetaClassicUnitFragmentUICustomization(); + break; + case R.id.std_meta_carousel: + fragmentToOpen = new MetaAdCarouselFragment(); + break; } if (fragmentToOpen != null) { diff --git a/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdCarouselFragment.java b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdCarouselFragment.java new file mode 100644 index 0000000..7251d0c --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdCarouselFragment.java @@ -0,0 +1,86 @@ +package com.taboola.sdk4example.sdk_classic; + +import static com.taboola.sdk4example.Const.META_WIDGET_MODE; +import static com.taboola.sdk4example.Const.META_WIDGET_PLACEMENT_NAME; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.facebook.ads.NativeAdLayout; +import com.taboola.android.TBLClassicPage; +import com.taboola.android.TBLClassicUnit; +import com.taboola.android.TBLPublisherInfo; +import com.taboola.android.Taboola; +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE; +import com.taboola.android.listeners.TBLClassicListener; +import com.taboola.sdk4example.Const; +import com.taboola.sdk4example.MetaConst; +import com.taboola.sdk4example.R; +import com.taboola.sdk4example.tabs.BaseTaboolaFragment; + +import java.util.HashMap; + +public class MetaAdCarouselFragment extends BaseTaboolaFragment { + + private static final String TAG = MetaAdInsideScrollViewFragment.class.getSimpleName(); + + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + Taboola.init(new TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)); + View rootView = inflater.inflate(R.layout.fragment_meta_ad_inside_sv, null); + NativeAdLayout adContainerTop = rootView.findViewById(R.id.native_ad_container_top); + + Taboola.setGlobalExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID); + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true"); + }}); + + setupAndLoadTaboolaAd(adContainerTop); + return rootView; + } + + + private void setupAndLoadTaboolaAd(NativeAdLayout adContainer) { + TBLClassicPage tblClassicPage = Taboola.getClassicPage(Const.PAGE_URL, Const.PAGE_TYPE); + TBLClassicUnit tblClassicUnit = tblClassicPage.build(getContext(), META_WIDGET_PLACEMENT_NAME, META_WIDGET_MODE, TBL_PLACEMENT_TYPE.PAGE_MIDDLE, new TBLClassicListener() { + @Override + public boolean onItemClick(String placementName, String itemId, String clickUrl, boolean isOrganic, String customData) { + Log.d(TAG, "onItemClick"); + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData); + } + + @Override + public void onAdReceiveSuccess() { + super.onAdReceiveSuccess(); + Log.d(TAG, "onAdReceiveSuccess"); + } + + @Override + public void onAdReceiveFail(String error) { + super.onAdReceiveFail(error); + Log.d(TAG, "onAdReceiveFail " + error); + } + }); + // Force the ad to be of type image_link + tblClassicUnit.setAdTypeForDebug(MetaConst.TEST_LAYOUT_CAROUSEL_TYPE); + tblClassicUnit.setUnitExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY, MetaConst.AUDIENCE_NETWORK_CAROUSEL_PLACEMENT_ID); + }}); + + tblClassicUnit.setNativeUI(MetaConst.DEFAULT_LAYOUT_KEY); + + adContainer.addView(tblClassicUnit); + tblClassicUnit.fetchContent(); + } + + +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdInsideScrollViewFragment.java b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdInsideScrollViewFragment.java new file mode 100644 index 0000000..77418b1 --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdInsideScrollViewFragment.java @@ -0,0 +1,87 @@ +package com.taboola.sdk4example.sdk_classic; + +import static com.taboola.sdk4example.Const.META_WIDGET_MODE; +import static com.taboola.sdk4example.Const.META_WIDGET_PLACEMENT_NAME; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.facebook.ads.NativeAdLayout; +import com.taboola.android.TBLClassicPage; +import com.taboola.android.TBLClassicUnit; +import com.taboola.android.TBLPublisherInfo; +import com.taboola.android.Taboola; +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE; +import com.taboola.android.listeners.TBLClassicListener; +import com.taboola.sdk4example.Const; +import com.taboola.sdk4example.MetaConst; +import com.taboola.sdk4example.R; +import com.taboola.sdk4example.tabs.BaseTaboolaFragment; + +import java.util.HashMap; + + +public class MetaAdInsideScrollViewFragment extends BaseTaboolaFragment { + + private static final String TAG = MetaAdInsideScrollViewFragment.class.getSimpleName(); + + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + Taboola.init(new TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)); + View rootView = inflater.inflate(R.layout.fragment_meta_ad_inside_sv, null); + NativeAdLayout adContainerTop = rootView.findViewById(R.id.native_ad_container_top); + + Taboola.setGlobalExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID); + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true"); + }}); + + setupAndLoadTaboolaAd(adContainerTop); + return rootView; + } + + + private void setupAndLoadTaboolaAd(NativeAdLayout adContainer) { + TBLClassicPage tblClassicPage = Taboola.getClassicPage(Const.PAGE_URL, Const.PAGE_TYPE); + TBLClassicUnit tblClassicUnit = tblClassicPage.build(getContext(), META_WIDGET_PLACEMENT_NAME, META_WIDGET_MODE, TBL_PLACEMENT_TYPE.PAGE_MIDDLE, new TBLClassicListener() { + @Override + public boolean onItemClick(String placementName, String itemId, String clickUrl, boolean isOrganic, String customData) { + Log.d(TAG, "onItemClick"); + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData); + } + + @Override + public void onAdReceiveSuccess() { + super.onAdReceiveSuccess(); + Log.d(TAG, "onAdReceiveSuccess"); + } + + @Override + public void onAdReceiveFail(String error) { + super.onAdReceiveFail(error); + Log.d(TAG, "onAdReceiveFail " + error); + } + }); + // Force the ad to be of type image_link + tblClassicUnit.setAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE); + tblClassicUnit.setUnitExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY, MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID); + }}); + + tblClassicUnit.setNativeUI(MetaConst.DEFAULT_LAYOUT_KEY); + + adContainer.addView(tblClassicUnit); + tblClassicUnit.fetchContent(); + } + + +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdUICustomization.java b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdUICustomization.java new file mode 100644 index 0000000..005625a --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaAdUICustomization.java @@ -0,0 +1,125 @@ +package com.taboola.sdk4example.sdk_classic; + +import static com.taboola.sdk4example.Const.META_WIDGET_MODE; +import static com.taboola.sdk4example.Const.META_WIDGET_PLACEMENT_NAME; +import static com.taboola.sdk4example.MetaConst.AMOUNT_OF_SPACE_BETWEEN_LINES; +import static com.taboola.sdk4example.MetaConst.ELEMENT_TYPE_BRANDING; +import static com.taboola.sdk4example.MetaConst.NUMBER_OF_LINES; +import static com.taboola.sdk4example.MetaConst.TEXT_FONT_SIZE; +import static com.taboola.sdk4example.MetaConst.TYPEFACE_ARIAL_BOLD; +import static com.taboola.sdk4example.utils.Utils.loadFont; + +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.facebook.ads.NativeAdLayout; +import com.taboola.android.TBLClassicPage; +import com.taboola.android.TBLClassicUnit; +import com.taboola.android.TBLPublisherInfo; +import com.taboola.android.Taboola; +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE; +import com.taboola.android.listeners.TBLClassicListener; + +import com.taboola.android.utils.style_properties.TBLTextStylePropertiesBuilder; +import com.taboola.android.utils.style_properties.TBLTitleStylePropertiesBuilder; +import com.taboola.android.utils.style_properties.TBLUiStyleProperties; +import com.taboola.sdk4example.Const; +import com.taboola.sdk4example.MetaConst; +import com.taboola.sdk4example.R; +import com.taboola.sdk4example.tabs.BaseTaboolaFragment; + +import java.util.HashMap; + +public class MetaAdUICustomization extends BaseTaboolaFragment { + + + private static final String TAG = MetaAdUICustomization.class.getSimpleName(); + + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + Taboola.init(new TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)); + View rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null); + NativeAdLayout adContainerTop = rootView.findViewById(R.id.native_ad_container_top); + + Taboola.setGlobalExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID); + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true"); + }}); + + setupAndLoadTaboolaAd(adContainerTop); + return rootView; + } + + + private void setupAndLoadTaboolaAd(NativeAdLayout adContainer) { + TBLClassicPage tblClassicPage = Taboola.getClassicPage(Const.PAGE_URL, Const.PAGE_TYPE); + TBLClassicUnit tblClassicUnit = tblClassicPage.build(getContext(), META_WIDGET_PLACEMENT_NAME, META_WIDGET_MODE, TBL_PLACEMENT_TYPE.PAGE_MIDDLE, new TBLClassicListener() { + @Override + public boolean onItemClick(String placementName, String itemId, String clickUrl, boolean isOrganic, String customData) { + Log.d(TAG, "onItemClick"); + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData); + } + + @Override + public void onAdReceiveSuccess() { + super.onAdReceiveSuccess(); + Log.d(TAG, "onAdReceiveSuccess"); + } + + @Override + public void onAdReceiveFail(String error) { + super.onAdReceiveFail(error); + Log.d(TAG, "onAdReceiveFail " + error); + } + }); + tblClassicUnit.setUnitExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY, MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID); + }}); + Typeface font = loadFont(getActivity(), TYPEFACE_ARIAL_BOLD); + + // Create custom style properties for the branding + TBLUiStyleProperties brandingStyleProperties = new TBLTextStylePropertiesBuilder(ELEMENT_TYPE_BRANDING) + .setFontLightColor(R.color.design_default_color_error) + .setFontDarkColor(R.color.colorPrimary) + .setFontSize(TEXT_FONT_SIZE) + .setTypeface(font) + .build(); + + // Create custom style properties for the title + TBLUiStyleProperties titleStyleProperties = new TBLTitleStylePropertiesBuilder() + .setAmountOfSpaceBetweenLines(AMOUNT_OF_SPACE_BETWEEN_LINES) + .setLines(NUMBER_OF_LINES) + .setFontLightColor(Color.RED) + .setFontSize(TEXT_FONT_SIZE) + .setFontDarkColor(Color.BLUE) + .setTypeface(font) + .build(); + + // Create custom style properties for the call to action button +// TBLUiStyleProperties ctaStyleProperties = new TBLCallToActionButtonStylePropertiesBuilder() +// // Sets the visibility of the call-to-action (CTA) button. +// // The button is visible by default. for hide the button pass false. +// .setVisibility(false) +// .build(); + + // Set the custom UI properties to the Meta native Ad + tblClassicUnit.setNativeUI(MetaConst.DEFAULT_LAYOUT_KEY, brandingStyleProperties, titleStyleProperties +// ctaStyleProperties + ); + adContainer.addView(tblClassicUnit); + tblClassicUnit.fetchContent(); + } + + +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragment.java b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragment.java new file mode 100644 index 0000000..cecc387 --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragment.java @@ -0,0 +1,92 @@ +package com.taboola.sdk4example.sdk_classic; + +import static com.taboola.sdk4example.Const.META_FEED_MODE; +import static com.taboola.sdk4example.Const.META_FEED_PLACEMENT_NAME; +import static com.taboola.sdk4example.Const.META_WIDGET_MODE; +import static com.taboola.sdk4example.Const.META_WIDGET_PLACEMENT_NAME; + +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.facebook.ads.NativeAdLayout; +import com.taboola.android.MetaPlacementProperties; +import com.taboola.android.TBLClassicPage; +import com.taboola.android.TBLMetaClassicUnit; +import com.taboola.android.TBLPublisherInfo; +import com.taboola.android.Taboola; +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE; +import com.taboola.android.listeners.TBLClassicListener; +import com.taboola.sdk4example.Const; +import com.taboola.sdk4example.MetaConst; +import com.taboola.sdk4example.R; +import com.taboola.sdk4example.tabs.BaseTaboolaFragment; + +import java.util.HashMap; + +public class MetaClassicUnitFragment extends BaseTaboolaFragment { + + private static final String TAG = MetaClassicUnitFragment.class.getSimpleName(); + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + Taboola.init(new TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)); + View rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null); + NativeAdLayout adContainerTop = rootView.findViewById(R.id.native_ad_container_top); + + Taboola.setGlobalExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID); + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true"); + }}); + + setupAndLoadTaboolaAd(adContainerTop); + return rootView; + } + + + private void setupAndLoadTaboolaAd(NativeAdLayout adContainer) { + TBLClassicPage tblClassicPage = Taboola.getClassicPage(Const.PAGE_URL, Const.PAGE_TYPE); + MetaPlacementProperties metaPlacementProperties = new MetaPlacementProperties(META_WIDGET_PLACEMENT_NAME, META_WIDGET_MODE); + TBLMetaClassicUnit tblMetaClassicUnit = tblClassicPage.buildWithMeta(getContext(), META_FEED_PLACEMENT_NAME, META_FEED_MODE, TBL_PLACEMENT_TYPE.PAGE_MIDDLE, metaPlacementProperties, new TBLClassicListener() { + @Override + public boolean onItemClick(String placementName, String itemId, String clickUrl, boolean isOrganic, String customData) { + Log.d(TAG, "onItemClick"); + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData); + } + + @Override + public void onAdReceiveSuccess() { + super.onAdReceiveSuccess(); + Log.d(TAG, "onAdReceiveSuccess"); + } + + @Override + public void onAdReceiveFail(String error) { + super.onAdReceiveFail(error); + Log.d(TAG, "onAdReceiveFail " + error); + } + + @Override + public void onResize(int height) { + super.onResize(height); + Log.d(TAG, "onResize"); + } + }); + tblMetaClassicUnit.setMetaAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE); + tblMetaClassicUnit.setUnitExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY, MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID); + }}); + + tblMetaClassicUnit.setMetaNativeUI(MetaConst.DEFAULT_LAYOUT_KEY); + adContainer.addView(tblMetaClassicUnit); + tblMetaClassicUnit.fetchContent(); + } + +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragmentUICustomization.java b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragmentUICustomization.java new file mode 100644 index 0000000..89d60b3 --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/sdk_classic/MetaClassicUnitFragmentUICustomization.java @@ -0,0 +1,144 @@ +package com.taboola.sdk4example.sdk_classic; + +import static com.taboola.sdk4example.Const.META_FEED_MODE; +import static com.taboola.sdk4example.Const.META_FEED_PLACEMENT_NAME; +import static com.taboola.sdk4example.Const.META_WIDGET_MODE; +import static com.taboola.sdk4example.Const.META_WIDGET_PLACEMENT_NAME; +import static com.taboola.sdk4example.MetaConst.AMOUNT_OF_SPACE_BETWEEN_LINES; +import static com.taboola.sdk4example.MetaConst.DARK_NODE; +import static com.taboola.sdk4example.MetaConst.ELEMENT_TYPE_BRANDING; +import static com.taboola.sdk4example.MetaConst.NUMBER_OF_LINES; +import static com.taboola.sdk4example.MetaConst.TEXT_FONT_SIZE; +import static com.taboola.sdk4example.MetaConst.TYPEFACE_ARIAL_BOLD; +import static com.taboola.sdk4example.utils.Utils.loadFont; + +import android.content.res.Configuration; +import android.graphics.Color; +import android.graphics.Typeface; +import android.os.Bundle; +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; + +import com.facebook.ads.NativeAdLayout; +import com.taboola.android.MetaPlacementProperties; +import com.taboola.android.TBLClassicPage; +import com.taboola.android.TBLMetaClassicUnit; +import com.taboola.android.TBLPublisherInfo; +import com.taboola.android.Taboola; +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE; +import com.taboola.android.listeners.TBLClassicListener; +import com.taboola.android.utils.style_properties.TBLCallToActionButtonStylePropertiesBuilder; +import com.taboola.android.utils.style_properties.TBLTextStylePropertiesBuilder; +import com.taboola.android.utils.style_properties.TBLTitleStylePropertiesBuilder; +import com.taboola.android.utils.style_properties.TBLUiStyleProperties; +import com.taboola.sdk4example.Const; +import com.taboola.sdk4example.MetaConst; +import com.taboola.sdk4example.R; +import com.taboola.sdk4example.tabs.BaseTaboolaFragment; + +import java.util.HashMap; + +public class MetaClassicUnitFragmentUICustomization extends BaseTaboolaFragment { + + private static final String TAG = MetaClassicUnitFragmentUICustomization.class.getSimpleName(); + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + int isOSDarkMode = + getContext().getResources().getConfiguration().uiMode & + Configuration.UI_MODE_NIGHT_MASK; + Taboola.init(new TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)); + View rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null); + NativeAdLayout adContainerTop = rootView.findViewById(R.id.native_ad_container_top); + + Taboola.setGlobalExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID); + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true"); + if (isOSDarkMode == Configuration.UI_MODE_NIGHT_YES) { + put(DARK_NODE, "true"); + } + }}); + + setupAndLoadTaboolaAd(adContainerTop); + return rootView; + } + + + private void setupAndLoadTaboolaAd(NativeAdLayout adContainer) { + TBLClassicPage tblClassicPage = Taboola.getClassicPage(Const.PAGE_URL, Const.PAGE_TYPE); + MetaPlacementProperties metaPlacementProperties = new MetaPlacementProperties(META_WIDGET_PLACEMENT_NAME, META_WIDGET_MODE); + TBLMetaClassicUnit tblMetaClassicUnit = tblClassicPage.buildWithMeta(getContext(), META_FEED_PLACEMENT_NAME, META_FEED_MODE, TBL_PLACEMENT_TYPE.PAGE_MIDDLE, metaPlacementProperties, new TBLClassicListener() { + @Override + public boolean onItemClick(String placementName, String itemId, String clickUrl, boolean isOrganic, String customData) { + Log.d(TAG, "onItemClick"); + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData); + } + + @Override + public void onAdReceiveSuccess() { + super.onAdReceiveSuccess(); + Log.d(TAG, "onAdReceiveSuccess"); + } + + @Override + public void onAdReceiveFail(String error) { + super.onAdReceiveFail(error); + Log.d(TAG, "onAdReceiveFail " + error); + } + + @Override + public void onResize(int height) { + super.onResize(height); + Log.d(TAG, "onResize"); + } + }); + tblMetaClassicUnit.setMetaAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE); + tblMetaClassicUnit.setUnitExtraProperties(new HashMap() {{ + put(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY, MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID); + }}); + + Typeface font = loadFont(getActivity(), TYPEFACE_ARIAL_BOLD); + + // Create custom style properties for the branding + TBLUiStyleProperties brandingStyleProperties = new TBLTextStylePropertiesBuilder(ELEMENT_TYPE_BRANDING) + .setFontLightColor(R.color.design_default_color_error) + .setFontDarkColor(R.color.colorPrimary) + .setFontSize(TEXT_FONT_SIZE) + .setTypeface(font) + .build(); + + // Create custom style properties for the title + TBLUiStyleProperties titleStyleProperties = new TBLTitleStylePropertiesBuilder() + .setAmountOfSpaceBetweenLines(AMOUNT_OF_SPACE_BETWEEN_LINES) + .setLines(NUMBER_OF_LINES) + .setFontLightColor(Color.RED) + .setFontSize(TEXT_FONT_SIZE) + .setFontDarkColor(Color.BLUE) + .setTypeface(font) + .build(); + + // Create custom style properties for the call to action button +// TBLUiStyleProperties ctaStyleProperties = new TBLCallToActionButtonStylePropertiesBuilder() +// // Sets the visibility of the call-to-action (CTA) button. +// // The button is visible by default. for hide the button pass false. +// .setVisibility(false) +// .build(); + + // Set the custom UI properties to the Meta native Ad + tblMetaClassicUnit.setMetaNativeUI(MetaConst.DEFAULT_LAYOUT_KEY, + brandingStyleProperties, + titleStyleProperties +// ctaStyleProperties + ); + adContainer.addView(tblMetaClassicUnit); + tblMetaClassicUnit.fetchContent(); + } + +} diff --git a/Java/app/src/main/java/com/taboola/sdk4example/utils/Utils.java b/Java/app/src/main/java/com/taboola/sdk4example/utils/Utils.java new file mode 100644 index 0000000..42b8f0b --- /dev/null +++ b/Java/app/src/main/java/com/taboola/sdk4example/utils/Utils.java @@ -0,0 +1,26 @@ +package com.taboola.sdk4example.utils; + +import static com.taboola.sdk4example.MetaConst.TYPEFACE_ARIAL_BOLD; + +import android.content.res.AssetManager; +import android.graphics.Typeface; +import android.os.Build; + +import androidx.fragment.app.FragmentActivity; + +public class Utils { + private static final String FONTS_PATH = "fonts/"; + private static final String FONT_SUFFIX = ".ttf"; + + public static Typeface loadFont(FragmentActivity activity, String fontName) { + Typeface font = Typeface.DEFAULT_BOLD; + AssetManager assets = activity.getAssets(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + font = new Typeface.Builder( + assets, + FONTS_PATH + TYPEFACE_ARIAL_BOLD + FONT_SUFFIX + ).build(); + } + return font; + } +} diff --git a/Java/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml b/Java/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml new file mode 100644 index 0000000..59a90d6 --- /dev/null +++ b/Java/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml b/Java/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml new file mode 100644 index 0000000..2e69d01 --- /dev/null +++ b/Java/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Java/app/src/main/res/values/ids.xml b/Java/app/src/main/res/values/ids.xml index 1240158..48bcb92 100644 --- a/Java/app/src/main/res/values/ids.xml +++ b/Java/app/src/main/res/values/ids.xml @@ -18,6 +18,11 @@ + + + + + diff --git a/Java/app/src/main/res/values/strings.xml b/Java/app/src/main/res/values/strings.xml index 37e5d38..112814e 100644 --- a/Java/app/src/main/res/values/strings.xml +++ b/Java/app/src/main/res/values/strings.xml @@ -106,6 +106,11 @@ These will help you remember what the consumer really wants to engage with and w Pull to refresh Feed Lazy Loading (RecyclerView) Feed with Dark Mode (RecyclerView) + Meta Ad Inside ScrollView Fragment + MetaAd UI customization + MeteTBLClassicUnit UI customization + Meta Ad Above Feed Fragment + Meta Ad Carousel Fragment Native Widget Native Feed diff --git a/Kotlin/app/build.gradle b/Kotlin/app/build.gradle index 01c37f3..4b66bb2 100644 --- a/Kotlin/app/build.gradle +++ b/Kotlin/app/build.gradle @@ -50,7 +50,7 @@ android { dependencies { // Import Taboola SDK - implementation 'com.taboola:android-sdk:4.0.0' + implementation 'com.taboola:android-sdk-beta:meta-unified-1.0.3-654-6d9c2e10d' implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation 'androidx.core:core-ktx:1.3.2' diff --git a/Kotlin/app/src/main/assets/fonts/arial_bold.ttf b/Kotlin/app/src/main/assets/fonts/arial_bold.ttf new file mode 100644 index 0000000..addc76c Binary files /dev/null and b/Kotlin/app/src/main/assets/fonts/arial_bold.ttf differ diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/MetaConst.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/MetaConst.kt new file mode 100644 index 0000000..4c1409c --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/MetaConst.kt @@ -0,0 +1,24 @@ +package com.taboola.kotlin.examples + +class MetaConst { + companion object { + const val META_PUBLISHER_NAME = "sdk-tester-meta" + const val AUDIENCE_NETWORK_APP_ID = "1097593608162039" + const val AUDIENCE_NETWORK_PLACEMENT_ID = "1097593608162039_1097982098123190" + const val AUDIENCE_NETWORK_CAROUSEL_PLACEMENT_ID = "1097593608162039_1288555252399206" + const val AUDIENCE_NETWORK_APPLICATION_ID_KEY = "audienceNetworkApplicationId" + const val AUDIENCE_NETWORK_PLACEMENT_ID_KEY = "audienceNetworkPlacementId" + const val ENABLE_META_DEMAND_DEBUG_KEY = "enableMetaDemandDebug" + const val DEFAULT_LAYOUT_KEY = "default" + const val TEST_LAYOUT_IMAGE_LINK_TYPE = "image_link" + const val TEST_LAYOUT_CAROUSEL_TYPE = "carousel" + + // UI customizations values + const val ELEMENT_TYPE_BRANDING: String = "branding" + const val TEXT_FONT_SIZE: Float = 20.0f + const val NUMBER_OF_LINES: Int = 2 + const val AMOUNT_OF_SPACE_BETWEEN_ELEMENTS: Float = 0.5f + const val FONT_TYPEFACE_ARIAL_BOLD = "arial_bold" + const val DARK_MODE = "darkMode" + } +} \ No newline at end of file diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/PlacementInfo.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/PlacementInfo.kt index 8fcdbf8..7318449 100644 --- a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/PlacementInfo.kt +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/PlacementInfo.kt @@ -2,49 +2,46 @@ package com.taboola.kotlin.examples class PlacementInfo { - class WidgetProperties { - val placementName = "Widget without video" - val sourceType = "text" - val pageType = "article" - val pageUrl = "https://blog.taboola.com" - val targetType = "mix" - val mode = "thumbs-feed-01" + open class BaseProperties { + open val placementName = "Widget without video" + open val sourceType = "text" + open val pageType = "article" + open val pageUrl = "https://blog.taboola.com" + open val targetType = "mix" + open val mode = "thumbs-feed-01" } - class ClassicFeedProperties { - val placementName = "Feed with video" - val sourceType = "text" - val pageType = "article" - val pageUrl = "https://blog.taboola.com" - val targetType = "mix" - val mode = "thumbs-feed-01" + class WidgetProperties : BaseProperties() + + class ClassicFeedProperties : BaseProperties() { + override val placementName = "Feed with video" + } + + class NativeFeedProperties : BaseProperties() { + override val placementName = "list_item" } - class NativeFeedProperties { - val placementName = "list_item" - val sourceType = "text" - val pageType = "article" - val pageUrl = "https://blog.taboola.com" - val targetType = "mix" - val mode = "thumbs-feed-01" + class WebFeedProperties : BaseProperties() { + override val placementName = "Feed without video" } - class WebFeedProperties { - val placementName = "Feed without video" - val sourceType = "text" - val pageType = "article" - val pageUrl = "https://blog.taboola.com" - val targetType = "mix" - val mode = "thumbs-feed-01" + class MetaWidgetProperties : BaseProperties() { + override val placementName = "Below Article Thumbnails" + override val mode = "meta-widget-1x1" + } + + class MetaFeedProperties : BaseProperties() { + override val placementName = "Feed without video" + override val mode = "alternating-thumbnails-a" } // Static access - companion object { + companion object { fun widgetProperties() = WidgetProperties() fun classicFeedProperties() = ClassicFeedProperties() fun nativeFeedProperties() = NativeFeedProperties() fun webFeedProperties() = WebFeedProperties() + fun metaWidgetProperties() = MetaWidgetProperties() + fun metaFeedProperties() = MetaFeedProperties() } - - } \ No newline at end of file diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdCarouselFragment.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdCarouselFragment.kt new file mode 100644 index 0000000..4febad3 --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdCarouselFragment.kt @@ -0,0 +1,83 @@ +package com.taboola.kotlin.examples.screens.classic + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.facebook.ads.NativeAdLayout +import com.taboola.android.TBLPublisherInfo +import com.taboola.android.Taboola +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE +import com.taboola.android.listeners.TBLClassicListener +import com.taboola.kotlin.examples.MetaConst +import com.taboola.kotlin.examples.PlacementInfo +import com.taboola.kotlin.examples.R + +class MetaAdCarouselFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Taboola.init(TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)) + val rootView = inflater.inflate(R.layout.fragment_meta_ad_inside_sv, null) + val adContainerTop: NativeAdLayout = rootView.findViewById(R.id.native_ad_container_top) + Taboola.setGlobalExtraProperties(object : HashMap() { + init { + put( + MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, + MetaConst.AUDIENCE_NETWORK_APP_ID + ) + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true") + } + }) + setupAndLoadTaboolaAd(adContainerTop) + return rootView + } + + + private fun setupAndLoadTaboolaAd(adContainer: NativeAdLayout) { + val widgetProperties = PlacementInfo.metaWidgetProperties() + val tblClassicPage = + Taboola.getClassicPage(widgetProperties.pageUrl, widgetProperties.pageType) + val tblClassicUnit = tblClassicPage.build( + context, + widgetProperties.placementName, + widgetProperties.mode, + TBL_PLACEMENT_TYPE.PAGE_MIDDLE, + object : TBLClassicListener() { + override fun onItemClick( + placementName: String?, + itemId: String?, + clickUrl: String?, + isOrganic: Boolean, + customData: String? + ): Boolean { + Log.d(TAG, "onItemClick") + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData) + } + + override fun onAdReceiveSuccess() { + super.onAdReceiveSuccess() + Log.d(TAG, "onAdReceiveSuccess") + } + + override fun onAdReceiveFail(error: String?) { + super.onAdReceiveFail(error) + Log.d(TAG, "onAdReceiveFail $error") + } + }) + tblClassicUnit.setAdTypeForDebug(MetaConst.TEST_LAYOUT_CAROUSEL_TYPE) + tblClassicUnit.setUnitExtraProperties(hashMapOf(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY to MetaConst.AUDIENCE_NETWORK_CAROUSEL_PLACEMENT_ID)) + tblClassicUnit.setNativeUI(MetaConst.DEFAULT_LAYOUT_KEY) + adContainer.addView(tblClassicUnit) + tblClassicUnit.fetchContent() + } + + companion object { + private val TAG = MetaAdCarouselFragment::class.java.simpleName + } +} \ No newline at end of file diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdInsideScrollViewFragment.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdInsideScrollViewFragment.kt new file mode 100644 index 0000000..2c49949 --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdInsideScrollViewFragment.kt @@ -0,0 +1,83 @@ +package com.taboola.kotlin.examples.screens.classic + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.facebook.ads.NativeAdLayout +import com.taboola.android.TBLPublisherInfo +import com.taboola.android.Taboola +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE +import com.taboola.android.listeners.TBLClassicListener +import com.taboola.kotlin.examples.MetaConst +import com.taboola.kotlin.examples.PlacementInfo +import com.taboola.kotlin.examples.R + +class MetaAdInsideScrollViewFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Taboola.init(TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)) + val rootView = inflater.inflate(R.layout.fragment_meta_ad_inside_sv, null) + val adContainerTop: NativeAdLayout = rootView.findViewById(R.id.native_ad_container_top) + Taboola.setGlobalExtraProperties(object : HashMap() { + init { + put( + MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, + MetaConst.AUDIENCE_NETWORK_APP_ID + ) + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true") + } + }) + setupAndLoadTaboolaAd(adContainerTop) + return rootView + } + + + private fun setupAndLoadTaboolaAd(adContainer: NativeAdLayout) { + val widgetProperties = PlacementInfo.metaWidgetProperties() + val tblClassicPage = + Taboola.getClassicPage(widgetProperties.pageUrl, widgetProperties.pageType) + val tblClassicUnit = tblClassicPage.build( + context, + widgetProperties.placementName, + widgetProperties.mode, + TBL_PLACEMENT_TYPE.PAGE_MIDDLE, + object : TBLClassicListener() { + override fun onItemClick( + placementName: String?, + itemId: String?, + clickUrl: String?, + isOrganic: Boolean, + customData: String? + ): Boolean { + Log.d(TAG, "onItemClick") + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData) + } + + override fun onAdReceiveSuccess() { + super.onAdReceiveSuccess() + Log.d(TAG, "onAdReceiveSuccess") + } + + override fun onAdReceiveFail(error: String?) { + super.onAdReceiveFail(error) + Log.d(TAG, "onAdReceiveFail $error") + } + }) + tblClassicUnit.setAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE) + tblClassicUnit.setUnitExtraProperties(hashMapOf(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY to MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID)) + tblClassicUnit.setNativeUI(MetaConst.DEFAULT_LAYOUT_KEY) + adContainer.addView(tblClassicUnit) + tblClassicUnit.fetchContent() + } + + companion object { + private val TAG = MetaAdInsideScrollViewFragment::class.java.simpleName + } +} diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdUICustomizationsFragment.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdUICustomizationsFragment.kt new file mode 100644 index 0000000..05e1d94 --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaAdUICustomizationsFragment.kt @@ -0,0 +1,131 @@ +package com.taboola.kotlin.examples.screens.classic + +import android.graphics.Typeface +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.fragment.app.Fragment +import com.facebook.ads.NativeAdLayout +import com.taboola.android.TBLPublisherInfo +import com.taboola.android.Taboola +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE +import com.taboola.android.listeners.TBLClassicListener +import com.taboola.android.utils.style_properties.TBLTextStylePropertiesBuilder +import com.taboola.android.utils.style_properties.TBLTitleStylePropertiesBuilder +import com.taboola.android.utils.style_properties.TBLCallToActionButtonStylePropertiesBuilder +import com.taboola.kotlin.examples.MetaConst +import com.taboola.kotlin.examples.MetaConst.Companion.AMOUNT_OF_SPACE_BETWEEN_ELEMENTS +import com.taboola.kotlin.examples.MetaConst.Companion.ELEMENT_TYPE_BRANDING +import com.taboola.kotlin.examples.MetaConst.Companion.FONT_TYPEFACE_ARIAL_BOLD +import com.taboola.kotlin.examples.MetaConst.Companion.NUMBER_OF_LINES +import com.taboola.kotlin.examples.MetaConst.Companion.TEXT_FONT_SIZE +import com.taboola.kotlin.examples.PlacementInfo +import com.taboola.kotlin.examples.R +import com.taboola.kotlin.examples.screens.utils.Utils.Companion.getFullPathToFontFile + +class MetaAdUICustomizationsFragment : Fragment() { + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View? { + Taboola.init(TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)) + val rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null) + val adContainerTop: NativeAdLayout = rootView.findViewById(R.id.native_ad_container_top) + Taboola.setGlobalExtraProperties(object : HashMap() { + init { + put( + MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID + ) + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true") + } + }) + setupAndLoadTaboolaAd(adContainerTop) + return rootView + } + + + private fun setupAndLoadTaboolaAd(adContainer: NativeAdLayout) { + val widgetProperties = PlacementInfo.metaWidgetProperties() + val tblClassicPage = + Taboola.getClassicPage(widgetProperties.pageUrl, widgetProperties.pageType) + val tblClassicUnit = tblClassicPage.build(context, + widgetProperties.placementName, + widgetProperties.mode, + TBL_PLACEMENT_TYPE.PAGE_MIDDLE, + object : TBLClassicListener() { + override fun onItemClick( + placementName: String?, + itemId: String?, + clickUrl: String?, + isOrganic: Boolean, + customData: String? + ): Boolean { + Log.d(MetaAdUICustomizationsFragment.TAG, "onItemClick") + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData) + } + + override fun onAdReceiveSuccess() { + super.onAdReceiveSuccess() + Log.d(MetaAdUICustomizationsFragment.TAG, "onAdReceiveSuccess") + } + + override fun onAdReceiveFail(error: String?) { + super.onAdReceiveFail(error) + Log.d(MetaAdUICustomizationsFragment.TAG, "onAdReceiveFail $error") + } + }) + // Force the ad to be of type image_link + tblClassicUnit.setAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE) + // Set the Audience Network placement ID here + tblClassicUnit.setUnitExtraProperties(hashMapOf(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY to MetaConst.AUDIENCE_NETWORK_CAROUSEL_PLACEMENT_ID)) + val typefaceArielBold = Typeface.Builder( + requireActivity().assets, + getFullPathToFontFile(FONT_TYPEFACE_ARIAL_BOLD) + ).build() + + // Create custom style properties for the title + val titleStyleProperties = TBLTitleStylePropertiesBuilder() + .setAmountOfSpaceBetweenLines(AMOUNT_OF_SPACE_BETWEEN_ELEMENTS) + .setLines(NUMBER_OF_LINES) + .setFontSize(TEXT_FONT_SIZE) + .setFontLightColor(Color.Blue.toArgb()) + .setFontDarkColor(Color.Red.toArgb()) + .setTypeface(typefaceArielBold) + .build() + + // Create custom style properties for the branding + val brandingStyleProperties = + TBLTextStylePropertiesBuilder(ELEMENT_TYPE_BRANDING) + .setFontSize(TEXT_FONT_SIZE) + .setFontLightColor(R.color.purple_200) + .setFontDarkColor(R.color.purple_500) + .setTypeface(typefaceArielBold) + .build() +// // Create custom style properties for the call to action button +// val callToActionButtonStyleProperties = +// TBLCallToActionButtonStylePropertiesBuilder() +// // Sets the visibility of the call-to-action (CTA) button. +// // The button is visible by default. for hide the button pass false. +// .setVisibility(false) +// .build() + + // Set the custom UI properties to the Meta native Ad + tblClassicUnit.setNativeUI( + MetaConst.DEFAULT_LAYOUT_KEY, + brandingStyleProperties, + titleStyleProperties, +// callToActionButtonStyleProperties + ) + adContainer.addView(tblClassicUnit) + tblClassicUnit.fetchContent() + } + + + + companion object { + private val TAG = MetaAdUICustomizationsFragment::class.java.simpleName + } +} diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaClassicUnitFragment.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaClassicUnitFragment.kt new file mode 100644 index 0000000..033623a --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaClassicUnitFragment.kt @@ -0,0 +1,96 @@ +package com.taboola.kotlin.examples.screens.classic + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import com.facebook.ads.NativeAdLayout +import com.taboola.android.MetaPlacementProperties +import com.taboola.android.TBLPublisherInfo +import com.taboola.android.Taboola +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE +import com.taboola.android.listeners.TBLClassicListener +import com.taboola.kotlin.examples.MetaConst +import com.taboola.kotlin.examples.PlacementInfo +import com.taboola.kotlin.examples.R + +class MetaClassicUnitFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + Taboola.init(TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)) + val rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null) + val adContainerTop: NativeAdLayout = + rootView.findViewById(R.id.native_ad_container_top) + Taboola.setGlobalExtraProperties(object : HashMap() { + init { + put( + MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, + MetaConst.AUDIENCE_NETWORK_APP_ID + ) + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true") + } + }) + setupAndLoadTaboolaAd(adContainerTop) + return rootView + } + + + private fun setupAndLoadTaboolaAd(adContainer: NativeAdLayout) { + val widgetProperties = PlacementInfo.metaWidgetProperties() + val feedProperties = PlacementInfo.metaFeedProperties() + val tblClassicPage = Taboola.getClassicPage(feedProperties.pageUrl, feedProperties.pageType) + val metaPlacementProperties = + MetaPlacementProperties(widgetProperties.placementName, widgetProperties.mode) + val tblMetaClassicUnit = tblClassicPage.buildWithMeta( + context, + feedProperties.placementName, + feedProperties.mode, + TBL_PLACEMENT_TYPE.PAGE_MIDDLE, + metaPlacementProperties, + object : TBLClassicListener() { + override fun onItemClick( + placementName: String?, + itemId: String?, + clickUrl: String?, + isOrganic: Boolean, + customData: String? + ): Boolean { + Log.d(TAG, "onItemClick") + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData) + } + + override fun onAdReceiveSuccess() { + super.onAdReceiveSuccess() + Log.d(TAG, "onAdReceiveSuccess") + } + + override fun onAdReceiveFail(error: String?) { + super.onAdReceiveFail(error) + Log.d(TAG, "onAdReceiveFail $error") + } + + override fun onResize(height: Int) { + super.onResize(height) + Log.d(TAG, "onResize $height") + } + }) + //Force the ad to be of type image_link + tblMetaClassicUnit.setMetaAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE) + tblMetaClassicUnit.setUnitExtraProperties(hashMapOf(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY to MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID)) + tblMetaClassicUnit.setMetaNativeUI(MetaConst.DEFAULT_LAYOUT_KEY) + adContainer.addView(tblMetaClassicUnit) + tblMetaClassicUnit.fetchContent() + } + + companion object { + private val TAG = MetaClassicUnitFragment::class.java.simpleName + } +} + + diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaUICustomizationClassicUnitFragment.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaUICustomizationClassicUnitFragment.kt new file mode 100644 index 0000000..464976f --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/classic/MetaUICustomizationClassicUnitFragment.kt @@ -0,0 +1,159 @@ +package com.taboola.kotlin.examples.screens.classic + +import android.app.Activity +import android.content.res.Configuration +import android.graphics.Typeface +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.graphics.toArgb +import androidx.fragment.app.Fragment +import com.facebook.ads.NativeAdLayout +import com.taboola.android.MetaPlacementProperties +import com.taboola.android.TBLPublisherInfo +import com.taboola.android.Taboola +import com.taboola.android.annotations.TBL_PLACEMENT_TYPE +import com.taboola.android.listeners.TBLClassicListener +import com.taboola.android.utils.style_properties.TBLCallToActionButtonStylePropertiesBuilder +import com.taboola.android.utils.style_properties.TBLTextStylePropertiesBuilder +import com.taboola.android.utils.style_properties.TBLTitleStylePropertiesBuilder +import com.taboola.kotlin.examples.MetaConst +import com.taboola.kotlin.examples.MetaConst.Companion.AMOUNT_OF_SPACE_BETWEEN_ELEMENTS +import com.taboola.kotlin.examples.MetaConst.Companion.DARK_MODE +import com.taboola.kotlin.examples.MetaConst.Companion.ELEMENT_TYPE_BRANDING +import com.taboola.kotlin.examples.MetaConst.Companion.FONT_TYPEFACE_ARIAL_BOLD +import com.taboola.kotlin.examples.MetaConst.Companion.NUMBER_OF_LINES +import com.taboola.kotlin.examples.MetaConst.Companion.TEXT_FONT_SIZE +import com.taboola.kotlin.examples.PlacementInfo +import com.taboola.kotlin.examples.R +import com.taboola.kotlin.examples.screens.utils.Utils.Companion.getFullPathToFontFile + +class MetaUICustomizationClassicUnitFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? + ): View? { + Taboola.init(TBLPublisherInfo(MetaConst.META_PUBLISHER_NAME)) + val rootView = inflater.inflate(R.layout.fragment_meta_ad_classic_unit, null) + val adContainerTop: NativeAdLayout = rootView.findViewById(R.id.native_ad_container_top) + Taboola.setGlobalExtraProperties(object : HashMap() { + init { + + val isDarkTheme = isDarkTheme(requireActivity()) + put( + MetaConst.AUDIENCE_NETWORK_APPLICATION_ID_KEY, MetaConst.AUDIENCE_NETWORK_APP_ID + ) + put(MetaConst.ENABLE_META_DEMAND_DEBUG_KEY, "true") + + //if the device is in dark mode, set the dark mode flag + if (isDarkTheme) { + put(DARK_MODE, "true") + } + } + }) + setupAndLoadTaboolaAd(adContainerTop) + return rootView + } + + // check OS dark mode + fun isDarkTheme(activity: Activity): Boolean { + return activity.resources.configuration.uiMode and + Configuration.UI_MODE_NIGHT_MASK == Configuration.UI_MODE_NIGHT_YES + } + + + private fun setupAndLoadTaboolaAd(adContainer: NativeAdLayout) { + val widgetProperties = PlacementInfo.metaWidgetProperties() + val feedProperties = PlacementInfo.metaFeedProperties() + val tblClassicPage = Taboola.getClassicPage(feedProperties.pageUrl, feedProperties.pageType) + val metaPlacementProperties = + MetaPlacementProperties(widgetProperties.placementName, widgetProperties.mode) + val tblMetaClassicUnit = tblClassicPage.buildWithMeta(context, + feedProperties.placementName, + feedProperties.mode, + TBL_PLACEMENT_TYPE.PAGE_MIDDLE, + metaPlacementProperties, + object : TBLClassicListener() { + override fun onItemClick( + placementName: String?, + itemId: String?, + clickUrl: String?, + isOrganic: Boolean, + customData: String? + ): Boolean { + Log.d(TAG, "onItemClick") + return super.onItemClick(placementName, itemId, clickUrl, isOrganic, customData) + } + + override fun onAdReceiveSuccess() { + super.onAdReceiveSuccess() + Log.d(TAG, "onAdReceiveSuccess") + } + + override fun onAdReceiveFail(error: String?) { + super.onAdReceiveFail(error) + Log.d(TAG, "onAdReceiveFail $error") + } + + override fun onResize(height: Int) { + super.onResize(height) + Log.d(TAG, "onResize $height") + } + }) + //Force the ad to be of type image_link + tblMetaClassicUnit.setMetaAdTypeForDebug(MetaConst.TEST_LAYOUT_IMAGE_LINK_TYPE) + tblMetaClassicUnit.setUnitExtraProperties(hashMapOf(MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID_KEY to MetaConst.AUDIENCE_NETWORK_PLACEMENT_ID)) + + val typefaceArielBold = Typeface.Builder( + requireActivity().assets, + getFullPathToFontFile(FONT_TYPEFACE_ARIAL_BOLD) + + ).build() + + // Create custom style properties for the title + val titleStyleProperties = TBLTitleStylePropertiesBuilder() + .setAmountOfSpaceBetweenLines(AMOUNT_OF_SPACE_BETWEEN_ELEMENTS) + .setLines(NUMBER_OF_LINES) + .setFontSize(TEXT_FONT_SIZE) + .setFontLightColor(Color.Blue.toArgb()) + .setFontDarkColor(Color.Red.toArgb()) + .setTypeface(typefaceArielBold) + .build() + + // Create custom style properties for the branding + val brandingStyleProperties = + TBLTextStylePropertiesBuilder(ELEMENT_TYPE_BRANDING) + .setFontSize(TEXT_FONT_SIZE) + .setFontLightColor(R.color.purple_200) + .setFontDarkColor(R.color.purple_500) + .setTypeface(typefaceArielBold) + .build() + +// // Create custom style properties for the call to action button +// val callToActionButtonStyleProperties = +// TBLCallToActionButtonStylePropertiesBuilder() +// // Sets the visibility of the call-to-action (CTA) button. +// // The button is visible by default. for hide the button pass false. +// .setVisibility(false) +// .build() + + // Set the custom UI properties to the Meta native Ad + tblMetaClassicUnit.setMetaNativeUI( + MetaConst.DEFAULT_LAYOUT_KEY, + brandingStyleProperties, + titleStyleProperties, +// callToActionButtonStyleProperties + ) + adContainer.addView(tblMetaClassicUnit) + tblMetaClassicUnit.fetchContent() + } + + companion object { + private val TAG = MetaUICustomizationClassicUnitFragment::class.java.simpleName + } +} + + diff --git a/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/utils/Utils.kt b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/utils/Utils.kt new file mode 100644 index 0000000..93c2793 --- /dev/null +++ b/Kotlin/app/src/main/java/com/taboola/kotlin/examples/screens/utils/Utils.kt @@ -0,0 +1,10 @@ +package com.taboola.kotlin.examples.screens.utils + +class Utils { + companion object { + fun getFullPathToFontFile(fontName: String): String { + return "fonts/$fontName.ttf" + } + } + +} \ No newline at end of file diff --git a/Kotlin/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml b/Kotlin/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml new file mode 100644 index 0000000..59a90d6 --- /dev/null +++ b/Kotlin/app/src/main/res/layout/fragment_meta_ad_classic_unit.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/Kotlin/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml b/Kotlin/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml new file mode 100644 index 0000000..2e69d01 --- /dev/null +++ b/Kotlin/app/src/main/res/layout/fragment_meta_ad_inside_sv.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/Kotlin/app/src/main/res/menu/activity_main_drawer.xml b/Kotlin/app/src/main/res/menu/activity_main_drawer.xml index b48d493..472848d 100644 --- a/Kotlin/app/src/main/res/menu/activity_main_drawer.xml +++ b/Kotlin/app/src/main/res/menu/activity_main_drawer.xml @@ -22,6 +22,21 @@ + + + + + diff --git a/Kotlin/app/src/main/res/navigation/mobile_navigation.xml b/Kotlin/app/src/main/res/navigation/mobile_navigation.xml index fe9ee87..ee3de63 100644 --- a/Kotlin/app/src/main/res/navigation/mobile_navigation.xml +++ b/Kotlin/app/src/main/res/navigation/mobile_navigation.xml @@ -32,15 +32,40 @@ + android:label="@string/nav_classic_compose_feed" /> + android:label="@string/nav_classic_compose_feed_lazycolumn" /> + + + + + + + + android:label="@string/web_compose_widget" /> + android:label="@string/web_compose_feed" /> + android:label="@string/web_continuous_scroll" /> + android:label="@string/native_widget_compose" /> + android:label="@string/native_feed_compose" /> \ No newline at end of file diff --git a/Kotlin/app/src/main/res/values/strings.xml b/Kotlin/app/src/main/res/values/strings.xml index 874e013..e4f9e99 100644 --- a/Kotlin/app/src/main/res/values/strings.xml +++ b/Kotlin/app/src/main/res/values/strings.xml @@ -16,6 +16,11 @@ Classic Feed Classic Xml Widget Classic View Pager + MetaAd inside scroll view + MetaAd UI customization + MeteTBLClassicUnit UI customization + MetaAd Carousel + MetaAd above feed Web Widget Web Widget - Compose Web Feed - Compose @@ -31,4 +36,38 @@ ComposeClassicRecyclerView + + YouTube and Taboola: Defining the Future of Digital Video\n\nEarly last month, I was asked to head out to Singapore for a one-day conference organized by IAB SEA + India called Tomorrow’s Digital Skills Today.\nI spoke about video creative and production from the psychological, data and research points of view, and although traveling there wasn’t easy (I flew 16 hours each way for a 48 hour stay)—I would definitely say it was worth it.\nAside from enjoying the modern city, delicious foods, and warm weather (not to mention a quick drink at the world famous Marina Bay Sands hotel rooftop), I also had the pleasure to co-present with Karl Duffill, Regional Agency Business Head at Google, who was asked to speak about video creatives as well.\nWhen preparing for this session, we found that although Taboola and Google are two different video platforms that give consumers a different experience, even when watching the same video, many of the video trends and recommendations regarding the video creative are similar: authenticity, keeping the viewer’s attention span in mind, inspiring the audience to take action, and more.\n + \n Authenticity in video drives success.\n + YouTube has been identifying some really interesting trends in regards to video formats.\n +People aren’t just watching videos with traditional storylines anymore—they’re spending hours watching gamers just play online games, they’re watching a lot of super short videos, and they’re especially loving live-streamed content.\n +One of the things that these trends have in common is authenticity.\n + The person recording himself playing a video game did not prepare a script for if he wins or when he loses.\n + + + +Authentic video creators don’t feel the need to spend hours planning a video—instead they upload a short video that gets their message across in an easy and relatable way. There’s nothing more real than a live-streamed video that includes every mistake and mishap that would’ve definitely been cut out of a recorded video.\n +On a similar note, I spoke about the importance of authenticity in video. From the psychological perspective, it creates an intimate relationship between the consumer and the brand.\n +I also presented some surprising findings—when analyzing the quality (bitrate) of the videos running on our network, we found that the average-quality videos performed significantly better in terms of both the viewability and the completion rate as opposed to videos with very high quality.\n +We think this is directly related to a less authentic feel in high-quality videos.\n +Bite, snack and meal sized videos perform better.\n\n +With regard to video length, Karl really put it best. +He stressed the importance of keeping the consumer’s attention span in mind when producing video creatives. He suggested creating videos for different attention spans, specifically, bite (6-second), snack (15-20 second) or meal (30-second)-sized videos. +I spoke about video length as well, and focused on the impact that a short video (anything less than 30 seconds) can have. +To illustrate, I presented one of the classic social psychology studies that found that watching a video of a person for half of a minute can predict how the viewer will feel about the person in the video after getting to know them long term. + \n\nInspiring consumers to take action.\n\n +Finally, and although video is known more for its power to inspire than its power to drive to immediate action, we spoke about driving said action. +Psychologists identified that emotion, or how you feel about the brand, is one of the main determinants when a consumer is deciding what to buy. +These emotions can be easily influenced with branded video. A recent analysis of our top 2,000 videos uncovered that videos that included some kind of emotional expression got a significantly higher viewability rate and completion rate. +Another thing to consider as a marketer looking to inspire action—create and distribute specific content for specific audience groups. +This was one of the main takeaways from a case study that Karl presented with AirBnB, who created video ads for audiences in the ‘dreaming’ stage of booking a trip and audiences in the ‘planning’ stage of booking a trip. +When you think video, think consumer-first. +When I think about what my learning are from this session, the thing that really stuck with me is that putting your consumer first is really key, regardless of where you choose to promote your video. +Although we suggest planning a marketing mix that will allow to reap the benefits that each platform has to offer, remember these three things: + \n\nBe authentic.\n\n +Customize video length to support your audience’s mindset +Understand how your consumer makes decisions to drive action +These will help you remember what the consumer really wants to engage with and will set you up for a successful marketing campaign. + + \ No newline at end of file