diff --git a/.gitignore b/.gitignore
index 71f9913..45b2fa1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@ g*.iml
.gradle
.idea
.kotlin
+libs
local.properties
diff --git a/DemoApp/DemoAppJava/app/build.gradle b/DemoApp/DemoAppJava/app/build.gradle
index 44e2c9b..498bbfa 100644
--- a/DemoApp/DemoAppJava/app/build.gradle
+++ b/DemoApp/DemoAppJava/app/build.gradle
@@ -41,11 +41,18 @@ android {
dependencies {
// Optable SDK
- implementation "com.github.Optable:optable-android-sdk:" + versioning.getVersionName(false)
+ if (useReleaseSdk == "true") {
+ implementation "com.github.Optable:optable-android-sdk:" + versioning.getVersionName(false)
+ } else {
+ implementation "co.optable:local-sdk"
+ }
// Google Mobile Ads
implementation 'com.google.android.gms:play-services-ads:24.6.0'
+ // Prebid Ads
+ implementation "org.prebid:prebid-mobile-sdk:3.0.2"
+
// Base Android
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.0.21"
implementation 'com.android.support:multidex:1.0.3'
diff --git a/DemoApp/DemoAppJava/app/src/main/AndroidManifest.xml b/DemoApp/DemoAppJava/app/src/main/AndroidManifest.xml
index 6757516..a228588 100644
--- a/DemoApp/DemoAppJava/app/src/main/AndroidManifest.xml
+++ b/DemoApp/DemoAppJava/app/src/main/AndroidManifest.xml
@@ -6,6 +6,7 @@
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/MainActivity.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/MainActivity.java
index ef7ce31..1e9d150 100644
--- a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/MainActivity.java
+++ b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/MainActivity.java
@@ -1,32 +1,55 @@
package co.optable.demoappjava;
import android.os.Bundle;
+import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
-import co.optable.android_sdk.OptableSDK;
+import com.google.android.gms.ads.MobileAds;
import com.google.android.material.bottomnavigation.BottomNavigationView;
+import org.prebid.mobile.PrebidMobile;
+import org.prebid.mobile.api.data.InitializationStatus;
public class MainActivity extends AppCompatActivity {
- public static OptableSDK OPTABLE;
+ private static final String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
- MainActivity.OPTABLE = new OptableSDK(this.getApplicationContext(), "sandbox.optable.co", "ios-sdk-demo");
-
+ initGoogleAds();
+ initPrebidSdk();
initUi();
}
+ private void initGoogleAds() {
+ MobileAds.initialize(this, initializationStatus -> {
+ });
+ }
+
+ private void initPrebidSdk() {
+ PrebidMobile.setPrebidServerAccountId("0689a263-318d-448b-a3d4-b02e8a709d9d");
+ PrebidMobile.initializeSdk(getApplicationContext(), "https://prebid-server-test-j.prebid.org/openrtb2/auction", status -> {
+ if (status == InitializationStatus.SUCCEEDED) {
+ Log.d(TAG, "SDK initialized successfully!");
+ } else {
+ Log.e(TAG, "SDK initialization error: " + status.getDescription());
+ }
+ });
+ }
+
private void initUi() {
BottomNavigationView navView = findViewById(R.id.nav_view);
NavController navController = Navigation.findNavController(this, R.id.nav_host_fragment);
- AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(R.id.navigation_identify, R.id.navigation_gambanner).build();
+ AppBarConfiguration appBarConfiguration = new AppBarConfiguration.Builder(
+ R.id.navigation_identify,
+ R.id.navigation_gambanner,
+ R.id.navigation_prebid
+ ).build();
NavigationUI.setupActionBarWithNavController(this, navController, appBarConfiguration);
NavigationUI.setupWithNavController(navView, navController);
}
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/TheApplication.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/TheApplication.java
new file mode 100644
index 0000000..0f84c6b
--- /dev/null
+++ b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/TheApplication.java
@@ -0,0 +1,19 @@
+package co.optable.demoappjava;
+
+import android.app.Application;
+import co.optable.android_sdk.OptableConfig;
+import co.optable.android_sdk.OptableSDK;
+
+public class TheApplication extends Application {
+
+ public static OptableSDK optable;
+
+ @Override
+ public void onCreate() {
+ super.onCreate();
+
+ OptableConfig config = new OptableConfig(this, "prebidtest", "js-sdk", "ca.edge.optable.co");
+ optable = new OptableSDK(config);
+ }
+
+}
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GAMBanner/GAMBannerFragment.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GAMBanner/GAMBannerFragment.java
deleted file mode 100644
index d717c4f..0000000
--- a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GAMBanner/GAMBannerFragment.java
+++ /dev/null
@@ -1,161 +0,0 @@
-package co.optable.demoappjava.ui.GAMBanner;
-
-import android.os.Bundle;
-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 co.optable.android_sdk.OptableSDK;
-import co.optable.demoappjava.MainActivity;
-import co.optable.demoappjava.R;
-import com.google.android.gms.ads.AdRequest;
-import com.google.android.gms.ads.admanager.AdManagerAdRequest;
-import com.google.android.gms.ads.admanager.AdManagerAdView;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-public class GAMBannerFragment extends Fragment {
-
- private AdManagerAdView mAdView;
- private TextView statusTextView;
-
- @Override
- public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View root = inflater.inflate(R.layout.fragment_gambanner, container, false);
- initUi(root);
- return root;
- }
-
- private void initUi(View root) {
- mAdView = root.findViewById(R.id.publisherAdView);
- statusTextView = root.findViewById(R.id.targetingDataView);
-
- root.findViewById(R.id.btnLoadBanner).setOnClickListener(view -> onClickLoadAd());
- root.findViewById(R.id.btnCachedBanner).setOnClickListener(view -> onClickCachedBanner());
- root.findViewById(R.id.btnClearCache).setOnClickListener(view -> onClickClearCache());
- }
-
- /**
- * Loads targeting data and then the GAM banner
- */
- private void onClickLoadAd() {
- statusTextView.setText("");
-
- MainActivity.OPTABLE
- .targeting()
- .observe(getViewLifecycleOwner(), result -> {
- AdManagerAdRequest.Builder adRequest = new AdManagerAdRequest.Builder();
-
- if (result.getStatus() == OptableSDK.Status.SUCCESS) {
- HashMap> data = result.getData();
- changeStatusText("Loading GAM ad with targeting data", data);
-
- if (data != null) {
- for (String key : data.keySet()) {
- List values = data.get(key);
- if (values == null) continue;
- adRequest.addCustomTargeting(key, values);
- }
- }
- } else {
- changeStatusText("Error getting targeting data: " + result.getMessage(), null);
- }
-
- mAdView.loadAd(adRequest.build());
- profile();
- witness();
- });
- }
-
- /**
- * Loads targeting data from cache and then the GAM banner
- */
- private void onClickCachedBanner() {
- statusTextView.setText("");
-
- AdRequest.Builder adRequest = new AdRequest.Builder();
- HashMap> data = MainActivity.OPTABLE.targetingFromCache();
-
- if (data != null) {
- changeStatusText("Loading GAM ad with cached targeting data", data);
- for (String key : data.keySet()) {
- List values = data.get(key);
- if (values == null) continue;
- adRequest.addCustomTargeting(key, values);
- }
- } else {
- changeStatusText("Targeting data cache empty.", null);
- }
-
- mAdView.loadAd(adRequest.build());
- profile();
- witness();
- }
-
- /**
- * Clears targeting data cache.
- */
- private void onClickClearCache() {
- statusTextView.setText("Clearing targeting data cache.\n\n");
- MainActivity.OPTABLE.targetingClearCache();
- }
-
- private void profile() {
- HashMap traits = new HashMap<>();
- traits.put("gender", "F");
- traits.put("age", 38);
- traits.put("hasAccount", true);
-
- MainActivity.OPTABLE
- .profile(traits)
- .observe(getViewLifecycleOwner(), result -> {
- if (result.getStatus() == OptableSDK.Status.SUCCESS) {
- appendStatusText("Success calling profile API to set traits on user.");
- } else {
- appendStatusText("Error during sending profile: " + result.getMessage());
- }
- });
- }
-
- private void witness() {
- HashMap eventProperties = new HashMap<>();
- eventProperties.put("exampleKey", "exampleValue");
- eventProperties.put("exampleKey2", 123);
- eventProperties.put("exampleKey3", false);
-
- MainActivity.OPTABLE
- .witness("GAMBannerFragment.loadAdButtonClicked", eventProperties)
- .observe(getViewLifecycleOwner(), result -> {
- if (result.getStatus() == OptableSDK.Status.SUCCESS) {
- appendStatusText("Success calling witness API to log loadAdButtonClicked event.");
- } else {
- appendStatusText("Error during sending witness: " + result.getMessage());
- }
- });
- }
-
- private void changeStatusText(@NonNull String message, @Nullable HashMap> optableResponse) {
- StringBuilder formattedMessage = new StringBuilder(message);
- if (optableResponse != null) {
- formattedMessage.append("\n\nTargeting data: ");
- for (Map.Entry> entry : optableResponse.entrySet()) {
- formattedMessage.append(entry.getKey())
- .append(" = ")
- .append(entry.getValue())
- .append("\n");
- }
- }
- statusTextView.setText(formattedMessage.toString());
- }
-
- private void appendStatusText(@NonNull String message) {
- statusTextView.append("\n\n" + message);
- }
-
-}
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GamBannerFragment.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GamBannerFragment.java
new file mode 100644
index 0000000..c9fceaf
--- /dev/null
+++ b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/GamBannerFragment.java
@@ -0,0 +1,150 @@
+package co.optable.demoappjava.ui;
+
+import android.os.Bundle;
+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 co.optable.android_sdk.OptableIdentifiers;
+import co.optable.android_sdk.OptableResult;
+import co.optable.android_sdk.OptableSDK;
+import co.optable.android_sdk.OptableTargeting;
+import co.optable.demoappjava.R;
+import co.optable.demoappjava.TheApplication;
+import com.google.android.gms.ads.admanager.AdManagerAdRequest;
+import com.google.android.gms.ads.admanager.AdManagerAdView;
+import kotlin.Unit;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class GamBannerFragment extends Fragment {
+
+ private AdManagerAdView mAdView;
+ private TextView statusTextView;
+
+ private OptableSDK optable;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_gambanner, container, false);
+ initUi(root);
+ optable = TheApplication.optable;
+ return root;
+ }
+
+ private void initUi(View root) {
+ mAdView = root.findViewById(R.id.publisherAdView);
+ statusTextView = root.findViewById(R.id.statusTextView);
+
+ root.findViewById(R.id.btnLoadBanner).setOnClickListener(view -> onClickLoadAd());
+ root.findViewById(R.id.btnCachedBanner).setOnClickListener(view -> onClickCachedBanner());
+ root.findViewById(R.id.btnClearCache).setOnClickListener(view -> onClickClearCache());
+ }
+
+ /**
+ * Loads targeting data and then the GAM banner
+ */
+ private void onClickLoadAd() {
+ statusTextView.setText("");
+
+ OptableIdentifiers ids = new OptableIdentifiers.Builder().email("test@test.com").build();
+ optable.targeting(ids, result -> {
+ AdManagerAdRequest.Builder requestBuilder = new AdManagerAdRequest.Builder();
+
+ if (result instanceof OptableResult.Success success) {
+ applyOptableToGam(requestBuilder, success.getData());
+ changeStatusText("Targeting success: " + success.getData().getAudiences());
+ } else if (result instanceof OptableResult.Error error) {
+ changeStatusText("Targeting error: " + error.getMessage());
+ }
+
+ mAdView.loadAd(requestBuilder.build());
+ profile();
+ witness();
+ });
+ }
+
+ /**
+ * Loads targeting data from cache and then the GAM banner
+ */
+ private void onClickCachedBanner() {
+ statusTextView.setText("");
+
+ AdManagerAdRequest.Builder requestBuilder = new AdManagerAdRequest.Builder();
+
+ OptableTargeting optableTargeting = optable.targetingFromCache();
+ if (optableTargeting != null) {
+ changeStatusText("Targeting from cache: " + optableTargeting.getAudiences());
+ applyOptableToGam(requestBuilder, optableTargeting);
+ } else {
+ changeStatusText("Targeting cache is empty");
+ }
+
+ mAdView.loadAd(requestBuilder.build());
+ profile();
+ witness();
+ }
+
+ private void applyOptableToGam(AdManagerAdRequest.Builder builder, @Nullable OptableTargeting targeting) {
+ if (targeting == null) return;
+
+ Map> audiences = targeting.getAudiences();
+ if (audiences != null) {
+ for (Map.Entry> entry : audiences.entrySet()) {
+ builder.addCustomTargeting(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ /**
+ * Clears targeting data cache.
+ */
+ private void onClickClearCache() {
+ statusTextView.setText("Clearing targeting data cache.");
+ optable.targetingClearCache();
+ }
+
+ private void profile() {
+ HashMap traits = new HashMap<>();
+ traits.put("gender", "F");
+ traits.put("age", 38);
+ traits.put("hasAccount", true);
+
+ optable.profile(traits, result -> {
+ if (result instanceof OptableResult.Success) {
+ appendStatusText("Profile success");
+ } else if (result instanceof OptableResult.Error error) {
+ appendStatusText("Profile error: " + error.getMessage());
+ }
+ });
+ }
+
+ private void witness() {
+ HashMap eventProperties = new HashMap<>();
+ eventProperties.put("exampleKey", "exampleValue");
+ eventProperties.put("exampleKey2", 123);
+ eventProperties.put("exampleKey3", false);
+
+ optable.witness("GAMBannerFragment.loadAdButtonClicked", eventProperties, result -> {
+ if (result instanceof OptableResult.Success) {
+ appendStatusText("Witness success");
+ } else if (result instanceof OptableResult.Error error) {
+ appendStatusText("Witness error: " + error.getMessage());
+ }
+ });
+ }
+
+ private void changeStatusText(@NonNull String message) {
+ statusTextView.setText(message);
+ }
+
+ private void appendStatusText(@NonNull String message) {
+ statusTextView.append("\n\n" + message);
+ }
+
+}
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/Identify/IdentifyFragment.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/IdentifyFragment.java
similarity index 65%
rename from DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/Identify/IdentifyFragment.java
rename to DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/IdentifyFragment.java
index b73e02c..78a9287 100644
--- a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/Identify/IdentifyFragment.java
+++ b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/IdentifyFragment.java
@@ -1,4 +1,4 @@
-package co.optable.demoappjava.ui.Identify;
+package co.optable.demoappjava.ui;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -9,9 +9,11 @@
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
+import co.optable.android_sdk.OptableResult;
import co.optable.android_sdk.OptableSDK;
-import co.optable.demoappjava.MainActivity;
import co.optable.demoappjava.R;
+import co.optable.demoappjava.TheApplication;
+import kotlin.Unit;
public class IdentifyFragment extends Fragment {
@@ -19,10 +21,13 @@ public class IdentifyFragment extends Fragment {
private EditText emailText;
private Switch gaidSwitch;
+ private OptableSDK optable;
+
@Override
public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View root = inflater.inflate(R.layout.fragment_identify, container, false);
initUi(root);
+ optable = TheApplication.optable;
return root;
}
@@ -37,19 +42,13 @@ private void initUi(View root) {
private void onClickIdentify() {
identifyView.setText("");
- MainActivity.OPTABLE
- .identify(emailText.getText().toString(), gaidSwitch.isChecked())
- .observe(getViewLifecycleOwner(), result -> {
- String msg = "Calling identify API... ";
-
- if (result.getStatus() == OptableSDK.Status.SUCCESS) {
- msg += "Success";
- } else {
- msg += "\n\nOptableSDK Error: " + result.getMessage();
- }
-
- identifyView.setText(msg);
- });
+ optable.identify(emailText.getText().toString(), gaidSwitch.isChecked(), result -> {
+ if (result instanceof OptableResult.Success) {
+ identifyView.setText("Identify success");
+ } else if (result instanceof OptableResult.Error error) {
+ identifyView.setText("Identify error: " + error.getMessage());
+ }
+ });
}
}
diff --git a/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/PrebidBannerFragment.java b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/PrebidBannerFragment.java
new file mode 100644
index 0000000..eeb6619
--- /dev/null
+++ b/DemoApp/DemoAppJava/app/src/main/java/co/optable/demoappjava/ui/PrebidBannerFragment.java
@@ -0,0 +1,205 @@
+package co.optable.demoappjava.ui;
+
+import android.os.Bundle;
+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 co.optable.android_sdk.OptableIdentifiers;
+import co.optable.android_sdk.OptableResult;
+import co.optable.android_sdk.OptableSDK;
+import co.optable.android_sdk.OptableTargeting;
+import co.optable.demoappjava.R;
+import co.optable.demoappjava.TheApplication;
+import com.google.android.gms.ads.AdListener;
+import com.google.android.gms.ads.LoadAdError;
+import com.google.android.gms.ads.admanager.AdManagerAdRequest;
+import com.google.android.gms.ads.admanager.AdManagerAdView;
+import kotlin.Unit;
+import org.jetbrains.annotations.NotNull;
+import org.prebid.mobile.BannerAdUnit;
+import org.prebid.mobile.TargetingParams;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class PrebidBannerFragment extends Fragment {
+
+ private static final String GAM_AD_UNIT_ID = "/21808260008/prebid_demo_app_original_api_banner";
+ private static final String PREBID_CONFIG_ID = "prebid-demo-banner-320-50";
+ private static final int WIDTH = 320;
+ private static final int HEIGHT = 50;
+
+ private AdManagerAdView adView;
+ private BannerAdUnit prebidAdUnit;
+
+ private ViewGroup adContainer;
+ private TextView statusTextView;
+
+ private OptableSDK optable;
+
+ @Override
+ public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View root = inflater.inflate(R.layout.fragment_prebid, container, false);
+ initUi(root);
+ optable = TheApplication.optable;
+ return root;
+ }
+
+ private void initUi(View root) {
+ statusTextView = root.findViewById(R.id.statusTextView);
+ adContainer = root.findViewById(R.id.adContainer);
+
+ root.findViewById(R.id.btnLoadBanner).setOnClickListener(view -> onClickLoadAd());
+ root.findViewById(R.id.btnCachedBanner).setOnClickListener(view -> onClickCachedBanner());
+ root.findViewById(R.id.btnClearCache).setOnClickListener(view -> onClickClearCache());
+ }
+
+ /**
+ * Loads targeting data and then the GAM banner
+ */
+ private void onClickLoadAd() {
+ statusTextView.setText("");
+
+ OptableIdentifiers ids = new OptableIdentifiers.Builder().email("test@test.com").build();
+ optable.targeting(ids, optableResult -> {
+ OptableTargeting optableTargeting = null;
+ if (optableResult instanceof OptableResult.Success success) {
+ changeStatusText("Targeting success: " + success.getData().getAudiences());
+ optableTargeting = success.getData();
+ } else if (optableResult instanceof OptableResult.Error error) {
+ changeStatusText("Targeting error: " + error.getMessage());
+ }
+
+ loadPrebidAd(optableTargeting);
+ profile();
+ witness();
+ });
+ }
+
+ private void loadPrebidAd(@Nullable OptableTargeting optableTargeting) {
+ AdManagerAdRequest.Builder adRequestBuilder = new AdManagerAdRequest.Builder();
+
+ prebidAdUnit = new BannerAdUnit(PREBID_CONFIG_ID, WIDTH, HEIGHT);
+ applyOptableToPrebid(optableTargeting);
+ prebidAdUnit.fetchDemand(adRequestBuilder, resultCode -> {
+ appendStatusText("Prebid ads loading status: " + resultCode.toString());
+ loadGamAd(adRequestBuilder, optableTargeting);
+ });
+ }
+
+ private void loadGamAd(AdManagerAdRequest.Builder requestBuilder, @Nullable OptableTargeting optableTargeting) {
+ applyOptableToGam(requestBuilder, optableTargeting);
+
+ adContainer.removeAllViews();
+
+ adView = new AdManagerAdView(requireContext());
+ adView.setAdUnitId(GAM_AD_UNIT_ID);
+ adView.setAdSizes(new com.google.android.gms.ads.AdSize(WIDTH, HEIGHT));
+ adView.setAdListener(new AdListener() {
+ @Override
+ public void onAdLoaded() {
+ super.onAdLoaded();
+ appendStatusText("Google ad loaded");
+ }
+
+ @Override
+ public void onAdFailedToLoad(@NonNull @NotNull LoadAdError loadAdError) {
+ appendStatusText("Google ad failed to load: " + loadAdError.getMessage());
+ }
+ });
+ adView.loadAd(requestBuilder.build());
+
+ adContainer.addView(adView);
+ }
+
+ /**
+ * Loads targeting data from cache and then the GAM banner
+ */
+ private void onClickCachedBanner() {
+ OptableTargeting targeting = optable.targetingFromCache();
+ if (targeting != null) {
+ changeStatusText("Targeting from cache: " + targeting.getAudiences());
+ } else {
+ changeStatusText("Targeting data cache empty.");
+ }
+
+ loadPrebidAd(targeting);
+ profile();
+ witness();
+ }
+
+ /**
+ * Clears targeting data cache.
+ */
+ private void onClickClearCache() {
+ statusTextView.setText("Clearing targeting data cache.\n\n");
+ optable.targetingClearCache();
+ }
+
+ private void applyOptableToPrebid(@Nullable OptableTargeting optableResult) {
+ if (optableResult == null) {
+ TargetingParams.setGlobalOrtbConfig(null);
+ return;
+ }
+
+ String openRtbJson = optableResult.getOpenRtbJson();
+ if (openRtbJson != null) {
+ TargetingParams.setGlobalOrtbConfig(openRtbJson);
+ }
+ }
+
+ private void applyOptableToGam(AdManagerAdRequest.Builder builder, @Nullable OptableTargeting targeting) {
+ if (targeting == null) return;
+
+ Map> audiences = targeting.getAudiences();
+ if (audiences != null) {
+ for (Map.Entry> entry : audiences.entrySet()) {
+ builder.addCustomTargeting(entry.getKey(), entry.getValue());
+ }
+ }
+ }
+
+ private void profile() {
+ HashMap traits = new HashMap<>();
+ traits.put("gender", "F");
+ traits.put("age", 38);
+ traits.put("hasAccount", true);
+
+ optable.profile(traits, result -> {
+ if (result instanceof OptableResult.Success) {
+ appendStatusText("Profile Success");
+ } else if (result instanceof OptableResult.Error error) {
+ appendStatusText("Profile Error: " + error.getMessage());
+ }
+ });
+ }
+
+ private void witness() {
+ HashMap eventProperties = new HashMap<>();
+ eventProperties.put("exampleKey", "exampleValue");
+ eventProperties.put("exampleKey2", 123);
+ eventProperties.put("exampleKey3", false);
+
+ optable.witness("GAMBannerFragment.loadAdButtonClicked", eventProperties, result -> {
+ if (result instanceof OptableResult.Success) {
+ appendStatusText("Witness Success");
+ } else if (result instanceof OptableResult.Error error) {
+ appendStatusText("Witness Error: " + error.getMessage());
+ }
+ });
+ }
+
+ private void changeStatusText(@NonNull String message) {
+ statusTextView.setText(message);
+ }
+
+ private void appendStatusText(@NonNull String message) {
+ statusTextView.append("\n\n" + message);
+ }
+
+}
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/res/layout/activity_main.xml b/DemoApp/DemoAppJava/app/src/main/res/layout/activity_main.xml
index 38c0aa8..472e2b8 100644
--- a/DemoApp/DemoAppJava/app/src/main/res/layout/activity_main.xml
+++ b/DemoApp/DemoAppJava/app/src/main/res/layout/activity_main.xml
@@ -1,33 +1,25 @@
-
-
-
+ android:orientation="vertical"
+ android:layout_height="match_parent">
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_gambanner.xml b/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_gambanner.xml
index 2fe5cbc..4ef0fcd 100644
--- a/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_gambanner.xml
+++ b/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_gambanner.xml
@@ -1,10 +1,45 @@
-
+ android:orientation="vertical"
+ tools:context=".ui.GamBannerFragment">
+
+
+
+
+
+
+
+
+
+
+ app:adUnitId="/22081946781/android-sdk-demo/mobile-leaderboard" />
-
-
+
-
+
-
+
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_identify.xml b/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_identify.xml
index 3a3f9fb..e33f755 100644
--- a/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_identify.xml
+++ b/DemoApp/DemoAppJava/app/src/main/res/layout/fragment_identify.xml
@@ -4,13 +4,15 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".ui.Identify.IdentifyFragment">
+ android:paddingTop="50dp"
+ tools:context=".ui.IdentifyFragment">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/res/menu/bottom_nav_menu.xml b/DemoApp/DemoAppJava/app/src/main/res/menu/bottom_nav_menu.xml
index 10eb35f..897adf3 100644
--- a/DemoApp/DemoAppJava/app/src/main/res/menu/bottom_nav_menu.xml
+++ b/DemoApp/DemoAppJava/app/src/main/res/menu/bottom_nav_menu.xml
@@ -11,4 +11,9 @@
android:icon="@drawable/ic_gambanner_black_24dp"
android:title="GAM Banner" />
+
+
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/app/src/main/res/navigation/mobile_navigation.xml b/DemoApp/DemoAppJava/app/src/main/res/navigation/mobile_navigation.xml
index c0c1bd1..13dd083 100644
--- a/DemoApp/DemoAppJava/app/src/main/res/navigation/mobile_navigation.xml
+++ b/DemoApp/DemoAppJava/app/src/main/res/navigation/mobile_navigation.xml
@@ -7,14 +7,20 @@
+
+
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/gradle.properties b/DemoApp/DemoAppJava/gradle.properties
index c52ac9b..d71fa93 100644
--- a/DemoApp/DemoAppJava/gradle.properties
+++ b/DemoApp/DemoAppJava/gradle.properties
@@ -16,4 +16,5 @@ org.gradle.jvmargs=-Xmx2048m
# https://developer.android.com/topic/libraries/support-library/androidx-rn
android.useAndroidX=true
# Automatically convert third-party libraries to use AndroidX
-android.enableJetifier=true
\ No newline at end of file
+android.enableJetifier=true
+useReleaseSdk=false
\ No newline at end of file
diff --git a/DemoApp/DemoAppJava/settings.gradle b/DemoApp/DemoAppJava/settings.gradle
index f864b0b..f9963f4 100644
--- a/DemoApp/DemoAppJava/settings.gradle
+++ b/DemoApp/DemoAppJava/settings.gradle
@@ -16,4 +16,9 @@ dependencyResolutionManagement {
}
include ':app'
+includeBuild("../..") {
+ dependencySubstitution {
+ substitute(module("co.optable:local-sdk")).using(project(":android_sdk"))
+ }
+}
rootProject.name = "DemoJava"
\ No newline at end of file
diff --git a/DemoApp/DemoAppKotlin/app/build.gradle b/DemoApp/DemoAppKotlin/app/build.gradle
index 810d749..327d076 100644
--- a/DemoApp/DemoAppKotlin/app/build.gradle
+++ b/DemoApp/DemoAppKotlin/app/build.gradle
@@ -41,11 +41,18 @@ android {
dependencies {
// Optable SDK
- implementation "com.github.Optable:optable-android-sdk:" + versioning.getVersionName(false)
+ if (useReleaseSdk == "true") {
+ implementation "com.github.Optable:optable-android-sdk:" + versioning.getVersionName(false)
+ } else {
+ implementation "co.optable:local-sdk"
+ }
// Google Mobile Ads
implementation 'com.google.android.gms:play-services-ads:24.6.0'
+ // Prebid Ads
+ implementation "org.prebid:prebid-mobile-sdk:3.0.2"
+
// Base Android
implementation "org.jetbrains.kotlin:kotlin-stdlib:2.0.21"
implementation 'com.android.support:multidex:1.0.3'
diff --git a/DemoApp/DemoAppKotlin/app/src/main/AndroidManifest.xml b/DemoApp/DemoAppKotlin/app/src/main/AndroidManifest.xml
index cabe392..d4616e9 100644
--- a/DemoApp/DemoAppKotlin/app/src/main/AndroidManifest.xml
+++ b/DemoApp/DemoAppKotlin/app/src/main/AndroidManifest.xml
@@ -7,6 +7,7 @@
+ if (status == org.prebid.mobile.api.data.InitializationStatus.SUCCEEDED) {
+ Log.d(TAG, "SDK initialized successfully!")
+ } else {
+ Log.e(TAG, "SDK initialization error: ${status?.description}")
+ }
+ }
+ }
+
private fun initUi() {
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
- val appBarConfiguration = AppBarConfiguration(setOf(R.id.navigation_identify, R.id.navigation_gambanner))
+ val appBarConfiguration = AppBarConfiguration(
+ setOf(
+ R.id.navigation_identify,
+ R.id.navigation_gambanner,
+ )
+ )
setupActionBarWithNavController(navController, appBarConfiguration)
navView.setupWithNavController(navController)
}
diff --git a/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/TheApplication.kt b/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/TheApplication.kt
new file mode 100644
index 0000000..96b4d42
--- /dev/null
+++ b/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/TheApplication.kt
@@ -0,0 +1,20 @@
+package co.optable.androidsdkdemo
+
+import android.app.Application
+import co.optable.android_sdk.OptableConfig
+import co.optable.android_sdk.OptableSDK
+
+class TheApplication : Application() {
+
+ companion object {
+ lateinit var optable: OptableSDK
+ }
+
+ override fun onCreate() {
+ super.onCreate()
+
+ val config = OptableConfig(this, "prebidtest", "js-sdk", host = "ca.edge.optable.co")
+ optable = OptableSDK(config)
+ }
+
+}
\ No newline at end of file
diff --git a/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/ui/GAMBanner/GAMBannerFragment.kt b/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/ui/GAMBanner/GAMBannerFragment.kt
deleted file mode 100644
index 6a560aa..0000000
--- a/DemoApp/DemoAppKotlin/app/src/main/java/co/optable/androidsdkdemo/ui/GAMBanner/GAMBannerFragment.kt
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright © 2020 Optable Technologies Inc. All rights reserved.
- * See LICENSE for details.
- */
-package co.optable.androidsdkdemo.ui.GAMBanner
-
-import android.os.Bundle
-import android.view.LayoutInflater
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.TextView
-import androidx.fragment.app.Fragment
-import androidx.lifecycle.Observer
-import co.optable.android_sdk.OptableSDK
-import co.optable.android_sdk.OptableTargetingResponse
-import co.optable.androidsdkdemo.MainActivity
-import co.optable.androidsdkdemo.R
-import com.google.android.gms.ads.admanager.AdManagerAdRequest
-import com.google.android.gms.ads.admanager.AdManagerAdView
-
-class GAMBannerFragment : Fragment() {
-
- private lateinit var adView: AdManagerAdView
- private lateinit var statusTextView: TextView
-
- override fun onCreateView(
- inflater: LayoutInflater,
- container: ViewGroup?,
- savedInstanceState: Bundle?,
- ): View? {
- val root = inflater.inflate(R.layout.fragment_gambanner, container, false)
- initUi(root)
- return root
- }
-
- private fun initUi(root: View) {
- adView = root.findViewById(R.id.publisherAdView)
- statusTextView = root.findViewById(R.id.targetingDataView)
- statusTextView.text = ""
-
- root.findViewById