Repository: fbsamples/audience-network Branch: main Commit: bdd83086d558 Files: 236 Total size: 788.9 KB Directory structure: gitextract_zu2obygx/ ├── .github/ │ └── workflows/ │ └── main.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md └── samples/ ├── android/ │ ├── .gitignore │ ├── AdUnitsSample/ │ │ ├── .gitignore │ │ ├── LICENSE │ │ ├── build.gradle │ │ ├── libs/ │ │ │ ├── AudienceNetwork.aar │ │ │ └── DebugSettings.aar │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ ├── AndroidManifestVariables.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── facebook/ │ │ │ └── samples/ │ │ │ └── AdUnitsSample/ │ │ │ ├── AdUnitsSampleActivity.java │ │ │ ├── AdUnitsSampleApplication.java │ │ │ ├── AdUnitsSampleType.java │ │ │ ├── AudienceNetworkInitializeHelper.java │ │ │ ├── SampleListActivity.java │ │ │ ├── SplashActivity.java │ │ │ ├── adapters/ │ │ │ │ ├── NativeAdRecyclerAdapter.java │ │ │ │ └── SampleAdapter.java │ │ │ ├── fragments/ │ │ │ │ ├── BannerFragment.java │ │ │ │ ├── InterstitialFragment.java │ │ │ │ ├── MultiLoadInterstitialFragment.java │ │ │ │ ├── NativeAdHScrollFragment.java │ │ │ │ ├── NativeAdRecyclerFragment.java │ │ │ │ ├── NativeAdSampleFragment.java │ │ │ │ ├── NativeAdTemplateFragment.java │ │ │ │ ├── NativeBannerAdFragment.java │ │ │ │ ├── NativeBannerAdTemplateFragment.java │ │ │ │ ├── RectangleFragment.java │ │ │ │ ├── RewardedInterstitialFragment.java │ │ │ │ └── RewardedVideoFragment.java │ │ │ ├── models/ │ │ │ │ └── RecyclerPostItem.java │ │ │ └── thirdparty/ │ │ │ └── DividerItemDecoration/ │ │ │ └── DividerItemDecoration.java │ │ └── res/ │ │ ├── layout/ │ │ │ ├── activity_ad_sample.xml │ │ │ ├── activity_sample_list.xml │ │ │ ├── activity_splash.xml │ │ │ ├── fragment_banner.xml │ │ │ ├── fragment_interstitial.xml │ │ │ ├── fragment_multi_load_interstitial.xml │ │ │ ├── fragment_native_ad_hscroll.xml │ │ │ ├── fragment_native_ad_recycler.xml │ │ │ ├── fragment_native_ad_sample.xml │ │ │ ├── fragment_native_ad_template.xml │ │ │ ├── fragment_native_banner_ad.xml │ │ │ ├── fragment_native_banner_ad_template.xml │ │ │ ├── fragment_rectangle.xml │ │ │ ├── fragment_rewarded_interstitial.xml │ │ │ ├── fragment_rewarded_video.xml │ │ │ ├── list_item_section.xml │ │ │ ├── native_ad_unit.xml │ │ │ ├── native_banner_ad_unit.xml │ │ │ └── recycler_post_item.xml │ │ ├── layout-land/ │ │ │ └── fragment_rectangle.xml │ │ ├── menu/ │ │ │ └── ad_units_sample_menu.xml │ │ ├── values/ │ │ │ ├── layouts.xml │ │ │ └── strings.xml │ │ ├── values-large/ │ │ │ └── layout.xml │ │ ├── values-sw600dp/ │ │ │ └── layout.xml │ │ └── xml/ │ │ ├── locales_config.xml │ │ └── network_security_config.xml │ ├── KotlinAdUnitsSample/ │ │ ├── .gitignore │ │ ├── KotlinAdUnitsSample/ │ │ │ └── .gitignore │ │ ├── LICENSE │ │ ├── build.gradle │ │ ├── libs/ │ │ │ ├── AudienceNetwork.aar │ │ │ └── DebugSettings.aar │ │ ├── proguard-rules.pro │ │ └── src/ │ │ └── main/ │ │ ├── AndroidManifest.xml │ │ ├── java/ │ │ │ └── com/ │ │ │ └── facebook/ │ │ │ └── samples/ │ │ │ └── adunitssamplekotlin/ │ │ │ ├── AdUnitsSampleActivity.kt │ │ │ ├── AdUnitsSampleApplication.kt │ │ │ ├── AdUnitsSampleType.kt │ │ │ ├── AudienceNetworkInitializeHelper.kt │ │ │ ├── SampleListActivity.kt │ │ │ ├── SplashActivity.kt │ │ │ ├── adapters/ │ │ │ │ ├── NativeAdRecyclerAdapter.kt │ │ │ │ └── SampleAdapter.kt │ │ │ ├── fragments/ │ │ │ │ ├── BannerFragment.kt │ │ │ │ ├── InterstitialFragment.kt │ │ │ │ ├── NativeAdHScrollFragment.kt │ │ │ │ ├── NativeAdRecyclerFragment.kt │ │ │ │ ├── NativeAdSampleFragment.kt │ │ │ │ ├── NativeAdTemplateFragment.kt │ │ │ │ ├── NativeBannerAdFragment.kt │ │ │ │ ├── NativeBannerAdTemplateFragment.kt │ │ │ │ ├── RectangleFragment.kt │ │ │ │ ├── RewardedInterstitialFragment.kt │ │ │ │ ├── RewardedVideoFragment.kt │ │ │ │ └── SampleListFragment.kt │ │ │ └── models/ │ │ │ └── RecyclerPostItem.kt │ │ └── res/ │ │ ├── layout/ │ │ │ ├── activity_ad_sample.xml │ │ │ ├── activity_sample_list.xml │ │ │ ├── activity_splash.xml │ │ │ ├── fragment_banner.xml │ │ │ ├── fragment_interstitial.xml │ │ │ ├── fragment_native_ad_hscroll.xml │ │ │ ├── fragment_native_ad_recycler.xml │ │ │ ├── fragment_native_ad_sample.xml │ │ │ ├── fragment_native_ad_template.xml │ │ │ ├── fragment_native_banner_ad.xml │ │ │ ├── fragment_native_banner_ad_template.xml │ │ │ ├── fragment_rectangle.xml │ │ │ ├── fragment_rewarded_interstitial.xml │ │ │ ├── fragment_rewarded_video.xml │ │ │ ├── list_item_section.xml │ │ │ ├── native_ad_unit.xml │ │ │ ├── native_banner_ad_unit.xml │ │ │ └── recycler_post_item.xml │ │ ├── menu/ │ │ │ └── ad_units_sample_menu.xml │ │ └── values/ │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ ├── README.md │ ├── build.gradle │ ├── gradle.properties │ ├── gradlew │ ├── gradlew.bat │ └── settings.gradle ├── ios/ │ ├── AdUnitsSample/ │ │ ├── .gitignore │ │ ├── AdUnitsSample/ │ │ │ ├── AdUnitsSample-Prefix.pch │ │ │ ├── AdUnitsSample.entitlements │ │ │ ├── AdUnitsSampleStoryboard.storyboard │ │ │ ├── AppDelegate.h │ │ │ ├── AppDelegate.m │ │ │ ├── BannerViewController.h │ │ │ ├── BannerViewController.m │ │ │ ├── CollectionViewController.h │ │ │ ├── CollectionViewController.m │ │ │ ├── DebugLogsViewController.h │ │ │ ├── DebugLogsViewController.m │ │ │ ├── Images.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ └── Contents.json │ │ │ ├── Info.plist │ │ │ ├── InfoPlist.strings │ │ │ ├── InstreamViewController.h │ │ │ ├── InstreamViewController.m │ │ │ ├── InterstitialViewController.h │ │ │ ├── InterstitialViewController.m │ │ │ ├── LaunchScreen.storyboard │ │ │ ├── MediumRectViewController.h │ │ │ ├── MediumRectViewController.m │ │ │ ├── MenuTableViewController.h │ │ │ ├── MenuTableViewController.m │ │ │ ├── NativeAdTemplateViewController.h │ │ │ ├── NativeAdTemplateViewController.m │ │ │ ├── NativeBannerAdTemplateViewController.h │ │ │ ├── NativeBannerAdTemplateViewController.m │ │ │ ├── NativeBannerViewController.h │ │ │ ├── NativeBannerViewController.m │ │ │ ├── NativeViewController.h │ │ │ ├── NativeViewController.m │ │ │ ├── NavigationController.h │ │ │ ├── NavigationController.m │ │ │ ├── RewardedVideoViewController.h │ │ │ ├── RewardedVideoViewController.m │ │ │ ├── ScrollViewController.h │ │ │ ├── ScrollViewController.m │ │ │ ├── SettingsLogLevelCell.h │ │ │ ├── SettingsLogLevelCell.m │ │ │ ├── SettingsSandboxCell.h │ │ │ ├── SettingsSandboxCell.m │ │ │ ├── SettingsTableViewController.h │ │ │ ├── SettingsTableViewController.m │ │ │ ├── SettingsTestAdCell.h │ │ │ ├── SettingsTestAdCell.m │ │ │ ├── SettingsTestModeCell.h │ │ │ ├── SettingsTestModeCell.m │ │ │ ├── TableViewController.h │ │ │ ├── TableViewController.m │ │ │ └── main.m │ │ ├── AdUnitsSample.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ └── AdUnitsSample.xcscheme │ │ ├── AdUnitsSample.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── Podfile │ │ ├── ReadMe.txt │ │ └── VERSION.bzl │ ├── FANSample/ │ │ ├── .gitignore │ │ ├── FANSample/ │ │ │ ├── AppDelegate.swift │ │ │ ├── Assets.xcassets/ │ │ │ │ ├── AppIcon.appiconset/ │ │ │ │ │ └── Contents.json │ │ │ │ ├── Contents.json │ │ │ │ └── fan.imageset/ │ │ │ │ └── Contents.json │ │ │ ├── Base.lproj/ │ │ │ │ ├── LaunchScreen.storyboard │ │ │ │ └── Main.storyboard │ │ │ ├── Extensions/ │ │ │ │ ├── NSObject+ClassName.swift │ │ │ │ ├── UIView+NibContent.swift │ │ │ │ └── UIViewController+Storyboard.swift │ │ │ ├── Info.plist │ │ │ ├── Samples/ │ │ │ │ ├── BannerSampleViewController.swift │ │ │ │ ├── FullscreenAdSampleViewController.swift │ │ │ │ ├── Native/ │ │ │ │ │ ├── NativeAdScreenViewController.swift │ │ │ │ │ ├── NativeAdView.swift │ │ │ │ │ └── NativeAdView.xib │ │ │ │ ├── NativeBanner/ │ │ │ │ │ ├── NativeBannerAdScreenViewController.swift │ │ │ │ │ ├── NativeBannerAdView.swift │ │ │ │ │ └── NativeBannerAdView.xib │ │ │ │ ├── NativeBannerTemplate/ │ │ │ │ │ ├── NativeBannerTemplateAdScreenViewController.swift │ │ │ │ │ └── NativeBannerTemplateAdView.swift │ │ │ │ └── NativeTemplate/ │ │ │ │ ├── NativeTemplateAdView.swift │ │ │ │ └── NativeTemplateScreenViewController.swift │ │ │ ├── SamplesViewController.swift │ │ │ ├── SceneDelegate.swift │ │ │ ├── Settings/ │ │ │ │ ├── Picker/ │ │ │ │ │ ├── PickerTableViewCell.swift │ │ │ │ │ ├── PickerTableViewCell.xib │ │ │ │ │ └── ViewModels.swift │ │ │ │ ├── SettingScreenViewController.swift │ │ │ │ └── TestMode/ │ │ │ │ ├── TestModeTableViewCell.swift │ │ │ │ └── TestModeTableViewCell.xib │ │ │ └── Utils/ │ │ │ ├── AdUtils.swift │ │ │ ├── BottomBarView.swift │ │ │ ├── BottomBarView.xib │ │ │ └── NavigationController.swift │ │ ├── FANSample.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ ├── project.xcworkspace/ │ │ │ │ ├── contents.xcworkspacedata │ │ │ │ └── xcshareddata/ │ │ │ │ └── IDEWorkspaceChecks.plist │ │ │ └── xcshareddata/ │ │ │ └── xcschemes/ │ │ │ └── FANSample.xcscheme │ │ ├── FANSample.xcworkspace/ │ │ │ ├── contents.xcworkspacedata │ │ │ └── xcshareddata/ │ │ │ └── IDEWorkspaceChecks.plist │ │ ├── Podfile │ │ └── README.md │ └── README.md └── python/ └── ReportingAPISamples/ ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE.md ├── PATENTS.md ├── README.md ├── adnw_examples.py ├── adnw_exception.py ├── adnw_params.py ├── adnw_requests.py ├── adnw_response.py └── adnw_utils.py ================================================ FILE CONTENTS ================================================ ================================================ FILE: .github/workflows/main.yml ================================================ name: Close new issues with template on: issues: types: [opened] jobs: close-new-issues: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - uses: actions/github-script@v3 with: github-token: ${{secrets.GITHUB_TOKEN}} script: | msg = `Dear developers. You will not be able to create new bug reports on GitHub after 28 April, and existing tickets will be automatically closed.\n Instead, please use the bug report (https://developers.facebook.com/support/bugs/) tool to report a bug on Audience Network. Our engineers will get back to you as soon as possible.\n If you have any other questions or suggestions relating to Facebook Audience Network, please use the online publisher support portal (https://www.facebook.com/business/publishersupport?hc_location=ufi) to submit a request.` issue = await github.issues.get({ owner: context.issue.owner, repo: context.issue.repo, issue_number: context.issue.number, }); await github.issues.createComment({ owner: context.issue.owner, repo: context.issue.repo, issue_number: context.issue.number, body: msg, }); await github.issues.update({ owner: context.issue.owner, repo: context.issue.repo, issue_number: context.issue.number, state: "closed" }); ================================================ FILE: .gitignore ================================================ .DS_Store xcuserdata/ *.xcuserdatad *.xcuserstate *.hmap *.ipa *.dSYM.zip *.dSYM Pods/ build/ DerivedData/ ================================================ FILE: CONTRIBUTING.md ================================================

Contributing to audience-network-support

We want to make contributing to this project as easy and transparent as possible.

Pull Requests

We actively welcome your pull requests.

Contributor License Agreement ("CLA")

In order to accept your pull request, we need you to submit a CLA. You only need to do this once to work on any of Facebook's open source projects. Complete your CLA here: https://code.facebook.com/cla

Issues

We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. Facebook has a bounty program for the safe disclosure of security bugs. In those cases, please go through the process outlined on that page and do not file a public issue. ================================================ FILE: LICENSE ================================================ Copyright (c) 2016-present, Facebook, Inc. All rights reserved. You are hereby granted a non-exclusive, worldwide, royalty-free license to use, copy, modify, and distribute this software in source code or binary form for use in connection with the web services and APIs provided by Facebook. As with any software that integrates with the Facebook platform, your use of this software is subject to the Facebook Developer Principles and Policies [http://developers.facebook.com/policy/]. This copyright notice shall be included in all copies or substantial portions of the software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Audience Network Samples In this repository there are sample code that demonstrates how to use Facebook [Audience Network](https://developers.facebook.com/docs/audience-network). ## Samples * [Android](./samples/android) * [iOS](./samples/ios) * [Facebook Audience Reporting API Samples](./samples/python) ## Support You can see our [developers' site][1] for documentation on using the SDK. From 28 April 2021, if you are having technical issues or experiencing bugs, please use the [bug report][2] tool to report a bug on `Audience Network`. Our engineers will get back to you as soon as possible. If you have any other questions or suggestions relating to Facebook Audience Network, please use the online [publisher support portal][3] to submit a request. [1]: https://developers.facebook.com/docs/audience-network [2]: https://developers.facebook.com/support/bugs/ [3]: https://www.facebook.com/business/publishersupport?hc_location=ufi ================================================ FILE: samples/android/.gitignore ================================================ admob.xml # Built application files *.apk *.ap_ # Files for the ART/Dalvik VM *.dex # Java class files *.class # Generated files bin/ gen/ out/ # Gradle files .gradle/ gradle/ build/ # Local configuration file (sdk path, etc) local.properties # Proguard folder generated by Eclipse proguard/ # Log Files *.log # Android Studio Navigation editor temp files .navigation/ # Android Studio captures folder captures/ # Intellij *.iml .idea # Keystore files *.jks # External native build folder generated in Android Studio 2.2 and later .externalNativeBuild google-services.json ================================================ FILE: samples/android/AdUnitsSample/.gitignore ================================================ BUCK *.iml .gradle /local.properties /.idea/caches /.idea/libraries /.idea/modules.xml /.idea/workspace.xml /.idea/navEditor.xml /.idea/assetWizardSettings.xml .DS_Store /build /captures .externalNativeBuild ================================================ FILE: samples/android/AdUnitsSample/LICENSE ================================================ Copyright (c) Meta Platforms, Inc. and affiliates. All rights reserved. You are hereby granted a non-exclusive, worldwide, royalty-free license to use, copy, modify, and distribute this software in source code or binary form for use in connection with the web services and APIs provided by Facebook. As with any software that integrates with the Facebook platform, your use of this software is subject to the Facebook Platform Policy [http://developers.facebook.com/policy/]. This copyright notice shall be included in all copies or substantial portions of the software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: samples/android/AdUnitsSample/build.gradle ================================================ apply plugin: 'com.android.application' repositories { flatDir { dirs 'libs' } } dependencies { implementation(name: 'AudienceNetwork', ext: 'aar') implementation(name: 'DebugSettings', ext: 'aar') implementation "androidx.legacy:legacy-support-v4:$project.ANDROIDX_VERSION" implementation "androidx.recyclerview:recyclerview:$project.ANDROIDX_VERSION" implementation "androidx.appcompat:appcompat:$project.ANDROIDX_VERSION" implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation "com.google.android.gms:play-services-basement:$project.ANDROID_GOOGLE_PLAY_SERVICES_VERSION" } android { compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION) buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION useLibrary 'org.apache.http.legacy' defaultConfig { applicationId 'com.facebook.samples.AdUnitsSample' minSdkVersion Integer.parseInt(project.ANDROID_BUILD_MIN_SDK_VERSION) targetSdkVersion Integer.parseInt(project.ANDROID_BUILD_TARGET_SDK_VERSION) versionCode 1 versionName '1.0' rootProject.ext.variantRelease = false } lintOptions { abortOnError false } } ================================================ FILE: samples/android/AdUnitsSample/proguard-rules.pro ================================================ # Add project specific ProGuard rules here. # By default, the flags in this file are appended to flags specified # in /Users/songqian/android-sdk-macosx/tools/proguard/proguard-android.txt # You can edit the include path and order by changing the proguardFiles # directive in build.gradle. # # For more details, see # http://developer.android.com/guide/developing/tools/proguard.html # Add any project specific keep options here: # If your project uses WebView with JS, uncomment the following # and specify the fully qualified class name to the JavaScript interface # class: #-keepclassmembers class fqcn.of.javascript.interface.for.webview { # public *; #} ================================================ FILE: samples/android/AdUnitsSample/src/main/AndroidManifest.xml ================================================ ================================================ FILE: samples/android/AdUnitsSample/src/main/AndroidManifestVariables.xml ================================================ ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/AdUnitsSampleActivity.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import android.content.Intent; import android.os.Bundle; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.widget.LinearLayout; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.fragments.BannerFragment; import com.facebook.samples.AdUnitsSample.fragments.InterstitialFragment; import com.facebook.samples.AdUnitsSample.fragments.MultiLoadInterstitialFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeAdHScrollFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeAdRecyclerFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeAdSampleFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeAdTemplateFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeBannerAdFragment; import com.facebook.samples.AdUnitsSample.fragments.NativeBannerAdTemplateFragment; import com.facebook.samples.AdUnitsSample.fragments.RectangleFragment; import com.facebook.samples.AdUnitsSample.fragments.RewardedInterstitialFragment; import com.facebook.samples.AdUnitsSample.fragments.RewardedVideoFragment; import com.facebook.samples.ads.debugsettings.DebugSettingsActivity; @Nullsafe(Nullsafe.Mode.LOCAL) public class AdUnitsSampleActivity extends FragmentActivity { public static final String SAMPLE_TYPE = "SAMPLE_TYPE"; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If you call AudienceNetworkAds.buildInitSettings(Context).initialize() // in Application.onCreate() this call is not really necessary. // Otherwise call initialize() onCreate() of all Activities that contain ads or // from onCreate() of your Splash Activity. AudienceNetworkInitializeHelper.initialize(this); setContentView(R.layout.activity_ad_sample); LinearLayout rootLayout = findViewById(R.id.activity_ad_sample); // added check for Android 35 to fix system toolbar issue // used hard coded value, as VANILLA_ICE_CREAM won't be available for older versions if (rootLayout != null && android.os.Build.VERSION.SDK_INT >= 35) { rootLayout.setFitsSystemWindows(true); } if (savedInstanceState != null) { return; } Intent intent = getIntent(); String sampleType = intent.getStringExtra(SAMPLE_TYPE); Fragment fragment = null; if (sampleType == null) { return; } // Basic ad unit sample types AdUnitsSampleType type = AdUnitsSampleType.getSampleTypeFromName(sampleType); if (type != null) { switch (type) { case BANNER: fragment = new BannerFragment(); break; case RECTANGLE: fragment = new RectangleFragment(); break; case INTERSTITIAL: fragment = new InterstitialFragment(); break; case MULTI_LOAD_INTERSTITIAL: fragment = new MultiLoadInterstitialFragment(); break; case REWARDED_VIDEO: fragment = new RewardedVideoFragment(); break; case REWARDED_INTERSTITIAL: fragment = new RewardedInterstitialFragment(); break; case NATIVE: fragment = new NativeAdSampleFragment(); break; case NATIVE_BANNER: fragment = NativeBannerAdFragment.newInstance(false); break; case NATIVE_BANNER_WITH_IMAGE_VIEW: fragment = NativeBannerAdFragment.newInstance(true); break; case RECYCLERVIEW: fragment = new NativeAdRecyclerFragment(); break; case HSCROLL: fragment = new NativeAdHScrollFragment(); break; case TEMPLATE: fragment = new NativeAdTemplateFragment(); break; case BANNER_TEMPLATE: fragment = new NativeBannerAdTemplateFragment(); break; } Preconditions.checkNotNull(fragment).setRetainInstance(true); setTitle(type.getName()); getSupportFragmentManager() .beginTransaction() .add(R.id.fragment_container, fragment) .commit(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.ad_units_sample_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int i = item.getItemId(); if (i == R.id.debug_settings) { startActivity(new Intent(getApplicationContext(), DebugSettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/AdUnitsSampleApplication.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import android.app.Application; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.ads.debugsettings.DebugSettings; @Nullsafe(Nullsafe.Mode.LOCAL) public class AdUnitsSampleApplication extends Application { @Override public void onCreate() { super.onCreate(); DebugSettings.initialize(this); AudienceNetworkInitializeHelper.initialize(this); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/AdUnitsSampleType.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import androidx.annotation.Nullable; import com.facebook.infer.annotation.Nullsafe; @Nullsafe(Nullsafe.Mode.LOCAL) public enum AdUnitsSampleType { BANNER("Banner"), RECTANGLE("Rectangle"), INTERSTITIAL("Interstitial"), MULTI_LOAD_INTERSTITIAL("Multiple Interstitials"), REWARDED_VIDEO("Rewarded Video"), REWARDED_INTERSTITIAL("Rewarded Interstitial"), NATIVE("Native Ad"), NATIVE_BANNER("Native Banner Ad"), RECYCLERVIEW("Native Ad in RecyclerView"), HSCROLL("Native Ad in H-Scroll"), TEMPLATE("Native Ad Template"), BANNER_TEMPLATE("Native Banner Ad Template"), NATIVE_BANNER_WITH_IMAGE_VIEW("Native Banner Ad With ImageView"); private final String mName; AdUnitsSampleType(String mName) { this.mName = mName; } public String getName() { return this.mName; } public static @Nullable AdUnitsSampleType getSampleTypeFromName(String name) { for (AdUnitsSampleType type : AdUnitsSampleType.values()) { if (type.getName().contentEquals(name)) { return type; } } return null; } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/AudienceNetworkInitializeHelper.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import static com.facebook.ads.BuildConfig.DEBUG; import android.content.Context; import android.util.Log; import com.facebook.ads.AdSettings; import com.facebook.ads.AudienceNetworkAds; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.ads.debugsettings.DebugSettings; /** Sample class that shows how to call initialize() method of Audience Network SDK. */ @Nullsafe(Nullsafe.Mode.LOCAL) public class AudienceNetworkInitializeHelper implements AudienceNetworkAds.InitListener { private final Context mContext; private AudienceNetworkInitializeHelper(Context context) { mContext = context; } /** * It's recommended to call this method from Application.onCreate(). Otherwise you can call it * from all Activity.onCreate() methods for Activities that contain ads. * * @param context Application or Activity. */ static void initialize(Context context) { if (!AudienceNetworkAds.isInitialized(context)) { if (DEBUG) { AdSettings.turnOnSDKDebugger(context); } AudienceNetworkAds.buildInitSettings(context) .withInitListener(new AudienceNetworkInitializeHelper(context)) .initialize(); } } @Override public void onInitialized(AudienceNetworkAds.InitResult result) { Log.d(AudienceNetworkAds.TAG, result.getMessage()); DebugSettings.onSDKInitialized(mContext); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/SampleListActivity.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import android.app.ListActivity; import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; import android.widget.AdapterView; import androidx.fragment.app.Fragment; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.adapters.SampleAdapter; import com.facebook.samples.ads.debugsettings.DebugSettingsActivity; /** A simple {@link Fragment} subclass. */ @Nullsafe(Nullsafe.Mode.LOCAL) public class SampleListActivity extends ListActivity { private static final String TAG = SampleListActivity.class.getSimpleName(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setTitle(R.string.select_sample); final SampleAdapter adapter = new SampleAdapter(SampleListActivity.this); // Bind to our new adapter. setListAdapter(adapter); // added check for Android 35 to fix system toolbar issue // used hard coded value, as VANILLA_ICE_CREAM won't be available for older versions if (android.os.Build.VERSION.SDK_INT >= 35) { getListView().setFitsSystemWindows(true); } getListView() .setOnItemClickListener( new AdapterView.OnItemClickListener() { @Override public void onItemClick(AdapterView parent, View view, int position, long id) { Log.e(TAG, "List item clicked: " + position); SampleAdapter.Item item = (SampleAdapter.Item) adapter.getItem(position); // NULLSAFE_FIXME[Nullable Dereference] String sampleName = item.getTitle(); AdUnitsSampleType type = AdUnitsSampleType.getSampleTypeFromName(sampleName); if (type != null) { Intent intent = new Intent(SampleListActivity.this, AdUnitsSampleActivity.class); intent.putExtra(AdUnitsSampleActivity.SAMPLE_TYPE, type.getName()); startActivity(intent); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.ad_units_sample_menu, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int i = item.getItemId(); if (i == R.id.debug_settings) { startActivity(new Intent(getApplicationContext(), DebugSettingsActivity.class)); return true; } return super.onOptionsItemSelected(item); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/SplashActivity.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.view.Window; import android.view.WindowManager; import com.facebook.infer.annotation.Nullsafe; @Nullsafe(Nullsafe.Mode.LOCAL) public class SplashActivity extends Activity { private static final int SPLASH_TIME = 2000; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // If you call AudienceNetworkAds.buildInitSettings(Context).initialize() // in Application.onCreate() this call is not really necessary. // Otherwise call initialize() onCreate() of all Activities that contain ads or // from onCreate() of your Splash Activity. AudienceNetworkInitializeHelper.initialize(this); // Hide title and nav bar, must be done before setContentView. requestWindowFeature(Window.FEATURE_NO_TITLE); getWindow() // NULLSAFE_FIXME[Nullable Dereference] .setFlags( WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); setContentView(R.layout.activity_splash); final Handler handler = new Handler(Looper.getMainLooper()); handler.postDelayed( new Runnable() { @Override public void run() { Intent intent = new Intent(SplashActivity.this, SampleListActivity.class); startActivity(intent); } }, SPLASH_TIME); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/adapters/NativeAdRecyclerAdapter.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.adapters; import android.app.Activity; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.TextView; import androidx.recyclerview.widget.RecyclerView; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.AdOptionsView; import com.facebook.ads.MediaView; import com.facebook.ads.NativeAd; import com.facebook.ads.NativeAdLayout; import com.facebook.ads.NativeAdListener; import com.facebook.ads.NativeAdsManager; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.AdUnitsSample.models.RecyclerPostItem; import java.util.ArrayList; import java.util.List; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeAdRecyclerAdapter extends RecyclerView.Adapter { private List mPostItems; private List mAdItems; private NativeAdsManager mNativeAdsManager; private Activity mActivity; private static final int AD_DISPLAY_FREQUENCY = 5; private static final int POST_TYPE = 0; private static final int AD_TYPE = 1; private static final String TAG = "NativeAdsManager"; public NativeAdRecyclerAdapter( Activity activity, List postItems, NativeAdsManager nativeAdsManager) { mNativeAdsManager = nativeAdsManager; mPostItems = postItems; mAdItems = new ArrayList<>(); mActivity = activity; } @Override public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == AD_TYPE) { NativeAdLayout inflatedView = (NativeAdLayout) LayoutInflater.from(parent.getContext()) .inflate(R.layout.native_ad_unit, parent, false); return new AdHolder(inflatedView); } else { View inflatedView = LayoutInflater.from(parent.getContext()) .inflate(R.layout.recycler_post_item, parent, false); return new PostHolder(inflatedView); } } @Override public int getItemViewType(int position) { return position % AD_DISPLAY_FREQUENCY == 0 ? AD_TYPE : POST_TYPE; } @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { if (holder.getItemViewType() == AD_TYPE) { NativeAd ad; if (mAdItems.size() > position / AD_DISPLAY_FREQUENCY) { ad = mAdItems.get(position / AD_DISPLAY_FREQUENCY); } else { ad = mNativeAdsManager.nextNativeAd( new NativeAdListener() { @Override public void onMediaDownloaded(Ad ad) { // ignore } @Override public void onError(Ad ad, AdError error) { // ignore } @Override public void onAdLoaded(Ad ad) { // ignore } @Override public void onAdClicked(Ad ad) { Log.i(TAG, ((NativeAd) ad).getAdvertiserName() + " Ad Clicked"); } @Override public void onLoggingImpression(Ad ad) { Log.i(TAG, ((NativeAd) ad).getAdvertiserName() + " Ad Impression"); } }); if (!Preconditions.checkNotNull(ad).isAdInvalidated()) { mAdItems.add(ad); } else { Log.w(NativeAdRecyclerAdapter.class.getSimpleName(), "Ad is invalidated!"); } } AdHolder adHolder = (AdHolder) holder; adHolder.adChoicesContainer.removeAllViews(); if (ad != null) { adHolder.tvAdTitle.setText(ad.getAdvertiserName()); adHolder.tvAdBody.setText(ad.getAdBodyText()); adHolder.tvAdSocialContext.setText(ad.getAdSocialContext()); adHolder.tvAdSponsoredLabel.setText(R.string.sponsored); adHolder.btnAdCallToAction.setText(ad.getAdCallToAction()); adHolder.btnAdCallToAction.setVisibility( ad.hasCallToAction() ? View.VISIBLE : View.INVISIBLE); AdOptionsView adOptionsView = new AdOptionsView(mActivity, ad, adHolder.nativeAdLayout); adHolder.adChoicesContainer.addView(adOptionsView, 0); List clickableViews = new ArrayList<>(); clickableViews.add(adHolder.ivAdIcon); clickableViews.add(adHolder.mvAdMedia); clickableViews.add(adHolder.btnAdCallToAction); ad.registerViewForInteraction( adHolder.nativeAdLayout, adHolder.mvAdMedia, adHolder.ivAdIcon, clickableViews); } } else { PostHolder postHolder = (PostHolder) holder; // Calculate where the next postItem index is by subtracting ads we've shown. int index = position - (position / AD_DISPLAY_FREQUENCY) - 1; RecyclerPostItem postItem = mPostItems.get(index); postHolder.tvPostContent.setText(postItem.getPostContent()); } } @Override public int getItemCount() { return mPostItems.size() + mAdItems.size(); } private static class PostHolder extends RecyclerView.ViewHolder { TextView tvPostContent; PostHolder(View view) { super(view); // NULLSAFE_FIXME[Field Not Nullable] tvPostContent = view.findViewById(R.id.tvPostContent); } } private static class AdHolder extends RecyclerView.ViewHolder { NativeAdLayout nativeAdLayout; MediaView mvAdMedia; MediaView ivAdIcon; TextView tvAdTitle; TextView tvAdBody; TextView tvAdSocialContext; TextView tvAdSponsoredLabel; Button btnAdCallToAction; LinearLayout adChoicesContainer; AdHolder(NativeAdLayout adLayout) { super(adLayout); nativeAdLayout = adLayout; // NULLSAFE_FIXME[Field Not Nullable] mvAdMedia = adLayout.findViewById(R.id.native_ad_media); // NULLSAFE_FIXME[Field Not Nullable] tvAdTitle = adLayout.findViewById(R.id.native_ad_title); // NULLSAFE_FIXME[Field Not Nullable] tvAdBody = adLayout.findViewById(R.id.native_ad_body); // NULLSAFE_FIXME[Field Not Nullable] tvAdSocialContext = adLayout.findViewById(R.id.native_ad_social_context); // NULLSAFE_FIXME[Field Not Nullable] tvAdSponsoredLabel = adLayout.findViewById(R.id.native_ad_sponsored_label); // NULLSAFE_FIXME[Field Not Nullable] btnAdCallToAction = adLayout.findViewById(R.id.native_ad_call_to_action); // NULLSAFE_FIXME[Field Not Nullable] ivAdIcon = adLayout.findViewById(R.id.native_ad_icon); // NULLSAFE_FIXME[Field Not Nullable] adChoicesContainer = adLayout.findViewById(R.id.ad_choices_container); } } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/adapters/SampleAdapter.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.adapters; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.TextView; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.AdUnitsSampleType; import com.facebook.samples.AdUnitsSample.R; @Nullsafe(Nullsafe.Mode.LOCAL) public class SampleAdapter extends ArrayAdapter { public static class Item { private String title; private boolean isSection; public Item(String title, boolean isSection) { this.title = title; this.isSection = isSection; } public Item(String title) { this(title, false); } public String getTitle() { return title; } } private Context context; private LayoutInflater inflater; public SampleAdapter(Context context) { super(context, 0); this.context = context; // Add the samples and section headers add(new Item("Basic Samples", true)); add(new Item(AdUnitsSampleType.BANNER.getName())); add(new Item(AdUnitsSampleType.RECTANGLE.getName())); add(new Item(AdUnitsSampleType.INTERSTITIAL.getName())); add(new Item(AdUnitsSampleType.MULTI_LOAD_INTERSTITIAL.getName())); add(new Item(AdUnitsSampleType.REWARDED_VIDEO.getName())); add(new Item(AdUnitsSampleType.REWARDED_INTERSTITIAL.getName())); // Native ad samples add(new Item("Native Ad Samples", true)); add(new Item(AdUnitsSampleType.NATIVE.getName())); add(new Item(AdUnitsSampleType.NATIVE_BANNER.getName())); add(new Item(AdUnitsSampleType.RECYCLERVIEW.getName())); add(new Item(AdUnitsSampleType.HSCROLL.getName())); add(new Item(AdUnitsSampleType.TEMPLATE.getName())); add(new Item(AdUnitsSampleType.BANNER_TEMPLATE.getName())); add(new Item(AdUnitsSampleType.NATIVE_BANNER_WITH_IMAGE_VIEW.getName())); // NULLSAFE_FIXME[Field Not Nullable] this.inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); } @Override public View getView(int position, View convertView, ViewGroup parent) { View v = convertView; final Item item = (Item) getItem(position); if (item != null) { if (item.isSection) { v = inflater.inflate(R.layout.list_item_section, parent, false); v.setOnClickListener(null); v.setOnLongClickListener(null); v.setLongClickable(false); final TextView title = (TextView) v.findViewById(R.id.list_item_section_text); Preconditions.checkNotNull(title).setText(item.title); } else { v = inflater.inflate(android.R.layout.simple_list_item_1, parent, false); final TextView title = (TextView) v.findViewById(android.R.id.text1); Preconditions.checkNotNull(title).setText(item.title); } } return v; } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/BannerFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.AdListener; import com.facebook.ads.AdSize; import com.facebook.ads.AdView; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; public class BannerFragment extends Fragment implements AdListener { private static final String TAG = BannerFragment.class.getSimpleName(); private RelativeLayout bannerAdContainer; private Button refreshBannerButton; private TextView bannerStatusLabel; private @Nullable AdView bannerAdView; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_banner, container, false); bannerStatusLabel = (TextView) view.findViewById(R.id.bannerStatusLabel); bannerAdContainer = (RelativeLayout) view.findViewById(R.id.bannerAdContainer); refreshBannerButton = (Button) view.findViewById(R.id.refreshBannerButton); refreshBannerButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { loadAdView(); } }); loadAdView(); return view; } @Override public void onDestroyView() { bannerAdContainer.removeView(bannerAdView); super.onDestroyView(); } @Override public void onDestroy() { if (bannerAdView != null) { bannerAdView.destroy(); bannerAdView = null; } super.onDestroy(); } private void loadAdView() { if (bannerAdView != null) { bannerAdView.destroy(); bannerAdView = null; } // Update progress message setLabel(getString(R.string.loading_status)); // Create a banner's ad view with a unique placement ID (generate your own on the Facebook // app settings). Use different ID for each ad placement in your app. boolean isTablet = getResources().getBoolean(R.bool.is_tablet); bannerAdView = new AdView( this.getActivity(), "YOUR_PLACEMENT_ID", isTablet ? AdSize.BANNER_HEIGHT_90 : AdSize.BANNER_HEIGHT_50); // Reposition the ad and add it to the view hierarchy. bannerAdContainer.addView(bannerAdView); // Initiate a request to load an ad. bannerAdView.loadAd(bannerAdView.buildLoadAdConfig().withAdListener(this).build()); } @Override public void onError(Ad ad, AdError error) { if (ad == bannerAdView) { setLabel("Ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == bannerAdView) { setLabel(""); } } @Override public void onAdClicked(Ad ad) { DebugToast.show(requireActivity(), "Ad Clicked", Toast.LENGTH_SHORT); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); } private void setLabel(String status) { bannerStatusLabel.setText(status); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/InterstitialFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.CacheFlag; import com.facebook.ads.InterstitialAd; import com.facebook.ads.InterstitialAdExtendedListener; import com.facebook.ads.RewardData; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import java.util.EnumSet; import javax.annotation.Nullable; @Nullsafe(Nullsafe.Mode.LOCAL) public class InterstitialFragment extends Fragment implements InterstitialAdExtendedListener { private static final String TAG = InterstitialFragment.class.getSimpleName(); private TextView interstitialAdStatusLabel; private Button loadInterstitialButton; private Button showInterstitialButton; @Nullable private InterstitialAd interstitialAd; private String statusLabel = ""; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_interstitial, container, false); // NULLSAFE_FIXME[Field Not Nullable] interstitialAdStatusLabel = (TextView) view.findViewById(R.id.interstitialAdStatusLabel); // NULLSAFE_FIXME[Field Not Nullable] loadInterstitialButton = (Button) view.findViewById(R.id.loadInterstitialButton); // NULLSAFE_FIXME[Field Not Nullable] showInterstitialButton = (Button) view.findViewById(R.id.showInterstitialButton); loadInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (interstitialAd != null) { interstitialAd.destroy(); interstitialAd = null; } setLabel("Loading interstitial ad..."); // Create the interstitial unit with a placement ID (generate your own on the Facebook // app settings). // Use different ID for each ad placement in your app. interstitialAd = // NULLSAFE_FIXME[Parameter Not Nullable] new InterstitialAd(InterstitialFragment.this.getActivity(), "YOUR_PLACEMENT_ID"); // Load a new interstitial. InterstitialAd.InterstitialLoadAdConfig loadAdConfig = interstitialAd .buildLoadAdConfig() // Set a listener to get notified on changes // or when the user interact with the ad. .withAdListener(InterstitialFragment.this) .withCacheFlags(EnumSet.of(CacheFlag.VIDEO)) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); interstitialAd.loadAd(loadAdConfig); } }); showInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (interstitialAd == null || !interstitialAd.isAdLoaded() || interstitialAd.isAdInvalidated()) { // Ad not ready to show. setLabel("Ad not loaded. Click load to request an ad."); } else { // Ad was loaded, show it! setLabel(""); interstitialAd.show(); } } }); return view; } @Override public void onDestroy() { if (interstitialAd != null) { interstitialAd.destroy(); interstitialAd = null; } super.onDestroy(); } @Override public void onError(Ad ad, AdError error) { if (ad == interstitialAd) { setLabel("Interstitial ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == interstitialAd) { setLabel("Ad loaded. Click show to present!"); } } @Override public void onInterstitialDisplayed(Ad ad) { showToast("Interstitial Displayed"); } @Override public void onInterstitialDismissed(Ad ad) { showToast("Interstitial Dismissed"); // Cleanup. Preconditions.checkNotNull(interstitialAd).destroy(); interstitialAd = null; } @Override public void onAdClicked(Ad ad) { showToast("Interstitial Clicked"); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); showToast("Interstitial Impression"); } private void setLabel(String label) { statusLabel = label; if (interstitialAdStatusLabel != null) { interstitialAdStatusLabel.setText(statusLabel); } } @Override public void onRewardedAdCompleted() { showToast("Reward Received"); } @Override public void onRewardedAdServerSucceeded() { showToast("Server success!"); } @Override public void onRewardedAdServerFailed() { showToast("Server failure"); } @Override public void onInterstitialActivityDestroyed() { showToast("Activity destroyed"); } private void showToast(String message) { Log.d(TAG, message); if (isAdded()) { DebugToast.show(requireActivity(), message, Toast.LENGTH_SHORT); } } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/MultiLoadInterstitialFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.CacheFlag; import com.facebook.ads.InterstitialAd; import com.facebook.ads.InterstitialAdExtendedListener; import com.facebook.ads.RewardData; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import java.util.EnumSet; public class MultiLoadInterstitialFragment extends Fragment implements InterstitialAdExtendedListener { private static final String TAG = MultiLoadInterstitialFragment.class.getSimpleName(); @Nullable private TextView mInterstitialAdStatusLabel; @Nullable private Button mLoadInterstitialButton; @Nullable private Button mShowInterstitialButton; @Nullable private InterstitialAd mInterstitialAd; @Nullable private TextView mInterstitialAdStatusLabel2; @Nullable private Button mLoadInterstitialButton2; @Nullable private Button mShowInterstitialButton2; @Nullable private InterstitialAd mInterstitialAd2; @Nullable private TextView mInterstitialAdStatusLabel3; @Nullable private Button mLoadInterstitialButton3; @Nullable private Button mShowInterstitialButton3; @Nullable private InterstitialAd mInterstitialAd3; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_multi_load_interstitial, container, false); mInterstitialAdStatusLabel = (TextView) view.findViewById(R.id.interstitialAdStatusLabel); mLoadInterstitialButton = (Button) view.findViewById(R.id.loadInterstitialButton); mShowInterstitialButton = (Button) view.findViewById(R.id.showInterstitialButton); if (mInterstitialAdStatusLabel == null || mLoadInterstitialButton == null || mShowInterstitialButton == null) { return view; } mLoadInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd != null) { mInterstitialAd.destroy(); mInterstitialAd = null; } setLabel(mInterstitialAdStatusLabel, "Loading interstitial ad..."); // Create the interstitial unit with a placement ID (generate your own on the Facebook // app settings). // Use different ID for each ad placement in your app. mInterstitialAd = new InterstitialAd( MultiLoadInterstitialFragment.this.requireActivity(), "YOUR_PLACEMENT_ID"); // Load a new interstitial. InterstitialAd.InterstitialLoadAdConfig loadAdConfig = mInterstitialAd .buildLoadAdConfig() // Set a listener to get notified on changes // or when the user interact with the ad. .withAdListener(MultiLoadInterstitialFragment.this) .withCacheFlags(EnumSet.of(CacheFlag.VIDEO)) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); mInterstitialAd.loadAd(loadAdConfig); } }); mShowInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd == null || !mInterstitialAd.isAdLoaded() || mInterstitialAd.isAdInvalidated()) { // Ad not ready to show. setLabel(mInterstitialAdStatusLabel, "Ad not loaded. Click load to request an ad."); } else { // Ad was loaded, show it! mInterstitialAd.show(); setLabel(mInterstitialAdStatusLabel, ""); } } }); mInterstitialAdStatusLabel2 = (TextView) view.findViewById(R.id.interstitialAdStatusLabel2); mLoadInterstitialButton2 = (Button) view.findViewById(R.id.loadInterstitialButton2); mShowInterstitialButton2 = (Button) view.findViewById(R.id.showInterstitialButton2); if (mInterstitialAdStatusLabel2 == null || mLoadInterstitialButton2 == null || mShowInterstitialButton2 == null) { return view; } mLoadInterstitialButton2.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd2 != null) { mInterstitialAd2.destroy(); mInterstitialAd2 = null; } setLabel(mInterstitialAdStatusLabel2, "Loading interstitial ad..."); // Create the interstitial unit with a placement ID (generate your own on the Facebook // app settings). // Use different ID for each ad placement in your app. mInterstitialAd2 = new InterstitialAd( MultiLoadInterstitialFragment.this.requireActivity(), "YOUR_PLACEMENT_ID"); // Load a new interstitial. InterstitialAd.InterstitialLoadAdConfig loadAdConfig = mInterstitialAd2 .buildLoadAdConfig() // Set a listener to get notified on changes // or when the user interact with the ad. .withAdListener(MultiLoadInterstitialFragment.this) .withCacheFlags(EnumSet.of(CacheFlag.VIDEO)) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); mInterstitialAd2.loadAd(loadAdConfig); } }); mShowInterstitialButton2.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd2 == null || !mInterstitialAd2.isAdLoaded() || mInterstitialAd2.isAdInvalidated()) { // Ad not ready to show. setLabel(mInterstitialAdStatusLabel2, "Ad not loaded. Click load to request an ad."); } else { // Ad was loaded, show it! mInterstitialAd2.show(); setLabel(mInterstitialAdStatusLabel2, ""); } } }); mInterstitialAdStatusLabel3 = (TextView) view.findViewById(R.id.interstitialAdStatusLabel3); mLoadInterstitialButton3 = (Button) view.findViewById(R.id.loadInterstitialButton3); mShowInterstitialButton3 = (Button) view.findViewById(R.id.showInterstitialButton3); if (mInterstitialAdStatusLabel3 == null || mLoadInterstitialButton3 == null || mShowInterstitialButton3 == null) { return view; } mLoadInterstitialButton3.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd3 != null) { mInterstitialAd3.destroy(); mInterstitialAd3 = null; } setLabel(mInterstitialAdStatusLabel3, "Loading interstitial ad..."); // Create the interstitial unit with a placement ID (generate your own on the Facebook // app settings). // Use different ID for each ad placement in your app. mInterstitialAd3 = new InterstitialAd( MultiLoadInterstitialFragment.this.requireActivity(), "YOUR_PLACEMENT_ID"); // Load a new interstitial. InterstitialAd.InterstitialLoadAdConfig loadAdConfig = mInterstitialAd3 .buildLoadAdConfig() // Set a listener to get notified on changes // or when the user interact with the ad. .withAdListener(MultiLoadInterstitialFragment.this) .withCacheFlags(EnumSet.of(CacheFlag.VIDEO)) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); mInterstitialAd3.loadAd(loadAdConfig); } }); mShowInterstitialButton3.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (mInterstitialAd3 == null || !mInterstitialAd3.isAdLoaded() || mInterstitialAd3.isAdInvalidated()) { // Ad not ready to show. setLabel(mInterstitialAdStatusLabel3, "Ad not loaded. Click load to request an ad."); } else { // Ad was loaded, show it! mInterstitialAd3.show(); setLabel(mInterstitialAdStatusLabel3, ""); } } }); return view; } private void destroy(@Nullable InterstitialAd interstitialAd) { if (interstitialAd != null) { interstitialAd.destroy(); interstitialAd = null; } } @Override public void onDestroy() { super.onDestroy(); } @Override public void onDestroyView() { super.onDestroyView(); destroy(mInterstitialAd); destroy(mInterstitialAd2); destroy(mInterstitialAd3); mInterstitialAdStatusLabel = null; mInterstitialAdStatusLabel2 = null; mInterstitialAdStatusLabel3 = null; mLoadInterstitialButton = null; mLoadInterstitialButton2 = null; mLoadInterstitialButton3 = null; mShowInterstitialButton = null; mShowInterstitialButton2 = null; mShowInterstitialButton3 = null; } @Override public void onError(Ad ad, AdError error) { if (ad == mInterstitialAd) { setLabel( mInterstitialAdStatusLabel, "Interstitial ad failed to load: " + error.getErrorMessage()); } else if (ad == mInterstitialAd2) { setLabel( mInterstitialAdStatusLabel2, "Interstitial ad failed to load: " + error.getErrorMessage()); } else if (ad == mInterstitialAd3) { setLabel( mInterstitialAdStatusLabel3, "Interstitial ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == mInterstitialAd) { setLabel(mInterstitialAdStatusLabel, "Ad loaded. Click show to present!"); } else if (ad == mInterstitialAd2) { setLabel(mInterstitialAdStatusLabel2, "Ad loaded. Click show to present!"); } else if (ad == mInterstitialAd3) { setLabel(mInterstitialAdStatusLabel3, "Ad loaded. Click show to present!"); } } @Override public void onInterstitialDisplayed(Ad ad) { showToast("Interstitial Displayed"); } @Override public void onInterstitialDismissed(Ad ad) { showToast("Interstitial Dismissed"); // Cleanup. if (ad == mInterstitialAd) { destroy(mInterstitialAd); } else if (ad == mInterstitialAd2) { destroy(mInterstitialAd2); } else if (ad == mInterstitialAd3) { destroy(mInterstitialAd3); } } @Override public void onAdClicked(Ad ad) { showToast("Interstitial Clicked"); } /** showing toast for tracking impression for manual testing */ @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); showToast("Interstitial Impression"); } private void setLabel(@Nullable TextView interstitialAdStatusLabel, String label) { if (interstitialAdStatusLabel != null) { interstitialAdStatusLabel.setText(label); } } @Override public void onRewardedAdCompleted() {} @Override public void onRewardedAdServerSucceeded() {} @Override public void onRewardedAdServerFailed() {} @Override public void onInterstitialActivityDestroyed() { showToast("Activity destroyed"); } private void showToast(String message) { Log.d(TAG, message); if (isAdded()) { DebugToast.show(requireActivity(), message, Toast.LENGTH_SHORT); } } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeAdHScrollFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.AdError; import com.facebook.ads.NativeAd; import com.facebook.ads.NativeAdScrollView; import com.facebook.ads.NativeAdsManager; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeAdHScrollFragment extends Fragment implements NativeAdsManager.Listener { private static final int NATIVE_AD_VIEW_HEIGHT_DP = 300; private NativeAdsManager manager; private @Nullable NativeAdScrollView scrollView; private LinearLayout scrollViewContainer; @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_native_ad_hscroll, container, false); // Create native options to enable or disable the different options on media NativeAd.NativeOptions nativeOptions = new NativeAd.NativeOptions() .setDisableFullScreen(false) .setHideMediaControls(false) .setUnMuteVolume(false); manager = new NativeAdsManager(requireActivity(), "YOUR_PLACEMENT_ID", 5, nativeOptions); manager.setListener(this); manager.loadAds(NativeAd.MediaCacheFlag.ALL); Button reloadButton = (Button) view.findViewById(R.id.reload_hscroll); Preconditions.checkNotNull(reloadButton) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { manager.loadAds(); } }); // NULLSAFE_FIXME[Field Not Nullable] scrollViewContainer = (LinearLayout) view.findViewById(R.id.hscroll_container); return view; } @Override public void onAdsLoaded() { if (getActivity() == null) { return; } DebugToast.show(getActivity(), "Ads loaded", Toast.LENGTH_SHORT); if (scrollView != null) { scrollViewContainer.removeView(scrollView); } scrollView = new NativeAdScrollView(getActivity(), manager, NATIVE_AD_VIEW_HEIGHT_DP); scrollViewContainer.addView(scrollView); } @Override public void onAdError(AdError error) { DebugToast.show(requireActivity(), "Ad error: " + error.getErrorMessage(), Toast.LENGTH_SHORT); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeAdRecyclerFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.facebook.ads.AdError; import com.facebook.ads.NativeAd; import com.facebook.ads.NativeAdsManager; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.AdUnitsSample.adapters.NativeAdRecyclerAdapter; import com.facebook.samples.AdUnitsSample.models.RecyclerPostItem; import com.facebook.samples.AdUnitsSample.thirdparty.DividerItemDecoration.DividerItemDecoration; import java.util.ArrayList; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeAdRecyclerFragment extends Fragment implements NativeAdsManager.Listener { private ArrayList mPostItemList; private NativeAdsManager mNativeAdsManager; private RecyclerView mRecyclerView; @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { // Create some dummy post items mPostItemList = new ArrayList<>(); for (int i = 1; i <= 100; i++) { mPostItemList.add(new RecyclerPostItem("RecyclerView Item #" + i)); } String placement_id = "YOUR_PLACEMENT_ID"; // Create native options to enable or disable the different options on media NativeAd.NativeOptions nativeOptions = new NativeAd.NativeOptions() .setDisableFullScreen(false) .setHideMediaControls(false) .setUnMuteVolume(false); mNativeAdsManager = new NativeAdsManager(requireActivity(), placement_id, 5, nativeOptions); mNativeAdsManager.loadAds(); mNativeAdsManager.setListener(this); // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_native_ad_recycler, container, false); // NULLSAFE_FIXME[Field Not Nullable] mRecyclerView = (RecyclerView) view.findViewById(R.id.recyclerView); return view; } @Override public void onAdsLoaded() { if (getActivity() == null) { return; } mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); RecyclerView.ItemDecoration itemDecoration = new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST); mRecyclerView.addItemDecoration(itemDecoration); NativeAdRecyclerAdapter adapter = new NativeAdRecyclerAdapter(getActivity(), mPostItemList, mNativeAdsManager); mRecyclerView.setAdapter(adapter); } @Override public void onAdError(AdError error) {} } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeAdSampleFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.LinearLayout; import android.widget.Switch; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdClosedListener; import com.facebook.ads.AdError; import com.facebook.ads.AdOptionsView; import com.facebook.ads.MediaView; import com.facebook.ads.MediaViewListener; import com.facebook.ads.NativeAd; import com.facebook.ads.NativeAdBase.NativeComponentTag; import com.facebook.ads.NativeAdLayout; import com.facebook.ads.NativeAdListener; import com.facebook.common.preconditions.Preconditions; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import java.util.ArrayList; import java.util.List; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeAdSampleFragment extends Fragment implements NativeAdListener { protected static final String TAG = NativeAdSampleFragment.class.getSimpleName(); private @Nullable TextView nativeAdStatus; private @Nullable LinearLayout adChoicesContainer; private @Nullable NativeAdLayout nativeAdLayout; private @Nullable NativeAd nativeAd; private @Nullable AdOptionsView adOptionsView; // NULLSAFE_FIXME[Field Not Initialized] private MediaView nativeAdMedia; private NativeAd.NativeOptions mNativeOptions; @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_native_ad_sample, container, false); nativeAdLayout = view.findViewById(R.id.native_ad_container); nativeAdStatus = view.findViewById(R.id.native_ad_status); adChoicesContainer = view.findViewById(R.id.ad_choices_container); // Create native options to enable or disable the different options on media mNativeOptions = new NativeAd.NativeOptions(); Switch disableFullScreenSwitch = view.findViewById(R.id.switch_fullscreen); if (disableFullScreenSwitch != null) { disableFullScreenSwitch.setOnCheckedChangeListener( (compoundButton, isChecked) -> mNativeOptions.setDisableFullScreen(isChecked)); } Switch unMuteSwitch = view.findViewById(R.id.switch_unmute); if (unMuteSwitch != null) { unMuteSwitch.setOnCheckedChangeListener( (compoundButton, isChecked) -> mNativeOptions.setUnMuteVolume(isChecked)); } Switch hideMediaControlsSwitch = view.findViewById(R.id.switch_hide_media_controls); if (hideMediaControlsSwitch != null) { hideMediaControlsSwitch.setOnCheckedChangeListener( (compoundButton, isChecked) -> mNativeOptions.setHideMediaControls(isChecked)); } Button showNativeAdButton = view.findViewById(R.id.load_native_ad_button); Preconditions.checkNotNull(showNativeAdButton) .setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if (nativeAdStatus != null) { nativeAdStatus.setText(R.string.loading_status); } if (nativeAd != null) { nativeAd.destroy(); } // Create a native ad request with a unique placement ID (generate your own on the // Facebook app settings). Use different ID for each ad placement in your app. nativeAd = new NativeAd(requireActivity(), "YOUR_PLACEMENT_ID", mNativeOptions); // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to log cat when running on a device and loading an ad. // AdSettings.addTestDevice("THE HASHED ID AS PRINTED TO LOG CAT"); // Initiate a request to load an ad. nativeAd.loadAd( nativeAd .buildLoadAdConfig() .withAdListener(NativeAdSampleFragment.this) .build()); } }); // if we already have loaded ad, render it if (nativeAd != null) { onAdLoaded(nativeAd); } return view; } @Override public void onDestroyView() { adChoicesContainer = null; nativeAdLayout = null; adOptionsView = null; nativeAdStatus = null; super.onDestroyView(); } @Override public void onError(Ad ad, AdError error) { if (nativeAdStatus != null) { nativeAdStatus.setText("Ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdClicked(Ad ad) { showToast("Ad Clicked"); } @Override public void onLoggingImpression(Ad ad) { showToast("Native Impression"); } @Override public void onMediaDownloaded(Ad ad) { if (nativeAd == ad) { Log.d(TAG, "onMediaDownloaded"); } } @Override public void onAdLoaded(Ad ad) { if (nativeAd == null || nativeAd != ad) { // Race condition, load() called again before last ad was displayed return; } if (nativeAdLayout == null) { return; } // Unregister last ad nativeAd.unregisterView(); if (nativeAdStatus != null) { nativeAdStatus.setText(""); } if (!nativeAd.isAdLoaded() || nativeAd.isAdInvalidated()) { if (nativeAdStatus != null) { nativeAdStatus.setText("Ad is not loaded or invalidated."); } return; } if (adChoicesContainer != null) { // NULLSAFE_FIXME[Parameter Not Nullable] adOptionsView = new AdOptionsView(getActivity(), nativeAd, nativeAdLayout); adOptionsView.setOnAdClosedListener( new AdClosedListener() { @Override public void onAdClosed() { // Ad closed by user move to next ad showToast("Ad closed by user!"); } }); adChoicesContainer.removeAllViews(); adChoicesContainer.addView(adOptionsView, 0); } inflateAd(nativeAd, nativeAdLayout); // Registering a touch listener to log which ad component receives the touch event. // We always return false from onTouch so that we don't swallow the touch event (which // would prevent click events from reaching the NativeAd control). // The touch listener could be used to do animations. nativeAd.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int i = view.getId(); if (i == R.id.native_ad_call_to_action) { Log.d(TAG, "Call to action button clicked"); } else if (i == R.id.native_ad_media) { Log.d(TAG, "Main image clicked"); } else { Log.d(TAG, "Other ad component clicked"); } } return false; } }); } private void inflateAd(NativeAd nativeAd, View adView) { Log.d(TAG, "Aspect ratio of ad: " + nativeAd.getAspectRatio()); // Create native UI using the ad metadata. MediaView nativeAdIcon = adView.findViewById(R.id.native_ad_icon); TextView nativeAdTitle = adView.findViewById(R.id.native_ad_title); TextView nativeAdBody = adView.findViewById(R.id.native_ad_body); TextView sponsoredLabel = adView.findViewById(R.id.native_ad_sponsored_label); TextView nativeAdSocialContext = adView.findViewById(R.id.native_ad_social_context); Button nativeAdCallToAction = adView.findViewById(R.id.native_ad_call_to_action); // NULLSAFE_FIXME[Field Not Nullable] nativeAdMedia = adView.findViewById(R.id.native_ad_media); nativeAdMedia.setListener(getMediaViewListener()); // Setting the Text Preconditions.checkNotNull(nativeAdSocialContext).setText(nativeAd.getAdSocialContext()); // NULLSAFE_FIXME[Nullable Dereference] nativeAdCallToAction.setText(nativeAd.getAdCallToAction()); // NULLSAFE_FIXME[Nullable Dereference] nativeAdCallToAction.setVisibility(nativeAd.hasCallToAction() ? View.VISIBLE : View.INVISIBLE); // NULLSAFE_FIXME[Nullable Dereference] nativeAdTitle.setText(nativeAd.getAdvertiserName()); // NULLSAFE_FIXME[Nullable Dereference] nativeAdBody.setText(nativeAd.getAdBodyText()); // NULLSAFE_FIXME[Nullable Dereference] sponsoredLabel.setText(R.string.sponsored); // You can use the following to specify the clickable areas. List clickableViews = new ArrayList<>(); clickableViews.add(nativeAdIcon); clickableViews.add(nativeAdMedia); clickableViews.add(nativeAdCallToAction); nativeAd.registerViewForInteraction( // NULLSAFE_FIXME[Parameter Not Nullable] nativeAdLayout, nativeAdMedia, nativeAdIcon, clickableViews); if (nativeAdMedia.isVideoContent()) { showToast("This is video content!!!"); showToast("Video duration: " + nativeAdMedia.getVideoDuration()); } // Optional: tag views // NULLSAFE_FIXME[Parameter Not Nullable] NativeComponentTag.tagView(nativeAdIcon, NativeComponentTag.AD_ICON); // NULLSAFE_FIXME[Parameter Not Nullable] NativeComponentTag.tagView(nativeAdTitle, NativeComponentTag.AD_TITLE); // NULLSAFE_FIXME[Parameter Not Nullable] NativeComponentTag.tagView(nativeAdBody, NativeComponentTag.AD_BODY); NativeComponentTag.tagView(nativeAdSocialContext, NativeComponentTag.AD_SOCIAL_CONTEXT); // NULLSAFE_FIXME[Parameter Not Nullable] NativeComponentTag.tagView(nativeAdCallToAction, NativeComponentTag.AD_CALL_TO_ACTION); } @Override public void onDestroy() { if (nativeAdMedia != null) { nativeAdMedia.destroy(); } if (nativeAd != null) { nativeAd.unregisterView(); nativeAd.destroy(); } super.onDestroy(); } private static MediaViewListener getMediaViewListener() { return new MediaViewListener() { @Override public void onVolumeChange(MediaView mediaView, float volume) { Log.i(TAG, "MediaViewEvent: Volume " + volume); } @Override public void onPause(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: Paused"); } @Override public void onPlay(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: Play"); } @Override public void onFullscreenBackground(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: FullscreenBackground"); } @Override public void onFullscreenForeground(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: FullscreenForeground"); } @Override public void onExitFullscreen(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: ExitFullscreen"); } @Override public void onEnterFullscreen(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: EnterFullscreen"); } @Override public void onComplete(MediaView mediaView) { Log.i(TAG, "MediaViewEvent: Completed"); } }; } private void showToast(String message) { if (isAdded()) { DebugToast.show(requireActivity(), message, Toast.LENGTH_SHORT); } } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeAdTemplateFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import android.app.Activity; import android.content.res.Resources; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.SeekBar; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.NativeAd; import com.facebook.ads.NativeAdListener; import com.facebook.ads.NativeAdView; import com.facebook.ads.NativeAdViewAttributes; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeAdTemplateFragment extends Fragment implements NativeAdListener { private static final String TAG = NativeAdTemplateFragment.class.getSimpleName(); private static final int COLOR_LIGHT_GRAY = 0xff90949c; private static final int COLOR_DARK_GRAY = 0xff4e5665; private static final int COLOR_CTA_BLUE_BG = 0xff4080ff; private static final int MIN_HEIGHT_DP = 200; private static final int MAX_HEIGHT_DP = 500; private static final int DEFAULT_HEIGHT_DP = 350; private static final int DEFAULT_PROGRESS_DP = 50; private @Nullable NativeAd mNativeAd; private int mLayoutHeightDp = DEFAULT_HEIGHT_DP; private int mAdBackgroundColor, mTitleColor, mCtaTextColor, mContentColor, mCtaBgColor; private TextView mStatusText; private ViewGroup mNativeAdContainer; private Spinner mBackgroundColorSpinner; private Button mShowCodeButton, mReloadButton; private SeekBar mSeekBar; @Nullable private View mAdView; @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_native_ad_template, container, false); // NULLSAFE_FIXME[Field Not Nullable] mStatusText = view.findViewById(R.id.status); // NULLSAFE_FIXME[Field Not Nullable] mNativeAdContainer = view.findViewById(R.id.templateContainer); // NULLSAFE_FIXME[Field Not Nullable] mShowCodeButton = view.findViewById(R.id.showCodeButton); // NULLSAFE_FIXME[Field Not Nullable] mReloadButton = view.findViewById(R.id.reloadAdButton); // NULLSAFE_FIXME[Field Not Nullable] mBackgroundColorSpinner = view.findViewById(R.id.backgroundColorSpinner); // NULLSAFE_FIXME[Field Not Nullable] mSeekBar = view.findViewById(R.id.seekBar); setUpLayoutBuilders(); setUpButtons(); createAndLoadNativeAd(); return view; } @Override public void onAdLoaded(Ad ad) { if (mNativeAd == null || mNativeAd != ad) { // Race condition, load() called again before last ad was displayed return; } mStatusText.setText(R.string.ad_loaded); reloadAdContainer(); } @Override public void onError(Ad ad, AdError error) { String msg = getResources().getString(R.string.ad_load_failed, error.getErrorMessage()); mStatusText.setText(msg); } @Override public void onAdClicked(Ad ad) { mStatusText.setText(R.string.ad_clicked); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); } @Override public void onMediaDownloaded(Ad ad) { Log.d(TAG, "onMediaDownloaded"); } @Override public void onDestroy() { mNativeAd = null; super.onDestroy(); } private void createAndLoadNativeAd() { // Create a native ad request with a unique placement ID // (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. // NULLSAFE_FIXME[Parameter Not Nullable] mNativeAd = new NativeAd(getActivity(), "YOUR_PLACEMENT_ID"); // Initiate a request to load an ad. mNativeAd.loadAd(mNativeAd.buildLoadAdConfig().withAdListener(this).build()); mStatusText.setText(R.string.ad_loading); } private void reloadAdContainer() { Activity activity = getActivity(); if (activity != null && mNativeAd != null && mNativeAd.isAdLoaded() && !mNativeAd.isAdInvalidated()) { mNativeAdContainer.removeAllViews(); // Create a NativeAdViewAttributes object and set the attributes NativeAdViewAttributes attributes = new NativeAdViewAttributes() .setBackgroundColor(mAdBackgroundColor) .setTitleTextColor(mTitleColor) .setDescriptionTextColor(mContentColor) .setButtonBorderColor(mCtaTextColor) .setButtonTextColor(mCtaTextColor) .setButtonColor(mCtaBgColor); // Use NativeAdView.render to generate the ad View mAdView = NativeAdView.render(activity, mNativeAd, attributes); mNativeAdContainer.addView(mAdView, new ViewGroup.LayoutParams(MATCH_PARENT, 0)); updateAdViewParams(); mShowCodeButton.setText(R.string.show_code); } } private void setUpLayoutBuilders() { ArrayAdapter backgroundColorSpinnerAdapter = ArrayAdapter.createFromResource( // NULLSAFE_FIXME[Parameter Not Nullable] getActivity(), R.array.background_color_array, android.R.layout.simple_spinner_item); backgroundColorSpinnerAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); mBackgroundColorSpinner.setAdapter(backgroundColorSpinnerAdapter); mBackgroundColorSpinner.setOnItemSelectedListener( new android.widget.AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView arg0, View view, int position, long id) { int item = mBackgroundColorSpinner.getSelectedItemPosition(); switch (item) { case 0: mAdBackgroundColor = Color.WHITE; mTitleColor = COLOR_DARK_GRAY; mCtaTextColor = COLOR_CTA_BLUE_BG; mContentColor = COLOR_LIGHT_GRAY; mCtaBgColor = Color.WHITE; break; case 1: mAdBackgroundColor = Color.BLACK; mTitleColor = Color.WHITE; mContentColor = Color.LTGRAY; mCtaTextColor = Color.BLACK; mCtaBgColor = Color.WHITE; break; } reloadAdContainer(); } @Override public void onNothingSelected(AdapterView parent) {} }); mSeekBar.setProgress(DEFAULT_PROGRESS_DP); mSeekBar.setOnSeekBarChangeListener( new SeekBar.OnSeekBarChangeListener() { @Override public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { mLayoutHeightDp = progress * ((MAX_HEIGHT_DP - MIN_HEIGHT_DP) / 100) + MIN_HEIGHT_DP; updateAdViewParams(); } @Override public void onStartTrackingTouch(SeekBar seekBar) {} @Override public void onStopTrackingTouch(SeekBar seekBar) {} }); } private void updateAdViewParams() { if (mAdView == null) { return; } ViewGroup.LayoutParams params = mAdView.getLayoutParams(); params.height = (int) (Resources.getSystem().getDisplayMetrics().density * mLayoutHeightDp); mAdView.setLayoutParams(params); mAdView.requestLayout(); } private void setUpButtons() { mShowCodeButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mShowCodeButton.getText() == getResources().getString(R.string.show_ad)) { reloadAdContainer(); } else { showCodeInAdContainer(); } } }); mReloadButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { createAndLoadNativeAd(); } }); } private void showCodeInAdContainer() { String[] lines = getResources().getStringArray(R.array.code_snippet_mediumrect_template); StringBuilder codeSnippet = new StringBuilder(); for (String line : lines) { codeSnippet.append(line).append("\r\n"); } mNativeAdContainer.removeAllViews(); // NULLSAFE_FIXME[Parameter Not Nullable] TextView code = new TextView(getActivity()); code.setText(codeSnippet); code.setBackgroundColor(Color.WHITE); code.setTextColor(Color.BLACK); mNativeAdContainer.addView(code, 0); mShowCodeButton.setText(R.string.show_ad); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeBannerAdFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.FrameLayout; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.AdOptionsView; import com.facebook.ads.MediaView; import com.facebook.ads.NativeAdBase; import com.facebook.ads.NativeAdLayout; import com.facebook.ads.NativeAdListener; import com.facebook.ads.NativeBannerAd; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import java.util.ArrayList; import java.util.List; public class NativeBannerAdFragment extends Fragment implements NativeAdListener { public static final String USE_IMAGE_VIEW = "useImageView"; private static final String TAG = NativeBannerAdFragment.class.getSimpleName(); private LinearLayout mAdView; private FrameLayout mAdChoicesContainer; private NativeAdLayout mNativeBannerAdContainer; private @Nullable NativeBannerAd mNativeBannerAd; private TextView mNativeBannerAdStatusLabel; private boolean isAdViewAdded; private boolean mUseImageView; public static NativeBannerAdFragment newInstance(boolean useImageView) { NativeBannerAdFragment myFragment = new NativeBannerAdFragment(); Bundle args = new Bundle(); args.putBoolean(USE_IMAGE_VIEW, useImageView); myFragment.setArguments(args); return myFragment; } @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); Bundle arguments = getArguments(); if (arguments != null) { mUseImageView = arguments.getBoolean(USE_IMAGE_VIEW, false); } } @Nullable @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_native_banner_ad, container, false); mNativeBannerAdContainer = view.findViewById(R.id.native_banner_ad_container); mNativeBannerAdStatusLabel = view.findViewById(R.id.native_banner_status_label); mAdView = (LinearLayout) inflater.inflate(R.layout.native_banner_ad_unit, mNativeBannerAdContainer, false); mAdChoicesContainer = mAdView.findViewById(R.id.ad_choices_container); Button showNativeBannerAdButton = view.findViewById(R.id.refresh_native_banner_button); showNativeBannerAdButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { mNativeBannerAdStatusLabel.setText(getString(R.string.loading_status)); // Create a native ad request with a unique placement ID (generate your own on the // Facebook app settings). Use different ID for each ad placement in your app. mNativeBannerAd = new NativeBannerAd(getContext(), "YOUR_PLACEMENT_ID"); // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to log cat when running on a device and loading an ad. // AdSettings.addTestDevice("THE HASHED ID AS PRINTED TO LOG CAT"); // Initiate a request to load an ad. mNativeBannerAd.loadAd( mNativeBannerAd .buildLoadAdConfig() .withMediaCacheFlag(NativeAdBase.MediaCacheFlag.ALL) .withAdListener(NativeBannerAdFragment.this) .build()); } }); // load the Native Banner when this fragment is created // as the Banner in BannerFragment does. showNativeBannerAdButton.performClick(); return view; } @Override public void onError(Ad ad, AdError error) { mNativeBannerAdStatusLabel.setText("Ad Failed to Load: " + error.getErrorMessage()); } @Override public void onAdLoaded(Ad ad) { if (mNativeBannerAd == null || mNativeBannerAd != ad) { // Race condition, load() called again before last ad was displayed return; } if (!isAdViewAdded) { isAdViewAdded = true; mNativeBannerAdContainer.addView(mAdView); } // Unregister last ad mNativeBannerAd.unregisterView(); mNativeBannerAdStatusLabel.setText(""); if (!mNativeBannerAd.isAdLoaded() || mNativeBannerAd.isAdInvalidated()) { mNativeBannerAdStatusLabel.setText("Ad is not loaded or invalidated."); return; } // Using the AdOptionsView is optional, but your native ad unit should // be clearly delineated from the rest of your app content. See // https://developers.facebook.com/docs/audience-network/guidelines/native-ads#native // for details. We recommend using the AdOptionsView. AdOptionsView adOptionsView = new AdOptionsView( getActivity(), mNativeBannerAd, mNativeBannerAdContainer, AdOptionsView.Orientation.HORIZONTAL, 20); mAdChoicesContainer.removeAllViews(); mAdChoicesContainer.addView(adOptionsView); inflateAd(mNativeBannerAd, mAdView); // Registering a touch listener to log which ad component receives the touch event. // We always return false from onTouch so that we don't swallow the touch event (which // would prevent click events from reaching the NativeAd control). // The touch listener could be used to do animations. mNativeBannerAd.setOnTouchListener( new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int i = view.getId(); if (i == R.id.native_ad_call_to_action) { Log.d(TAG, "Call to action button clicked"); } else if (i == R.id.native_icon_view) { Log.d(TAG, "Main image clicked"); } else { Log.d(TAG, "Other ad component clicked"); } } return false; } }); } @Override public void onAdClicked(Ad ad) { DebugToast.show(requireActivity(), "Ad Clicked", Toast.LENGTH_SHORT); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); } @Override public void onMediaDownloaded(Ad ad) { Log.d(TAG, "onMediaDownloaded"); } private void inflateAd(NativeBannerAd nativeBannerAd, View adView) { // Create native UI using the ad metadata. TextView nativeAdTitle = adView.findViewById(R.id.native_ad_title); TextView nativeAdSocialContext = adView.findViewById(R.id.native_ad_social_context); TextView sponsoredLabel = adView.findViewById(R.id.native_ad_sponsored_label); Button nativeAdCallToAction = adView.findViewById(R.id.native_ad_call_to_action); // Setting the Text nativeAdCallToAction.setText(nativeBannerAd.getAdCallToAction()); nativeAdCallToAction.setVisibility( nativeBannerAd.hasCallToAction() ? View.VISIBLE : View.INVISIBLE); nativeAdTitle.setText(nativeBannerAd.getAdvertiserName()); nativeAdSocialContext.setText(nativeBannerAd.getAdSocialContext()); // You can use the following to specify the clickable areas. List clickableViews = new ArrayList<>(); clickableViews.add(nativeAdCallToAction); MediaView nativeAdIconView = adView.findViewById(R.id.native_icon_view); ImageView nativeImageViewAdIconView = adView.findViewById(R.id.image_view_icon_view); if (mUseImageView) { nativeAdIconView.setVisibility(View.GONE); nativeImageViewAdIconView.setVisibility(View.VISIBLE); nativeBannerAd.registerViewForInteraction( mNativeBannerAdContainer, nativeImageViewAdIconView, clickableViews); } else { // use MediaView nativeAdIconView.setVisibility(View.VISIBLE); nativeImageViewAdIconView.setVisibility(View.GONE); nativeBannerAd.registerViewForInteraction( mNativeBannerAdContainer, nativeAdIconView, clickableViews); } sponsoredLabel.setText(R.string.sponsored); } @Override public void onDestroy() { if (mNativeBannerAd != null) { mNativeBannerAd.unregisterView(); mNativeBannerAd = null; } super.onDestroy(); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/NativeBannerAdTemplateFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.NativeAdListener; import com.facebook.ads.NativeAdViewAttributes; import com.facebook.ads.NativeBannerAd; import com.facebook.ads.NativeBannerAdView; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; @Nullsafe(Nullsafe.Mode.LOCAL) public class NativeBannerAdTemplateFragment extends Fragment implements NativeAdListener { private static final String TAG = NativeBannerAdTemplateFragment.class.getSimpleName(); private static final int COLOR_LIGHT_GRAY = 0xff90949c; private static final int COLOR_DARK_GRAY = 0xff4e5665; private static final int COLOR_CTA_BLUE_BG = 0xff4080ff; private @Nullable NativeBannerAd mNativeBannerAd; private NativeBannerAdView.Type mViewType = NativeBannerAdView.Type.HEIGHT_100; private int mAdBackgroundColor, mTitleColor, mLinkColor, mContentColor, mCtaBgColor; private TextView mStatusText; private ViewGroup mNativeAdContainer; private Spinner mBackgroundColorSpinner; private Spinner mAdViewTypeSpinner; private Button mShowCodeButton; @Override public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_native_banner_ad_template, container, false); // NULLSAFE_FIXME[Field Not Nullable] mStatusText = view.findViewById(R.id.status); // NULLSAFE_FIXME[Field Not Nullable] mNativeAdContainer = view.findViewById(R.id.templateContainer); // NULLSAFE_FIXME[Field Not Nullable] mShowCodeButton = view.findViewById(R.id.showCodeButton); // NULLSAFE_FIXME[Field Not Nullable] mBackgroundColorSpinner = view.findViewById(R.id.backgroundColorSpinner); // NULLSAFE_FIXME[Field Not Nullable] mAdViewTypeSpinner = view.findViewById(R.id.adViewTypeSpinner); ArrayAdapter backgroundColorSpinnerAdapter = ArrayAdapter.createFromResource( // NULLSAFE_FIXME[Parameter Not Nullable] getActivity(), R.array.background_color_array, android.R.layout.simple_spinner_item); backgroundColorSpinnerAdapter.setDropDownViewResource( android.R.layout.simple_spinner_dropdown_item); mBackgroundColorSpinner.setAdapter(backgroundColorSpinnerAdapter); ArrayAdapter adViewTypeSpinnerAdapter = ArrayAdapter.createFromResource( // NULLSAFE_FIXME[Parameter Not Nullable] getActivity(), R.array.ad_bannerview_type_array, android.R.layout.simple_spinner_item); adViewTypeSpinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); mAdViewTypeSpinner.setAdapter(adViewTypeSpinnerAdapter); setSpinnerListeners(); setButtonListeners(); createAndLoadNativeAd(); return view; } protected void createAndLoadNativeAd() { // Create a native banner ad request with a unique placement ID // (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. // NULLSAFE_FIXME[Parameter Not Nullable] mNativeBannerAd = new NativeBannerAd(getContext(), "YOUR_PLACEMENT_ID"); // Initiate a request to load an ad. mNativeBannerAd.loadAd(mNativeBannerAd.buildLoadAdConfig().withAdListener(this).build()); mStatusText.setText(R.string.ad_loading); } private void reloadAdContainer() { Activity activity = getActivity(); if (activity != null && mNativeBannerAd != null && mNativeBannerAd.isAdLoaded() && !mNativeBannerAd.isAdInvalidated()) { mNativeAdContainer.removeAllViews(); // Create a NativeAdViewAttributes object and set the attributes NativeAdViewAttributes attributes = new NativeAdViewAttributes(activity) .setBackgroundColor(mAdBackgroundColor) .setTitleTextColor(mTitleColor) .setDescriptionTextColor(mContentColor) .setButtonBorderColor(mCtaBgColor) .setButtonTextColor(mLinkColor) .setButtonColor(mCtaBgColor); // Use NativeAdView.render to generate the ad View View adView = NativeBannerAdView.render(activity, mNativeBannerAd, mViewType, attributes); // Add adView to the container showing Ads mNativeAdContainer.addView(adView, 0); mNativeAdContainer.setBackgroundColor(Color.TRANSPARENT); mShowCodeButton.setText(R.string.show_code); } } private void setSpinnerListeners() { mBackgroundColorSpinner.setOnItemSelectedListener( new android.widget.AdapterView.OnItemSelectedListener() { @Override public void onItemSelected(AdapterView arg0, View view, int position, long id) { int item = mBackgroundColorSpinner.getSelectedItemPosition(); switch (item) { case 0: mAdBackgroundColor = Color.WHITE; mTitleColor = COLOR_DARK_GRAY; mLinkColor = Color.WHITE; mContentColor = COLOR_LIGHT_GRAY; mCtaBgColor = COLOR_CTA_BLUE_BG; break; case 1: mAdBackgroundColor = Color.BLACK; mTitleColor = Color.WHITE; mContentColor = Color.LTGRAY; mLinkColor = Color.BLACK; mCtaBgColor = Color.WHITE; break; } reloadAdContainer(); } @Override public void onNothingSelected(AdapterView parent) {} }); mAdViewTypeSpinner.setOnItemSelectedListener( new android.widget.AdapterView.OnItemSelectedListener() { public void onItemSelected(AdapterView arg0, View view, int position, long id) { int item = mAdViewTypeSpinner.getSelectedItemPosition(); if (item == 0) { mViewType = NativeBannerAdView.Type.HEIGHT_50; } else if (item == 1) { mViewType = NativeBannerAdView.Type.HEIGHT_100; } else if (item == 2) { mViewType = NativeBannerAdView.Type.HEIGHT_120; } reloadAdContainer(); } @Override public void onNothingSelected(AdapterView parent) {} }); } private void setButtonListeners() { mShowCodeButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (mShowCodeButton.getText() == getResources().getString(R.string.show_ad)) { reloadAdContainer(); } else { showCodeInAdContainer(); } } }); } private void showCodeInAdContainer() { String[] lines = getResources().getStringArray(R.array.code_snippet_banner_template); StringBuilder codeSnippet = new StringBuilder(); for (String line : lines) { codeSnippet.append(line).append("\r\n"); } mNativeAdContainer.removeAllViews(); // NULLSAFE_FIXME[Parameter Not Nullable] TextView code = new TextView(getActivity()); code.setText(codeSnippet); code.setBackgroundColor(Color.WHITE); code.setTextColor(Color.BLACK); mNativeAdContainer.addView(code, 0); mShowCodeButton.setText(R.string.show_ad); } @Override public void onAdLoaded(Ad ad) { if (mNativeBannerAd == null || mNativeBannerAd != ad) { // Race condition, load() called again before last ad was displayed return; } mStatusText.setText(R.string.ad_loaded); reloadAdContainer(); } @Override public void onError(Ad ad, AdError error) { String msg = getResources().getString(R.string.ad_load_failed, error.getErrorMessage()); mStatusText.setText(msg); } @Override public void onAdClicked(Ad ad) { mStatusText.setText(R.string.ad_clicked); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); } @Override public void onMediaDownloaded(Ad ad) { Log.d(TAG, "onMediaDownloaded"); } @Override public void onDestroy() { mNativeBannerAd = null; super.onDestroy(); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/RectangleFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.AdListener; import com.facebook.ads.AdSize; import com.facebook.ads.AdView; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; @Nullsafe(Nullsafe.Mode.LOCAL) public class RectangleFragment extends Fragment implements AdListener { private static final String TAG = RectangleFragment.class.getSimpleName(); private RelativeLayout rectangleAdContainer; private Button refreshRectangleButton; private TextView rectangleStatusLabel; private @Nullable AdView rectangleAdView; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_rectangle, container, false); // NULLSAFE_FIXME[Field Not Nullable] rectangleStatusLabel = (TextView) view.findViewById(R.id.rectangleStatusLabel); // NULLSAFE_FIXME[Field Not Nullable] rectangleAdContainer = (RelativeLayout) view.findViewById(R.id.rectangleAdContainer); // NULLSAFE_FIXME[Field Not Nullable] refreshRectangleButton = (Button) view.findViewById(R.id.refreshRectangleButton); refreshRectangleButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { loadAdView(); } }); loadAdView(); return view; } @Override public void onDestroyView() { rectangleAdContainer.removeView(rectangleAdView); super.onDestroyView(); } @Override public void onDestroy() { if (rectangleAdView != null) { rectangleAdView.destroy(); rectangleAdView = null; } super.onDestroy(); } private void loadAdView() { if (rectangleAdView != null) { rectangleAdView.destroy(); rectangleAdView = null; } // Update progress message setLabel(getString(R.string.loading_status)); // Create a banner's ad view with a unique placement ID (generate your own on the Facebook // app settings). Use different ID for each ad placement in your app. // NULLSAFE_FIXME[Parameter Not Nullable] rectangleAdView = new AdView(getActivity(), "YOUR_PLACEMENT_ID", AdSize.RECTANGLE_HEIGHT_250); // Reposition the ad and add it to the view hierarchy. rectangleAdContainer.addView(rectangleAdView); // Initiate a request to load an ad. rectangleAdView.loadAd(rectangleAdView.buildLoadAdConfig().withAdListener(this).build()); } @Override public void onError(Ad ad, AdError error) { if (ad == rectangleAdView) { setLabel("Ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == rectangleAdView) { setLabel(""); } } @Override public void onAdClicked(Ad ad) { DebugToast.show(requireActivity(), "Ad Clicked", Toast.LENGTH_SHORT); } @Override public void onLoggingImpression(Ad ad) { Log.d(TAG, "onLoggingImpression"); } private void setLabel(String status) { rectangleStatusLabel.setText(status); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/RewardedInterstitialFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; 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 android.widget.Toast; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.RewardData; import com.facebook.ads.RewardedInterstitialAd; import com.facebook.ads.S2SRewardedInterstitialAdListener; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import javax.annotation.Nullable; @Nullsafe(Nullsafe.Mode.LOCAL) public class RewardedInterstitialFragment extends Fragment implements S2SRewardedInterstitialAdListener { private TextView rewardedInterstitialAdStatusLabel; private Button loadRewardedInterstitialButton; private Button showRewardedInterstitialButton; @Nullable private RewardedInterstitialAd rewardedInterstitialAd; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_rewarded_interstitial, container, false); // NULLSAFE_FIXME[Field Not Nullable] rewardedInterstitialAdStatusLabel = (TextView) view.findViewById(R.id.rewardedInterstitialAdStatusLabel); // NULLSAFE_FIXME[Field Not Nullable] loadRewardedInterstitialButton = (Button) view.findViewById(R.id.loadRewardedInterstitialButton); // NULLSAFE_FIXME[Field Not Nullable] showRewardedInterstitialButton = (Button) view.findViewById(R.id.showRewardedInterstitialButton); loadRewardedInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (rewardedInterstitialAd != null) { rewardedInterstitialAd.destroy(); rewardedInterstitialAd = null; } rewardedInterstitialAd = new RewardedInterstitialAd( // NULLSAFE_FIXME[Parameter Not Nullable] RewardedInterstitialFragment.this.getActivity(), "YOUR_PLACEMENT_ID"); RewardedInterstitialAd.RewardedInterstitialLoadAdConfig loadAdConfig = rewardedInterstitialAd .buildLoadAdConfig() .withAdListener(RewardedInterstitialFragment.this) .withFailOnCacheFailureEnabled(true) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); rewardedInterstitialAd.loadAd(loadAdConfig); setStatusLabelText("Loading rewarded interstitial ad..."); } }); showRewardedInterstitialButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (rewardedInterstitialAd == null || !rewardedInterstitialAd.isAdLoaded() || rewardedInterstitialAd.isAdInvalidated()) { setStatusLabelText("Ad not loaded. Click load to request an ad."); } else { rewardedInterstitialAd.show(); setStatusLabelText(""); } } }); return view; } @Override public void onError(Ad ad, AdError error) { if (ad == rewardedInterstitialAd) { setStatusLabelText("Rewarded interstitial ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == rewardedInterstitialAd) { setStatusLabelText("Ad loaded. Click show to present!"); } } @Override public void onAdClicked(Ad ad) { showToast("Rewarded Interstitial Clicked"); } private void setStatusLabelText(String label) { if (rewardedInterstitialAdStatusLabel != null) { rewardedInterstitialAdStatusLabel.setText(label); } } private void showToast(String message) { if (isAdded()) { DebugToast.show(requireActivity(), message, Toast.LENGTH_SHORT); } } @Override public void onRewardedInterstitialCompleted() { showToast("Rewarded Interstitial View Complete"); } @Override public void onLoggingImpression(Ad ad) { showToast("Rewarded Interstitial Impression"); } @Override public void onRewardedInterstitialClosed() { showToast("Rewarded Interstitial Closed"); } @Override public void onRewardServerFailed() { showToast("Reward Video Server Failed"); } @Override public void onRewardServerSuccess() { showToast("Reward Video Server Succeeded"); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/fragments/RewardedVideoFragment.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.fragments; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import androidx.fragment.app.Fragment; import com.facebook.ads.Ad; import com.facebook.ads.AdError; import com.facebook.ads.RewardData; import com.facebook.ads.RewardedVideoAd; import com.facebook.ads.S2SRewardedVideoAdListener; import com.facebook.infer.annotation.Nullsafe; import com.facebook.samples.AdUnitsSample.R; import com.facebook.samples.ads.debugsettings.DebugToast; import javax.annotation.Nullable; @Nullsafe(Nullsafe.Mode.LOCAL) public class RewardedVideoFragment extends Fragment implements S2SRewardedVideoAdListener { private static final String TAG = "RewardedVideoFragment"; private TextView rewardedVideoAdStatusLabel; private Button loadRewardedVideoButton; private Button showRewardedVideoButton; @Nullable private RewardedVideoAd rewardedVideoAd; @Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_rewarded_video, container, false); // NULLSAFE_FIXME[Field Not Nullable] rewardedVideoAdStatusLabel = (TextView) view.findViewById(R.id.rewardedVideoAdStatusLabel); // NULLSAFE_FIXME[Field Not Nullable] loadRewardedVideoButton = (Button) view.findViewById(R.id.loadRewardedVideoButton); // NULLSAFE_FIXME[Field Not Nullable] showRewardedVideoButton = (Button) view.findViewById(R.id.showRewardedVideoButton); loadRewardedVideoButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (rewardedVideoAd != null) { rewardedVideoAd.destroy(); rewardedVideoAd = null; } rewardedVideoAd = // NULLSAFE_FIXME[Parameter Not Nullable] new RewardedVideoAd(RewardedVideoFragment.this.getActivity(), "YOUR_PLACEMENT_ID"); RewardedVideoAd.RewardedVideoLoadAdConfig loadAdConfig = rewardedVideoAd .buildLoadAdConfig() .withAdListener(RewardedVideoFragment.this) .withFailOnCacheFailureEnabled(true) .withRewardData(new RewardData("YOUR_USER_ID", "YOUR_REWARD", 10)) .build(); rewardedVideoAd.loadAd(loadAdConfig); setStatusLabelText("Loading rewarded video ad..."); } }); showRewardedVideoButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { if (rewardedVideoAd == null || !rewardedVideoAd.isAdLoaded() || rewardedVideoAd.isAdInvalidated()) { setStatusLabelText("Ad not loaded. Click load to request an ad."); } else { setStatusLabelText(""); rewardedVideoAd.show(); } } }); return view; } @Override public void onError(Ad ad, AdError error) { if (ad == rewardedVideoAd) { setStatusLabelText("Rewarded video ad failed to load: " + error.getErrorMessage()); } } @Override public void onAdLoaded(Ad ad) { if (ad == rewardedVideoAd) { setStatusLabelText("Ad loaded. Click show to present!"); } } @Override public void onAdClicked(Ad ad) { showToast("Rewarded Video Clicked"); } private void setStatusLabelText(String label) { if (rewardedVideoAdStatusLabel != null) { rewardedVideoAdStatusLabel.setText(label); } } private void showToast(String message) { Log.d(TAG, message); if (isAdded()) { DebugToast.show(requireActivity(), message, Toast.LENGTH_SHORT); } } @Override public void onRewardedVideoCompleted() { showToast("Rewarded Video View Complete"); } @Override public void onLoggingImpression(Ad ad) { showToast("Rewarded Video Impression"); } @Override public void onRewardedVideoClosed() { showToast("Rewarded Video Closed"); } @Override public void onRewardServerFailed() { showToast("Reward Video Server Failed"); } @Override public void onRewardServerSuccess() { showToast("Reward Video Server Succeeded"); } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/models/RecyclerPostItem.java ================================================ /* * Copyright (c) Meta Platforms, Inc. and affiliates. * All rights reserved. * * This source code is licensed under the license found in the * LICENSE file in the root directory of this source tree. */ package com.facebook.samples.AdUnitsSample.models; import com.facebook.infer.annotation.Nullsafe; @Nullsafe(Nullsafe.Mode.LOCAL) public class RecyclerPostItem { // NULLSAFE_FIXME[Field Not Initialized] private String postContent; public RecyclerPostItem(String postContent) { setPostContent(postContent); } public String getPostContent() { return postContent; } public void setPostContent(String postContent) { this.postContent = postContent; } } ================================================ FILE: samples/android/AdUnitsSample/src/main/java/com/facebook/samples/AdUnitsSample/thirdparty/DividerItemDecoration/DividerItemDecoration.java ================================================ /* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.facebook.samples.AdUnitsSample.thirdparty.DividerItemDecoration; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.view.View; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import com.facebook.infer.annotation.Nullsafe; @Nullsafe(Nullsafe.Mode.LOCAL) public class DividerItemDecoration extends RecyclerView.ItemDecoration { private static final int[] ATTRS = new int[] {android.R.attr.listDivider}; public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL; public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL; private Drawable mDivider; private int mOrientation; public DividerItemDecoration(Context context, int orientation) { final TypedArray a = context.obtainStyledAttributes(ATTRS); // NULLSAFE_FIXME[Field Not Nullable] mDivider = a.getDrawable(0); a.recycle(); setOrientation(orientation); } public void setOrientation(int orientation) { if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) { throw new IllegalArgumentException("invalid orientation"); } mOrientation = orientation; } @Override public void onDraw(Canvas c, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { drawVertical(c, parent); } else { drawHorizontal(c, parent); } } public void drawVertical(Canvas c, RecyclerView parent) { final int left = parent.getPaddingLeft(); final int right = parent.getWidth() - parent.getPaddingRight(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int top = child.getBottom() + params.bottomMargin; final int bottom = top + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } public void drawHorizontal(Canvas c, RecyclerView parent) { final int top = parent.getPaddingTop(); final int bottom = parent.getHeight() - parent.getPaddingBottom(); final int childCount = parent.getChildCount(); for (int i = 0; i < childCount; i++) { final View child = parent.getChildAt(i); final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); final int left = child.getRight() + params.rightMargin; final int right = left + mDivider.getIntrinsicHeight(); mDivider.setBounds(left, top, right, bottom); mDivider.draw(c); } } @Override public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) { if (mOrientation == VERTICAL_LIST) { outRect.set(0, 0, 0, mDivider.getIntrinsicHeight()); } else { outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0); } } } ================================================ FILE: samples/android/AdUnitsSample/src/main/res/layout/activity_ad_sample.xml ================================================ ================================================ FILE: samples/android/AdUnitsSample/src/main/res/layout/activity_sample_list.xml ================================================ ================================================ FILE: samples/android/AdUnitsSample/src/main/res/layout/activity_splash.xml ================================================ ================================================ FILE: samples/android/AdUnitsSample/src/main/res/layout/fragment_banner.xml ================================================ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/AppDelegate.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface AppDelegate : UIResponder @property (nonatomic, strong) UIWindow *window; @property (nonatomic, strong) UIViewController *viewController; @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/AppDelegate.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "AppDelegate.h" #import @implementation AppDelegate void installUncaughtExceptionHandler(void); - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Debug exception handler installUncaughtExceptionHandler(); [FBAudienceNetworkAds initializeWithSettings:nil completionHandler:nil]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.viewController = [[UIStoryboard storyboardWithName:@"AdUnitsSampleStoryboard" bundle:nil] instantiateInitialViewController]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } - (void)applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. } - (void)applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. } - (void)applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. } - (void)applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. } - (void)applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. } #pragma mark Exception Handling (for debugging purposes) NSString * const FBAdSignalExceptionName = @"handlerExceptionName"; NSString * const FBAdStackTraceKey = @"handlerStackTraceKey"; NSString * const FBAdSignalKey = @"handlerSignalKey"; void FBAdExceptionHandler(NSException *exception); void FBAdSignalHandler(int signal); static BOOL _displayExceptionMessage = YES; void installUncaughtExceptionHandler() { NSSetUncaughtExceptionHandler(&FBAdExceptionHandler); signal(SIGABRT, FBAdSignalHandler); signal(SIGILL, FBAdSignalHandler); signal(SIGSEGV, FBAdSignalHandler); signal(SIGFPE, FBAdSignalHandler); signal(SIGBUS, FBAdSignalHandler); signal(SIGPIPE, FBAdSignalHandler); } void FBAdExceptionHandler(NSException *exception) { if (!exception) { NSLog(@"Exception handler called with nil exception."); __builtin_trap(); } NSArray *callStack = [exception callStackSymbols]; NSLog(@"Stack trace: %@", callStack); AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; NSMutableDictionary *userInfo = [@{FBAdStackTraceKey: callStack} mutableCopy]; [userInfo addEntriesFromDictionary:exception.userInfo]; NSException *newException = [NSException exceptionWithName:exception.name reason:exception.reason userInfo:userInfo]; [delegate performSelectorOnMainThread:@selector(handleException:) withObject:newException waitUntilDone:YES]; } void FBAdSignalHandler(int signal) { NSMutableDictionary *userInfo = [@{FBAdSignalKey: @(signal)} mutableCopy]; NSMutableArray *callStack = [[NSThread callStackSymbols] mutableCopy]; if (callStack) { NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, 2)]; if ([callStack objectsAtIndexes:indexSet]) { [callStack removeObjectsAtIndexes:indexSet]; } userInfo[FBAdStackTraceKey] = callStack; NSLog(@"Stack trace: %@", callStack); } NSString *reason = [NSString stringWithFormat:@"Signal %d was raised.", signal]; NSException *exception = [NSException exceptionWithName:FBAdSignalExceptionName reason:reason userInfo:userInfo]; AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; [delegate performSelectorOnMainThread:@selector(handleException:) withObject:exception waitUntilDone:YES]; } - (void)handleException:(NSException *)exception { BOOL displayExceptionMessage = _displayExceptionMessage; _displayExceptionMessage = NO; if (displayExceptionMessage) { NSString *message = [NSString stringWithFormat:@"The app has crashed due to an unhandled exception.\n\n" @"Stack trace:\n%@\n%@", [exception reason], [[exception userInfo] objectForKey:FBAdStackTraceKey]]; UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Unhandled Exception" message:message preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:cancel]; [self.viewController presentViewController:alertController animated:YES completion:nil]; } CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFArrayRef allModesCF = CFRunLoopCopyAllModes(runLoop); NSArray *allModes = CFBridgingRelease(allModesCF); while (true) { for (NSString *mode in allModes) { CFRunLoopRunInMode((CFStringRef)mode, 0.01, false); } } } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/BannerViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface BannerViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/BannerViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "BannerViewController.h" #import @interface BannerViewController () @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) FBAdView *adView; @end @implementation BannerViewController - (void)viewDidLoad { [super viewDidLoad]; [self loadAd]; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; FBAdSize adSize = [self fbAdSize]; CGSize viewSize = self.view.bounds.size; CGSize tabBarSize = self.tabBarController.tabBar.frame.size; viewSize = CGSizeMake(viewSize.width, viewSize.height - tabBarSize.height); UIEdgeInsets insets = [self safeAreaInsets]; CGFloat bottomAlignedY = viewSize.height - adSize.size.height - insets.bottom; self.adView.frame = CGRectMake(insets.left, bottomAlignedY, viewSize.width - insets.right - insets.left, adSize.size.height); } - (UIEdgeInsets)safeAreaInsets { // Comment the following if-statement if you are not running XCode 9+ if (@available(iOS 11.0, *)) { UIWindow *window = [[UIApplication sharedApplication].delegate window]; return [window safeAreaInsets]; } return UIEdgeInsetsZero; } - (IBAction)refreshAd:(id)sender { self.adView.hidden = YES; [self loadAd]; } - (void)loadAd { if (nil != self.adView) { [self.adView removeFromSuperview]; } // Create a banner's ad view with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBAdSize adSize = [self fbAdSize]; self.adView = [[FBAdView alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID" adSize:adSize rootViewController:self]; // Set a delegate to get notified on changes or when the user interact with the ad. self.adView.delegate = self; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; // Set autoresizingMask so the rotation is automatically handled self.adView.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin| UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; // Add adView to the view hierarchy. [self.view addSubview:self.adView]; self.adStatusLabel.text = @"Loading ad..."; [self.adView loadAd]; } - (FBAdSize)fbAdSize { BOOL isIPAD = ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad); return isIPAD ? kFBAdSizeHeight90Banner : kFBAdSizeHeight50Banner; } #pragma mark - FBAdViewDelegate implementation // Implement this function if you want to change the viewController after the FBAdView // is created. The viewController will be used to present the modal view (such as the // in-app browser that can appear when an ad is clicked). //- (UIViewController *)viewControllerForPresentingModalView //{ // return self; //} - (void)adViewDidClick:(FBAdView *)adView { NSLog(@"Ad was clicked."); } - (void)adViewDidFinishHandlingClick:(FBAdView *)adView { NSLog(@"Ad did finish click handling."); } - (void)adViewDidLoad:(FBAdView *)adView { self.adStatusLabel.text = @"Ad loaded."; NSLog(@"Ad was loaded."); // Now that the ad was loaded, show the view in case it was hidden before. self.adView.hidden = NO; } - (void)adView:(FBAdView *)adView didFailWithError:(NSError *)error { self.adStatusLabel.text = [NSString stringWithFormat:@"Ad failed to load. %@", error.localizedDescription]; NSLog(@"Ad failed to load with error: %@", error); // Hide the unit since no ad is shown. self.adView.hidden = YES; } - (void)adViewWillLogImpression:(FBAdView *)adView { NSLog(@"Ad impression is being captured."); } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/CollectionViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface CollectionViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/CollectionViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "CollectionViewController.h" #import static NSInteger const kRowStrideForAdCell = 3; static NSString *const kDefaultCellIdentifier = @"kDefaultCellIdentifier"; @interface CollectionViewCell : UICollectionViewCell @property (nonatomic, strong, nullable) UILabel *textLabel; @end @implementation CollectionViewCell - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { UILabel *label = [UILabel new]; label.textColor = [UIColor blackColor]; label.numberOfLines = 2; self.textLabel = label; [self.contentView addSubview:label]; } return self; } @end @interface CollectionViewController () @property (strong, nonatomic) IBOutlet UICollectionView *collectionView; @property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator; @property (strong, nonatomic) FBNativeAdsManager *adsManager; @property (strong, nonatomic) FBNativeAdCollectionViewCellProvider *cellProvider; @property (strong, nonatomic) NSMutableArray *collectionViewContentArray; @property (assign, nonatomic) BOOL adCellsCreated; @end @implementation CollectionViewController #pragma mark - Lazy Loading - (NSMutableArray *)collectionViewContentArray { if (!_collectionViewContentArray) { _collectionViewContentArray = [NSMutableArray array]; for (NSUInteger i = 0; i < 10; i++) { [_collectionViewContentArray addObject:[NSString stringWithFormat:@"CollectionView\n Cell #%lu", (unsigned long)(i + 1)]]; } } return _collectionViewContentArray; } - (void)viewDidLoad { [super viewDidLoad]; self.collectionView.delegate = self; self.collectionView.dataSource = self; [self.collectionView registerClass:[CollectionViewCell class] forCellWithReuseIdentifier:kDefaultCellIdentifier]; [self loadNativeAd]; } - (IBAction)dismissViewController:(id)sender { [self dismissViewControllerAnimated:YES completion:nil]; } - (IBAction)refresh:(id)sender { [self loadNativeAd]; } - (void)loadNativeAd { [self.activityIndicator startAnimating]; if (!self.adsManager) { // Create a native ad manager with a unique placement ID (generate your own on the Facebook app settings) // and how many ads you would like to create. Note that you may get fewer ads than you ask for. // Use different ID for each ad placement in your app. self.adsManager = [[FBNativeAdsManager alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID" forNumAdsRequested:5]; // Set a delegate to get notified when the ads are loaded. self.adsManager.delegate = self; // Configure native ad manager to wait to call nativeAdsLoaded until all ad assets are loaded self.adsManager.mediaCachePolicy = FBNativeAdsCachePolicyAll; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; } // Load some ads [self.adsManager loadAds]; } #pragma mark FBNativeAdsManagerDelegate implementation - (void)nativeAdsLoaded { NSLog(@"Native ad was loaded, constructing native UI..."); // After the native ads have loaded we create the native ad cell provider and let it take over FBNativeAdsManager *manager = self.adsManager; self.adsManager.delegate = nil; self.adsManager = nil; // The native ad cell provider operates over a loaded ads manager and can create table cells with native // ad templates in them as well as help with the math to have a consistent distribution of ads within a table. FBNativeAdCollectionViewCellProvider *cellProvider = [[FBNativeAdCollectionViewCellProvider alloc] initWithManager:manager forType:FBNativeAdViewTypeGenericHeight300]; self.cellProvider = cellProvider; self.cellProvider.delegate = self; [self.collectionView reloadData]; [self.activityIndicator stopAnimating]; } - (void)nativeAdsFailedToLoadWithError:(NSError *)error { NSLog(@"Native ad failed to load with error: %@", error); [self.activityIndicator stopAnimating]; UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Native ad failed to load" message:@"Check console for more details" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:cancel]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma mark FBNativeAdDelegate - (void)nativeAdDidClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad was clicked."); } - (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { return 1; } - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { // In this example the ads are evenly distributed within the table every kRowStrideForAdCell-th cell. NSUInteger count = [self.collectionViewContentArray count]; count = [self.cellProvider adjustCount:count forStride:kRowStrideForAdCell] ?: count; return count; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { if ([self.cellProvider isAdCellAtIndexPath:indexPath forStride:kRowStrideForAdCell]) { return [self.cellProvider collectionView:collectionView cellForItemAtIndexPath:indexPath]; } else { indexPath = [self.cellProvider adjustNonAdCellIndexPath:indexPath forStride:kRowStrideForAdCell] ?: indexPath; CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:kDefaultCellIdentifier forIndexPath:indexPath]; cell.textLabel.text = [self.collectionViewContentArray objectAtIndex:indexPath.row]; [cell.textLabel sizeToFit]; cell.textLabel.center = cell.contentView.center; return cell; } } - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { if ([self.cellProvider isAdCellAtIndexPath:indexPath forStride:kRowStrideForAdCell]) { return (CGSize){300.0, [self.cellProvider collectionView:collectionView heightForRowAtIndexPath:indexPath]}; } else { return (CGSize){300.0, 100.0}; } } - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section { return 20.0; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/DebugLogsViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface DebugLogsViewController : UITableViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/DebugLogsViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "DebugLogsViewController.h" static NSString *const kDebugLogsCellIdentifier = @"kDebugLogsCellIdentifier"; @interface DebugLogsViewController () @property (nonatomic, strong, readonly) NSArray *tableViewCellLabels; @end @implementation DebugLogsViewController @synthesize tableViewCellLabels = _tableViewCellLabels; - (void)viewDidLoad { [super viewDidLoad]; } - (NSArray *)tableViewCellLabels { if (nil == _tableViewCellLabels) { _tableViewCellLabels = @[@"Generic Error", @"Database Error", @"Exception App Crash", @"Signal App Crash", @"Exception SDK Crash"]; } return _tableViewCellLabels; } - (void)generateGenericError { Class class = NSClassFromString(@"FBAdDebugLogging"); SEL selector = NSSelectorFromString(@"logDebugEventWithType:code:description:"); NSMethodSignature *signature = [class methodSignatureForSelector:selector]; NSUInteger errorCode = 0; NSString *eventType = @"generic"; NSString *errorDescription = @"Generic error test message"; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:class]; [invocation setSelector:selector]; [invocation setArgument:&eventType atIndex:2]; [invocation setArgument:&errorCode atIndex:3]; [invocation setArgument:&errorDescription atIndex:4]; [invocation retainArguments]; [invocation invoke]; } - (void)generateDatabaseError { Class class = NSClassFromString(@"FBAdDebugLogging"); SEL selector = NSSelectorFromString(@"logDebugEventWithType:code:description:"); NSMethodSignature *signature = [class methodSignatureForSelector:selector]; NSUInteger errorCode = 7; NSString *eventType = @"database"; NSString *errorDescription = @"Database error cannot open database test message"; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:class]; [invocation setSelector:selector]; [invocation setArgument:&eventType atIndex:2]; [invocation setArgument:&errorCode atIndex:3]; [invocation setArgument:&errorDescription atIndex:4]; [invocation retainArguments]; [invocation invoke]; } - (void)generateExceptionCrash { [[self class] staticGenerateExceptionCrash]; } + (void)staticGenerateExceptionCrash { NSString *string = nil; NSArray *array = @[string]; array = nil; } - (void)generateSignalCrash { __unsafe_unretained NSNumber *number = @4.4; [number description]; } - (void)generateSDKCrash { Class class = NSClassFromString(@"FBAdReportingItem"); id reportingItem = [class alloc]; SEL selector = NSSelectorFromString(@"initWithIdentifier:title:heading:subItems:"); NSMethodSignature *signature = [reportingItem methodSignatureForSelector:selector]; NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:reportingItem]; [invocation setSelector:selector]; [invocation setArgument:@"" atIndex:2]; [invocation setArgument:@"" atIndex:3]; [invocation setArgument:@"" atIndex:4]; [invocation retainArguments]; [invocation invoke]; selector = NSSelectorFromString(@"addSubItem:"); signature = [reportingItem methodSignatureForSelector:selector]; invocation = [NSInvocation invocationWithMethodSignature:signature]; [invocation setTarget:reportingItem]; [invocation setSelector:selector]; [invocation retainArguments]; [invocation invoke]; } #pragma mark - UITableViewDataSource implementation - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [@"Select one of the options below" uppercaseString]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return self.tableViewCellLabels.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kDebugLogsCellIdentifier forIndexPath:indexPath]; cell.textLabel.text = self.tableViewCellLabels[indexPath.row]; return cell; } #pragma mark - UITableViewDelegate implementation - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; switch (indexPath.row) { case 0: [self generateGenericError]; break; case 1: [self generateDatabaseError]; break; case 2: [self generateExceptionCrash]; break; case 3: [self generateSignalCrash]; break; case 4: [self generateSDKCrash]; break; } } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "1x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "size" : "29x29", "idiom" : "iphone", "filename" : "Icon-Small@3x.png", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "size" : "40x40", "idiom" : "iphone", "filename" : "Icon-Small-40@3x.png", "scale" : "3x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "Icon.png", "scale" : "1x" }, { "size" : "57x57", "idiom" : "iphone", "filename" : "Icon@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-Small-60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "iphone", "filename" : "Icon-Small-60@3x.png", "scale" : "3x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x" }, { "size" : "29x29", "idiom" : "ipad", "filename" : "Icon-Small.png", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-Small-40.png", "scale" : "1x" }, { "size" : "40x40", "idiom" : "ipad", "filename" : "Icon-Small-40@2x.png", "scale" : "2x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "Icon-Small-50.png", "scale" : "1x" }, { "size" : "50x50", "idiom" : "ipad", "filename" : "Icon-Small-50@2x.png", "scale" : "2x" }, { "size" : "72x72", "idiom" : "ipad", "filename" : "Icon-72.png", "scale" : "1x" }, { "size" : "72x72", "idiom" : "ipad", "filename" : "Icon-72@2x.png", "scale" : "2x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76.png", "scale" : "1x" }, { "size" : "76x76", "idiom" : "ipad", "filename" : "Icon-76@2x.png", "scale" : "2x" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x" }, { "size" : "60x60", "idiom" : "car", "filename" : "Icon-60@2x.png", "scale" : "2x" }, { "size" : "60x60", "idiom" : "car", "filename" : "Icon-60@3x.png", "scale" : "3x" }, { "size" : "24x24", "idiom" : "watch", "scale" : "2x", "role" : "notificationCenter", "subtype" : "38mm" }, { "size" : "27.5x27.5", "idiom" : "watch", "scale" : "2x", "role" : "notificationCenter", "subtype" : "42mm" }, { "size" : "29x29", "idiom" : "watch", "filename" : "Icon-Small@2x.png", "role" : "companionSettings", "scale" : "2x" }, { "size" : "29x29", "idiom" : "watch", "role" : "companionSettings", "scale" : "3x" }, { "size" : "40x40", "idiom" : "watch", "scale" : "2x", "role" : "appLauncher", "subtype" : "38mm" }, { "size" : "44x44", "idiom" : "watch", "scale" : "2x", "role" : "appLauncher", "subtype" : "40mm" }, { "size" : "50x50", "idiom" : "watch", "scale" : "2x", "role" : "appLauncher", "subtype" : "44mm" }, { "size" : "86x86", "idiom" : "watch", "scale" : "2x", "role" : "quickLook", "subtype" : "38mm" }, { "size" : "98x98", "idiom" : "watch", "scale" : "2x", "role" : "quickLook", "subtype" : "42mm" }, { "size" : "108x108", "idiom" : "watch", "scale" : "2x", "role" : "quickLook", "subtype" : "44mm" }, { "idiom" : "watch-marketing", "size" : "1024x1024", "scale" : "1x" }, { "size" : "44x44", "idiom" : "watch", "scale" : "2x", "role" : "longLook", "subtype" : "42mm" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/Images.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleDisplayName ${PRODUCT_NAME} CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1.0 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile AdUnitsSampleStoryboard UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/InfoPlist.strings ================================================ /* Localized versions of Info.plist keys */ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/InstreamViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface InstreamViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/InstreamViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "InstreamViewController.h" #import @interface InstreamViewController () @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) IBOutlet UIView *mediaView; @property (nonatomic, strong) FBInstreamAdView *adView; @end @implementation InstreamViewController - (IBAction)loadAd { // Create an instream ad view with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. [self.adView removeFromSuperview]; self.adView = [[FBInstreamAdView alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified on changes or when the user interacts with the ad. self.adView.delegate = self; // Initiate a request to load an ad. [self.adView loadAd]; self.adStatusLabel.text = @"Loading instream ad..."; } - (IBAction)showAd { if (!self.adView || !self.adView.adValid) { // Ad not ready to present. self.adStatusLabel.text = @"Ad not loaded. Click load to request an ad."; } else { // Ad is ready, present it! self.adStatusLabel.text = nil; self.adView.frame = self.mediaView.bounds; self.adView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.mediaView addSubview:self.adView]; [self.adView showAdFromRootViewController:self]; } } #pragma mark - FBInstreamAdViewDelegate implementation - (void)adViewDidLoad:(FBInstreamAdView *)adView { self.adStatusLabel.text = @"Ad loaded"; } - (void)adViewDidEnd:(FBInstreamAdView *)adView { self.adStatusLabel.text = @"Ad ended"; [self.adView removeFromSuperview]; self.adView = nil; } - (void)adView:(FBInstreamAdView *)adView didFailWithError:(NSError *)error { self.adStatusLabel.text = [NSString stringWithFormat:@"Ad failed: %@", error.localizedDescription]; [self.adView removeFromSuperview]; self.adView = nil; } - (void)adViewDidClick:(FBInstreamAdView *)adView { self.adStatusLabel.text = @"Ad clicked"; } - (void)adViewWillLogImpression:(FBInstreamAdView *)adView { self.adStatusLabel.text = @"Ad impression"; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/InterstitialViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface InterstitialViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/InterstitialViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "InterstitialViewController.h" #import @interface InterstitialViewController () @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) FBInterstitialAd *interstitialAd; @end @implementation InterstitialViewController - (IBAction)loadAd { self.adStatusLabel.text = @"Loading interstitial ad..."; // Create the interstitial unit with a placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. self.interstitialAd = [[FBInterstitialAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified on changes or when the user interact with the ad. self.interstitialAd.delegate = self; // Initiate the request to load the ad. [self.interstitialAd loadAd]; } - (IBAction)showAd { if (!self.interstitialAd || !self.interstitialAd.isAdValid) { // Ad not ready to present. self.adStatusLabel.text = @"Ad not loaded. Click load to request an ad."; } else { self.adStatusLabel.text = @"1. Tap 'Load Ad'\n2. Once ad loads, tap 'Show!' to see the ad"; // Ad is ready, present it! [self.interstitialAd showAdFromRootViewController:self]; } } #pragma mark - FBInterstitialAdDelegate implementation - (void)interstitialAdDidLoad:(FBInterstitialAd *)interstitialAd { NSLog(@"Interstitial ad was loaded. Can present now."); self.adStatusLabel.text = @"Ad loaded. Click show to present!"; } - (void)interstitialAd:(FBInterstitialAd *)interstitialAd didFailWithError:(NSError *)error { NSLog(@"Interstitial failed to load with error: %@", error.description); self.adStatusLabel.text = [NSString stringWithFormat:@"Interstitial ad failed to load. %@", error.localizedDescription]; } - (void)interstitialAdDidClick:(FBInterstitialAd *)interstitialAd { NSLog(@"Interstitial was clicked."); } - (void)interstitialAdDidClose:(FBInterstitialAd *)interstitialAd { NSLog(@"Interstitial closed."); // Optional, Cleaning up. self.interstitialAd = nil; } - (void)interstitialAdWillClose:(FBInterstitialAd *)interstitialAd { NSLog(@"Interstitial will close."); } - (void)interstitialAdWillLogImpression:(FBInterstitialAd *)interstitialAd { NSLog(@"Interstitial impression is being captured."); } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/LaunchScreen.storyboard ================================================ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/MediumRectViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface MediumRectViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/MediumRectViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "MediumRectViewController.h" #import @interface MediumRectViewController () @property (nonatomic, strong) IBOutlet UIView *adContainer; @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) FBAdView *mediumRectAdView; @end @implementation MediumRectViewController - (void)viewDidLoad { [super viewDidLoad]; [self loadAd]; } - (IBAction)refreshAd:(id)sender { self.mediumRectAdView.hidden = YES; [self loadAd]; } - (void)loadAd { if (nil != self.mediumRectAdView) { [self.mediumRectAdView removeFromSuperview]; } // Create the medium rectangle unit with a placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBAdSize adSize = kFBAdSizeHeight250Rectangle; self.mediumRectAdView = [[FBAdView alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID" adSize:adSize rootViewController:self]; self.mediumRectAdView.hidden = YES; // Set a delegate to get notified on changes or when the user interact with the ad. self.mediumRectAdView.delegate = self; // Reposition the adView self.mediumRectAdView.frame = CGRectMake(0, 0, 300, 250); [self.adContainer addSubview:self.mediumRectAdView]; self.adStatusLabel.text = @"Loading ad..."; [self.mediumRectAdView loadAd]; } #pragma mark - FBAdViewDelegate implementation // Implement this function if you want to change the viewController after the FBAdView // is created. The viewController will be used to present the modal view (such as the // in-app browser that can appear when an ad is clicked). // - (UIViewController *)viewControllerForPresentingModalView // { // return self; // } - (void)adViewDidClick:(FBAdView *)adView { NSLog(@"Ad was clicked."); } - (void)adViewDidFinishHandlingClick:(FBAdView *)adView { NSLog(@"Ad did finish click handling."); } - (void)adViewDidLoad:(FBAdView *)adView { self.adStatusLabel.text = @"Ad loaded."; NSLog(@"Ad was loaded."); // Now that the ad was loaded, show the view in case it was hidden before. self.mediumRectAdView.hidden = NO; } - (void)adView:(FBAdView *)adView didFailWithError:(NSError *)error { self.adStatusLabel.text = [NSString stringWithFormat:@"Ad failed to load. Check console for details. %@", error.localizedDescription]; NSLog(@"Ad failed to load with error: %@", error); // Hide the unit since no ad is shown. self.mediumRectAdView.hidden = YES; } - (void)adViewWillLogImpression:(FBAdView *)adView { NSLog(@"Ad impression is being captured."); } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/MenuTableViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface MenuTableViewController : UITableViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/MenuTableViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "MenuTableViewController.h" @interface MenuTableViewController () @end @implementation MenuTableViewController - (void)viewDidLoad { [super viewDidLoad]; self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return @"Select one of the options below".uppercaseString; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeAdTemplateViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface NativeAdTemplateViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeAdTemplateViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "NativeAdTemplateViewController.h" #import @interface NativeAdTemplateViewController () @property (strong, nonatomic) IBOutlet UILabel *adStatusLabel; @property (strong, nonatomic) IBOutlet UIView *adContainerView; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *adContainerHeightConstraint; @property (retain, nonatomic) IBOutlet NSLayoutConstraint *adContainerWidthConstraint; @property (retain, nonatomic) IBOutlet UISlider *heightSlider; @property (retain, nonatomic) IBOutlet UISlider *widthSlider; @property (strong, nonatomic) FBNativeAd *nativeAd; @property (strong, nonatomic) FBNativeAdViewAttributes *nativeAdAttributes; @property (strong, nonatomic) FBNativeAdView *adView; @end @implementation NativeAdTemplateViewController - (FBNativeAdViewAttributes *)nativeAdAttributes { FBNativeAdViewAttributes *attributes = _nativeAdAttributes; if (!attributes) { attributes = [[FBNativeAdViewAttributes alloc] init]; attributes.backgroundColor = [UIColor whiteColor]; attributes.advertiserNameColor = [UIColor colorWithRed:0.11 green:0.12 blue:0.13 alpha:1.0]; attributes.buttonColor = [UIColor colorWithRed:0.235 green:0.485 blue:1.000 alpha:1.000]; attributes.buttonTitleColor = [UIColor whiteColor]; attributes.titleColor = [UIColor darkGrayColor]; attributes.descriptionColor = [UIColor grayColor]; _nativeAdAttributes = attributes; } return attributes; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; self.heightSlider.value = self.adContainerHeightConstraint.constant; self.widthSlider.value = self.adContainerWidthConstraint.constant; } #pragma mark - Actions - (IBAction)handleAdHeightChange:(id)sender { CGFloat height = ((UISlider *)sender).value; self.adContainerHeightConstraint.constant = height; } - (IBAction)handleWidthChange:(id)sender { CGFloat width = ((UISlider *)sender).value; self.adContainerWidthConstraint.constant = width; } - (IBAction)loadNativeAd { self.adStatusLabel.text = @"Requesting an ad..."; // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBNativeAd *nativeAd = [[FBNativeAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified when the ad was loaded. nativeAd.delegate = self; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; // Initiate a request to load an ad. [nativeAd loadAd]; [self.adView removeFromSuperview]; } #pragma mark - FBNativeAdDelegate - (void)nativeAdDidLoad:(FBNativeAd *)nativeAd { if (self.nativeAd) { [self.nativeAd unregisterView]; } self.nativeAd = nativeAd; self.adStatusLabel.text = @"Ad loaded."; if (nativeAd && nativeAd.isAdValid) { FBNativeAdView *adView = [FBNativeAdView nativeAdViewWithNativeAd:nativeAd withAttributes:[self nativeAdAttributes]]; adView.frame = self.adContainerView.bounds; adView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self.adContainerView addSubview:adView]; self.adView = adView; } } - (void)nativeAd:(FBNativeAd *)nativeAd didFailWithError:(NSError *)error { self.adStatusLabel.text = @"Ad failed to load. Check console for details."; NSLog(@"Native ad failed to load with error: %@", error); } - (void)nativeAdDidClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad was clicked."); } - (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeBannerAdTemplateViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface NativeBannerAdTemplateViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeBannerAdTemplateViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "NativeBannerAdTemplateViewController.h" #import @interface NativeBannerAdTemplateViewController () @property (strong, nonatomic) IBOutlet UISegmentedControl *templateTypeControl; @property (strong, nonatomic) IBOutlet UILabel *adStatusLabel; @property (strong, nonatomic) IBOutlet UIView *adContainerView; @property (strong, nonatomic) IBOutlet NSLayoutConstraint *adContainerHeightConstraint; @property (strong, nonatomic) FBNativeBannerAd *nativeAd; @property (strong, nonatomic) FBNativeAdViewAttributes *nativeAdAttributes; @property (strong, nonatomic) FBNativeBannerAdView *adView; @end @implementation NativeBannerAdTemplateViewController - (void)adjustAdContainerHeight { switch ([self templateType]) { case FBNativeBannerAdViewTypeGenericHeight50: self.adContainerHeightConstraint.constant = 50.0f; break; case FBNativeBannerAdViewTypeGenericHeight100: self.adContainerHeightConstraint.constant = 100.f; break; case FBNativeBannerAdViewTypeGenericHeight120: self.adContainerHeightConstraint.constant = 120.f; break; default: break; } } - (FBNativeBannerAdViewType)templateType { FBNativeBannerAdViewType type = FBNativeBannerAdViewTypeGenericHeight50; switch (self.templateTypeControl.selectedSegmentIndex) { case 0: type = FBNativeBannerAdViewTypeGenericHeight50; break; case 1: type = FBNativeBannerAdViewTypeGenericHeight100; break; case 2: type = FBNativeBannerAdViewTypeGenericHeight120; break; }; return type; } #pragma mark - Actions - (IBAction)loadNativeAd { self.adStatusLabel.text = @"Requesting an ad..."; // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBNativeBannerAd *nativeAd = [[FBNativeBannerAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified when the ad was loaded. nativeAd.delegate = self; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; // Initiate a request to load an ad. [nativeAd loadAd]; [self.adView removeFromSuperview]; [self adjustAdContainerHeight]; } #pragma mark - FBNativeAdDelegate - (void)nativeBannerAdDidLoad:(FBNativeBannerAd *)nativeBannerAd { if (self.nativeAd) { [self.nativeAd unregisterView]; } self.nativeAd = nativeBannerAd; self.adStatusLabel.text = @"Ad loaded."; if (nativeBannerAd && nativeBannerAd.isAdValid) { FBNativeBannerAdView *adView = [FBNativeBannerAdView nativeBannerAdViewWithNativeBannerAd:nativeBannerAd withType:[self templateType]]; adView.frame = self.adContainerView.bounds; [self.adContainerView addSubview:adView]; self.adView = adView; } } - (void)nativeBannerAd:(FBNativeBannerAd *)nativeBannerAd didFailWithError:(NSError *)error { self.adStatusLabel.text = @"Ad failed to load. Check console for details."; NSLog(@"Native ad failed to load with error: %@", error); } - (void)nativeBannerAdDidClick:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad was clicked."); } - (void)nativeBannerAdDidFinishHandlingClick:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeBannerAdWillLogImpression:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskAll; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeBannerViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface NativeBannerViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeBannerViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "NativeBannerViewController.h" #import @interface NativeBannerViewController () @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) IBOutlet FBAdIconView *adIconView; @property (nonatomic, strong) IBOutlet UILabel *adTitleLabel; @property (nonatomic, strong) IBOutlet UIButton *adCallToActionButton; @property (nonatomic, strong) IBOutlet UILabel *adSponsoredLabel; @property (nonatomic, strong) IBOutlet FBAdOptionsView *adOptionsView; @property (nonatomic, strong) IBOutlet UIView *adUIView; @property (nonatomic, strong) FBNativeBannerAd *nativeBannerAd; @end @implementation NativeBannerViewController - (void)viewDidLoad { [super viewDidLoad]; self.adOptionsView.hidden = YES; } #pragma mark - IB Actions - (IBAction)loadAd:(id)sender { self.adStatusLabel.text = @"Requesting an ad..."; // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBNativeBannerAd *nativeBannerAd = [[FBNativeBannerAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified when the ad was loaded. nativeBannerAd.delegate = self; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; // Initiate a request to load an ad. [nativeBannerAd loadAd]; } #pragma mark - FBNativeBannerAdDelegate implementation - (void)nativeBannerAdDidLoad:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native banner ad was loaded, constructing native UI..."); if (self.nativeBannerAd) { [self.nativeBannerAd unregisterView]; } self.nativeBannerAd = nativeBannerAd; self.adStatusLabel.text = @"Ad loaded."; // Render native ads onto UIView self.adTitleLabel.text = self.nativeBannerAd.advertiserName; self.adSponsoredLabel.text = self.nativeBannerAd.sponsoredTranslation; [self setCallToActionButton:self.nativeBannerAd.callToAction]; NSLog(@"Register UIView for impression and click..."); // Set native banner ad view tags to declare roles of your views for better analysis in future // We will be able to provide you statistics how often these views were clicked by users // Views provided by Facebook already have appropriate tag set self.adTitleLabel.nativeAdViewTag = FBNativeAdViewTagTitle; self.adCallToActionButton.nativeAdViewTag = FBNativeAdViewTagCallToAction; // Specify the clickable areas. View you were using to set ad view tags should be clickable. NSArray *clickableViews = @[self.adCallToActionButton]; [nativeBannerAd registerViewForInteraction:self.adUIView iconView:self.adIconView viewController:self clickableViews:clickableViews]; // In you don't want to provide native ad view tags you can simply // Wire up UIView with the native banner ad; the whole UIView will be clickable. // [nativeBannerAd registerViewForInteraction:self.adUIView // iconView:self.adIconView // viewController:self]; self.adOptionsView.nativeAd = nativeBannerAd; self.adOptionsView.hidden = NO; } - (void)nativeBannerAd:(FBNativeBannerAd *)nativeBannerAd didFailWithError:(NSError *)error { self.adStatusLabel.text = @"Ad failed to load. Check console for details."; NSLog(@"Native ad failed to load with error: %@", error); } - (void)nativeBannerAdDidClick:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad was clicked."); } - (void)nativeBannerAdDidFinishHandlingClick:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeBannerAdWillLogImpression:(FBNativeBannerAd *)nativeBannerAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - Private Methods - (void)setCallToActionButton:(NSString *)callToAction { if (callToAction) { [self.adCallToActionButton setHidden:NO]; [self.adCallToActionButton setTitle:callToAction forState:UIControlStateNormal]; } else { [self.adCallToActionButton setHidden:YES]; } } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface NativeViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NativeViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "NativeViewController.h" #import const NSUInteger LoadNativeAdCellRowIndex = 0; @interface NativeViewController () @property (strong, nonatomic) IBOutlet UITableView *menuTableView; @property (strong, nonatomic) IBOutlet UILabel *adStatusLabel; @property (strong, nonatomic) IBOutlet FBMediaView *adIconView; @property (strong, nonatomic) IBOutlet FBMediaView *adCoverMediaView; @property (strong, nonatomic) IBOutlet UILabel *adTitleLabel; @property (strong, nonatomic) IBOutlet UILabel *adBodyLabel; @property (strong, nonatomic) IBOutlet UIButton *adCallToActionButton; @property (strong, nonatomic) IBOutlet UILabel *adSocialContextLabel; @property (strong, nonatomic) IBOutlet UILabel *sponsoredLabel; @property (strong, nonatomic) IBOutlet FBAdOptionsView *adOptionsView; @property (strong, nonatomic) IBOutlet UIView *adUIView; @property (strong, nonatomic) FBNativeAd *nativeAd; @end @implementation NativeViewController - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { // Used in xib must be referenced here so linker won't eliminate it. [FBMediaView class]; self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.adOptionsView.hidden = YES; self.menuTableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero]; } #pragma mark - IB Actions - (void)loadNativeAd { self.adStatusLabel.text = @"Requesting an ad..."; // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. FBNativeAd *nativeAd = [[FBNativeAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified when the ad was loaded. nativeAd.delegate = self; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; // Initiate a request to load an ad. [nativeAd loadAd]; } #pragma mark - FBNativeAdDelegate implementation - (void)nativeAdDidLoad:(FBNativeAd *)nativeAd { NSLog(@"Native ad was loaded, constructing native UI..."); if (self.nativeAd) { [self.nativeAd unregisterView]; } self.nativeAd = nativeAd; // Create native UI using the ad metadata. self.adCoverMediaView.delegate = self; self.adStatusLabel.text = @"Ad loaded."; // Render native ads onto UIView self.adTitleLabel.text = self.nativeAd.advertiserName; self.adBodyLabel.text = self.nativeAd.bodyText; self.adSocialContextLabel.text = self.nativeAd.socialContext; self.sponsoredLabel.text = self.nativeAd.sponsoredTranslation; [self setCallToActionButton:self.nativeAd.callToAction]; // set the frame of the adBodyLabel depending on whether to show to call to action button CGFloat gapToBorder = 9.0f; CGFloat gapToCTAButton = 8.0f; CGRect adBodyLabelFrame = self.adBodyLabel.frame; if (!self.nativeAd.callToAction) { adBodyLabelFrame.size.width = self.adCoverMediaView.bounds.size.width - gapToBorder * 2; } else { adBodyLabelFrame.size.width = self.adCoverMediaView.bounds.size.width - gapToCTAButton - gapToBorder - (self.adCoverMediaView.bounds.size.width - self.adCallToActionButton.frame.origin.x); } self.adBodyLabel.frame = adBodyLabelFrame; NSLog(@"Register UIView for impression and click..."); // Set native ad view tags to declare roles of your views for better analysis in future // We will be able to provide you statistics how often these views were clicked by users // Views provided by Facebook already have appropriate tag set self.adTitleLabel.nativeAdViewTag = FBNativeAdViewTagTitle; self.adBodyLabel.nativeAdViewTag = FBNativeAdViewTagBody; self.adSocialContextLabel.nativeAdViewTag = FBNativeAdViewTagSocialContext; self.adCallToActionButton.nativeAdViewTag = FBNativeAdViewTagCallToAction; // Specify the clickable areas. Views you were using to set ad view tags should be clickable. NSArray *clickableViews = @[self.adIconView, self.adTitleLabel, self.adBodyLabel, self.adSocialContextLabel, self.adCallToActionButton]; [nativeAd registerViewForInteraction:self.adUIView mediaView:self.adCoverMediaView iconView:self.adIconView viewController:self clickableViews:clickableViews]; // // You may use this method if you want to have all adUIView's subviews clickable // [nativeAd registerViewForInteraction:self.adUIView // mediaView:self.adCoverMediaView // iconView:self.adIconView // viewController:self]; self.adOptionsView.hidden = NO; self.adOptionsView.nativeAd = nativeAd; } - (void)nativeAd:(FBNativeAd *)nativeAd didFailWithError:(NSError *)error { self.adStatusLabel.text = @"Ad failed to load. Check console for details."; NSLog(@"Native ad failed to load with error: %@", error); } - (void)nativeAdDidClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad was clicked."); } - (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - Menu Table View - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self menuItems].count; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == LoadNativeAdCellRowIndex) { [self loadNativeAd]; return; } NSString *segue = [self segueIdentifierForIndexPath:indexPath]; [self performSegueWithIdentifier:segue sender:nil]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"menuCell" forIndexPath:indexPath]; cell.textLabel.text = [self menuItems][indexPath.row]; cell.accessoryType = [self accessoryTypeForIndexPath:indexPath]; return cell; } #pragma mark - Private Methods - (UITableViewCellAccessoryType)accessoryTypeForIndexPath:(NSIndexPath *)indexPath { return indexPath.row == LoadNativeAdCellRowIndex ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator; } - (NSString *)segueIdentifierForIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == LoadNativeAdCellRowIndex) { return nil; } NSArray *segues = @[@"showTemplate", @"showTableView", @"showScrollView", @"showCollectionView", @"showNativeBanner", @"showNativeBannerTemplate"]; return segues[indexPath.row - 1]; } - (NSArray *)menuItems { return @[@"Load Native Ad", @"Load Native Ad using Template", @"Load Native Ad in TableView", @"Load Native Ad in ScrollView", @"Load Native Ad in CollectionView", @"Load Native Banner Ad", @"Load Native Banner Ad using Template"]; } - (void)setCallToActionButton:(NSString *)callToAction { if (callToAction) { [self.adCallToActionButton setHidden:NO]; [self.adCallToActionButton setTitle:callToAction forState:UIControlStateNormal]; } else { [self.adCallToActionButton setHidden:YES]; } } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (void)mediaViewDidLoad:(FBMediaView *)mediaView { } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NavigationController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface NavigationController : UINavigationController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/NavigationController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "NavigationController.h" #import "NativeViewController.h" @interface NavigationController () @end @implementation NavigationController - (UIInterfaceOrientationMask)supportedInterfaceOrientations { UIInterfaceOrientationMask mask = UIInterfaceOrientationMaskAll; NSArray *viewControllers = [self viewControllers]; for (UIViewController *viewController in viewControllers) { if ([viewController isKindOfClass:[NativeViewController class]]) { mask = UIInterfaceOrientationMaskPortrait; break; } } return mask; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/RewardedVideoViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface RewardedVideoViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/RewardedVideoViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "RewardedVideoViewController.h" #import @interface RewardedVideoViewController () @property (nonatomic, strong) IBOutlet UILabel *adStatusLabel; @property (nonatomic, strong) FBRewardedVideoAd *rewardedVideoAd; @end @implementation RewardedVideoViewController - (IBAction)loadAd { self.adStatusLabel.text = @"Loading rewarded video ad..."; // Create the rewarded video unit with a placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. self.rewardedVideoAd = [[FBRewardedVideoAd alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID"]; // Set a delegate to get notified on changes or when the user interact with the ad. self.rewardedVideoAd.delegate = self; // Initiate the request to load the ad. [self.rewardedVideoAd loadAd]; // Optional: Set Reward data. [self.rewardedVideoAd setRewardDataWithUserID:@"user1234" withCurrency:@"gold"]; } - (IBAction)showAd { if (!self.rewardedVideoAd || !self.rewardedVideoAd.isAdValid) { // Ad not ready to present. self.adStatusLabel.text = @"Ad not loaded. Click load to request an ad."; } else { self.adStatusLabel.text = @"1. Tap 'Load Ad'\n2. Once ad loads, tap 'Show!' to see the ad"; // Ad is ready, present it! [self.rewardedVideoAd showAdFromRootViewController:self animated:NO]; } } #pragma mark - FBRewardedVideoAdDelegate implementation - (void)rewardedVideoAdDidLoad:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video ad was loaded. Can present now."); self.adStatusLabel.text = @"Ad loaded. Click show to present!"; } - (void)rewardedVideoAd:(FBRewardedVideoAd *)rewardedVideoAd didFailWithError:(NSError *)error { NSLog(@"Rewarded video failed to load with error: %@", error.description); self.adStatusLabel.text = [NSString stringWithFormat:@"Rewarded Video ad failed to load. %@", error.localizedDescription]; } - (void)rewardedVideoAdDidClick:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video was clicked."); } - (void)rewardedVideoAdDidClose:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video closed."); } - (void)rewardedVideoAdWillClose:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video will close."); } - (void)rewardedVideoAdWillLogImpression:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video impression is being captured."); } - (void)rewardedVideoAdVideoComplete:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video was completed successfully."); } - (void)rewardedVideoAdServerRewardDidSucceed:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video server side reward succeeded."); //optional, cleanup self.rewardedVideoAd = nil; } - (void)rewardedVideoAdServerRewardDidFail:(FBRewardedVideoAd *)rewardedVideoAd { NSLog(@"Rewarded video server side reward failed."); //optional, cleanup self.rewardedVideoAd = nil; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/ScrollViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface ScrollViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/ScrollViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "ScrollViewController.h" #import @interface ScrollViewController () @property (nonatomic, strong) IBOutlet UIView *containerView; @property (nonatomic, strong) IBOutlet UIActivityIndicatorView *activityIndicator; @property (nonatomic, strong) FBNativeAdsManager *manager; @property (nonatomic, weak) FBNativeAdScrollView *scrollView; @end @implementation ScrollViewController - (void)viewDidLoad { [super viewDidLoad]; FBNativeAdsManager *manager = [[FBNativeAdsManager alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID" forNumAdsRequested:5]; manager.delegate = self; manager.mediaCachePolicy = FBNativeAdsCachePolicyAll; [manager loadAds]; self.manager = manager; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; self.scrollView.frame = self.containerView.bounds; } - (IBAction)refresh:(id)sender { [self.manager loadAds]; if (self.scrollView) { [self.scrollView removeFromSuperview]; self.scrollView = nil; } [self.activityIndicator startAnimating]; } #pragma mark FBNativeAdDelegate - (void)nativeAdDidClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad was clicked."); } - (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd { NSLog(@"Native ad impression is being captured."); } #pragma mark FBNativeAdsManagerDelegate - (void)nativeAdsLoaded { [self.activityIndicator stopAnimating]; NSLog(@"Native ads loaded, constructing native UI..."); if (self.scrollView) { [self.scrollView removeFromSuperview]; self.scrollView = nil; } FBNativeAdScrollView *scrollView = [[FBNativeAdScrollView alloc] initWithNativeAdsManager:self.manager withType:FBNativeAdViewTypeGenericHeight300]; scrollView.delegate = self; scrollView.frame = self.containerView.bounds; [self.containerView addSubview:scrollView]; self.scrollView = scrollView; } - (void)nativeAdsFailedToLoadWithError:(NSError *)error { [self.activityIndicator stopAnimating]; NSLog(@"Native ads failed to load with error: %@", error); UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Native ad failed to load" message:@"Check console for more details" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:cancel]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsLogLevelCell.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface SettingsLogLevelCell : UITableViewCell @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsLogLevelCell.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "SettingsLogLevelCell.h" #import @interface SettingsLogLevelCell () @property (nonatomic, strong) IBOutlet UIStepper *stepper; @property (nonatomic, strong) IBOutlet UILabel *logLevelLabel; @property (nonatomic, copy) void (^onLogLevelChange)(FBAdLogLevel logLevel); @end @implementation SettingsLogLevelCell - (void)awakeFromNib { [super awakeFromNib]; self.logLevelLabel.text = [self stringFromLogLevel:[FBAdSettings getLogLevel]]; self.stepper.value = [FBAdSettings getLogLevel]; } - (IBAction)logValueDidChange:(UIStepper *)sender { [FBAdSettings setLogLevel:sender.value]; self.logLevelLabel.text = [self stringFromLogLevel:[FBAdSettings getLogLevel]]; if (self.onLogLevelChange) { self.onLogLevelChange([FBAdSettings getLogLevel]); } } - (NSString *)stringFromLogLevel:(FBAdLogLevel)logLevel { NSString *logLevelString = nil; switch (logLevel) { case FBAdLogLevelNone: logLevelString = @"None"; break; case FBAdLogLevelNotification: logLevelString = @"Notification"; break; case FBAdLogLevelError: logLevelString = @"Error"; break; case FBAdLogLevelWarning: logLevelString = @"Warning"; break; case FBAdLogLevelLog: logLevelString = @"Log"; break; case FBAdLogLevelDebug: logLevelString = @"Debug"; break; case FBAdLogLevelVerbose: logLevelString = @"Verbose"; break; default: logLevelString = @"Unknown"; break; } return logLevelString; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsSandboxCell.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface SettingsSandboxCell : UITableViewCell @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsSandboxCell.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "SettingsSandboxCell.h" #import @interface SettingsSandboxCell () @property (nonatomic, strong) IBOutlet UITextField *sandboxTextField; @end @implementation SettingsSandboxCell - (void)awakeFromNib { [super awakeFromNib]; self.sandboxTextField.text = [FBAdSettings urlPrefix]; self.sandboxTextField.delegate = self; } #pragma mark - Text field delegate - (void)textFieldDidEndEditing:(UITextField *)textField { [FBAdSettings setUrlPrefix:textField.text]; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder]; return YES; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTableViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface SettingsTableViewController : UITableViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTableViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "SettingsTableViewController.h" #import #import "SettingsTestModeCell.h" @interface SettingsTableViewController () @property (nonatomic, strong, readonly) NSArray *reuseIdentifiers; @end @implementation SettingsTableViewController @synthesize reuseIdentifiers = _reuseIdentifiers; #pragma mark - Private - (NSArray *)reuseIdentifiers { if (nil == _reuseIdentifiers) { NSMutableArray *identifiers = [@[@"SettingsSandboxCell", @"SettingsLogLevelCell", @"SettingsTestModeCell", @"SettingsTestAdCell"] mutableCopy]; if ([self isDebugLogsViewControllerAvailable]) { [identifiers insertObject:@"SettingsDebugEventCell" atIndex:2]; } _reuseIdentifiers = [identifiers copy]; } return _reuseIdentifiers; } - (NSString *)reuseIdentifierForIndexPath:(NSIndexPath *)indexPath { return self.reuseIdentifiers[indexPath.row]; } - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } - (BOOL)isDebugLogsViewControllerAvailable { return NSClassFromString(@"DebugLogsViewController") != nil; } #pragma mark - UITableViewDataSource implementation - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { NSInteger numberOfRows = [FBAdSettings isTestMode] ? 4 : 3; if ([self isDebugLogsViewControllerAvailable]) { numberOfRows++; } return numberOfRows; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { NSString *reuseId = [self reuseIdentifierForIndexPath:indexPath]; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId forIndexPath:indexPath]; if ([reuseId isEqualToString:@"SettingsTestModeCell"]) { ((SettingsTestModeCell *)cell).onTestModeChange = ^(BOOL enabled) { [self.tableView reloadData]; }; } return cell; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { return [NSString stringWithFormat:@"SDK Version %@", FB_AD_SDK_VERSION]; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTestAdCell.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface SettingsTestAdCell : UITableViewCell @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTestAdCell.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "SettingsTestAdCell.h" #import @interface SettingsTestAdCell () @property (nonatomic, strong) IBOutlet UITextField *testAdTextField; @property (nonatomic, strong) UIPickerView *pickerView; @property (nonatomic, copy) NSDictionary *testsAds; @end @implementation SettingsTestAdCell - (void)awakeFromNib { [super awakeFromNib]; self.pickerView.delegate = self; self.testsAds = @{ @(FBAdTestAdType_Default) : @"default", @(FBAdTestAdType_Img_16_9_App_Install) : @"image_install", @(FBAdTestAdType_Img_16_9_Link) : @"image_link", @(FBAdTestAdType_Vid_HD_16_9_46s_App_Install) : @"video_16x9_46s_install", @(FBAdTestAdType_Vid_HD_16_9_46s_Link) : @"video_16x9_46s_link", @(FBAdTestAdType_Vid_HD_16_9_15s_App_Install) : @"video_16x9_15s_install", @(FBAdTestAdType_Vid_HD_16_9_15s_Link) : @"video_16x9_15s_link", @(FBAdTestAdType_Vid_HD_9_16_39s_App_Install) : @"video_9x16_39s_install", @(FBAdTestAdType_Vid_HD_9_16_39s_Link) : @"video_9x16_39s_link", @(FBAdTestAdType_Carousel_Img_Square_App_Install) : @"carousel_install", @(FBAdTestAdType_Carousel_Img_Square_Link) : @"carousel_link" }; [self setupPickerView]; [self setupAdTextField]; } - (void)setupPickerView { self.pickerView = [UIPickerView new]; self.pickerView.delegate = self; self.pickerView.dataSource = self; [self.pickerView selectRow:FBAdSettings.testAdType inComponent:0 animated:NO]; } - (UIToolbar *)toolbar { UIToolbar* toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), 44)]; UIBarButtonItem *flex = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; UIBarButtonItem *done = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(done:)]; toolbar.items = @[flex, done]; [toolbar sizeToFit]; return toolbar; } - (void)setupAdTextField { self.testAdTextField.inputView = self.pickerView; self.testAdTextField.inputAccessoryView = [self toolbar]; self.testAdTextField.text = self.testsAds[@(FBAdSettings.testAdType)]; } - (void)done:(id)sender { [self.testAdTextField resignFirstResponder]; } #pragma mark - Picker view delegate - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { NSString *title = self.testsAds[@(row)]; if (!title) { title = @"None"; } return title; } - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)thePickerView { return 1; } - (NSInteger)pickerView:(UIPickerView *)thePickerView numberOfRowsInComponent:(NSInteger)component { return self.testsAds.count; } - (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { self.testAdTextField.text = self.testsAds[@(row)] ? self.testsAds[@(row)] : @"None"; FBAdSettings.testAdType = row; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTestModeCell.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface SettingsTestModeCell : UITableViewCell @property (nonatomic, copy) void (^onTestModeChange)(BOOL enabled); @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/SettingsTestModeCell.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "SettingsTestModeCell.h" #import @interface SettingsTestModeCell () @property (nonatomic, strong) IBOutlet UISwitch *switcher; @end @implementation SettingsTestModeCell - (void)awakeFromNib { [super awakeFromNib]; [self.switcher setOn:[FBAdSettings isTestMode]]; } - (IBAction)switcherValueChanged:(UISwitch *)sender { if ([sender isOn]) { [FBAdSettings addTestDevice:[FBAdSettings testDeviceHash]]; } else { [FBAdSettings clearTestDevice:[FBAdSettings testDeviceHash]]; } if (self.onTestModeChange) { self.onTestModeChange([FBAdSettings isTestMode]); } } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/TableViewController.h ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import @interface TableViewController : UIViewController @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/TableViewController.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import "TableViewController.h" #import static NSInteger const kRowStrideForAdCell = 9; static NSString *const kDefaultCellIdentifier = @"kDefaultCellIdentifier"; @interface TableViewController () @property (nonatomic, strong) IBOutlet UITableView *tableView; @property (nonatomic, strong) IBOutlet UIActivityIndicatorView *activityIndicator; @property (nonatomic, strong) FBNativeAdsManager *adsManager; @property (nonatomic, strong) FBNativeAdTableViewCellProvider *cellProvider; @property (nonatomic, strong) NSMutableArray *tableViewContentArray; @property (nonatomic, assign) BOOL adCellsCreated; @end @implementation TableViewController #pragma mark - Lazy Loading - (NSMutableArray *)tableViewContentArray { if (!_tableViewContentArray) { _tableViewContentArray = [NSMutableArray array]; for (NSUInteger i = 0; i < 45; i++) { [_tableViewContentArray addObject:[NSString stringWithFormat:@"TableView Cell #%lu", (unsigned long)(i + 1)]]; } } return _tableViewContentArray; } - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. self.tableView.delegate = self; self.tableView.dataSource = self; [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kDefaultCellIdentifier]; [self loadNativeAd]; } - (IBAction)refresh:(id)sender { [self loadNativeAd]; } - (void)loadNativeAd { [self.activityIndicator startAnimating]; if (!self.adsManager) { // Create a native ad manager with a unique placement ID (generate your own on the Facebook app settings) // and how many ads you would like to create. Note that you may get fewer ads than you ask for. // Use different ID for each ad placement in your app. self.adsManager = [[FBNativeAdsManager alloc] initWithPlacementID:@"YOUR_PLACEMENT_ID" forNumAdsRequested:5]; // Set a delegate to get notified when the ads are loaded. self.adsManager.delegate = self; // Configure native ad manager to wait to call nativeAdsLoaded until all ad assets are loaded self.adsManager.mediaCachePolicy = FBNativeAdsCachePolicyAll; // When testing on a device, add its hashed ID to force test ads. // The hash ID is printed to console when running on a device. // [FBAdSettings addTestDevice:@"THE HASHED ID AS PRINTED TO CONSOLE"]; } // Load some ads [self.adsManager loadAds]; } #pragma mark FBNativeAdsManagerDelegate implementation - (void)nativeAdsLoaded { NSLog(@"Native ad was loaded, constructing native UI..."); // After the native ads have loaded we create the native ad cell provider and let it take over FBNativeAdsManager *manager = self.adsManager; self.adsManager.delegate = nil; self.adsManager = nil; // The native ad cell provider operates over a loaded ads manager and can create table cells with native // ad templates in them as well as help with the math to have a consistent distribution of ads within a table. FBNativeAdTableViewCellProvider *cellProvider = [[FBNativeAdTableViewCellProvider alloc] initWithManager:manager forType:FBNativeAdViewTypeGenericHeight300]; self.cellProvider = cellProvider; self.cellProvider.delegate = self; [self.tableView reloadData]; [self.activityIndicator stopAnimating]; } - (void)nativeAdsFailedToLoadWithError:(NSError *)error { NSLog(@"Native ad failed to load with error: %@", error); [self.activityIndicator stopAnimating]; UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Native ad failed to load" message:@"Check console for more details" preferredStyle:UIAlertControllerStyleAlert]; UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil]; [alertController addAction:cancel]; [self presentViewController:alertController animated:YES completion:nil]; } #pragma mark FBNativeAdDelegate - (void)nativeAdDidClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad was clicked."); } - (void)nativeAdDidFinishHandlingClick:(FBNativeAd *)nativeAd { NSLog(@"Native ad did finish click handling."); } - (void)nativeAdWillLogImpression:(FBNativeAd *)nativeAd { NSLog(@"Native ad impression is being captured."); } #pragma mark - UITableViewDataSource - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // In this example the ads are evenly distributed within the table every kRowStrideForAdCell-th cell. NSUInteger count = [self.tableViewContentArray count]; count = [self.cellProvider adjustCount:count forStride:kRowStrideForAdCell] ?: count; return count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // For ad cells just as the ad cell provider, for normal cells do whatever you would do. if ([self.cellProvider isAdCellAtIndexPath:indexPath forStride:kRowStrideForAdCell]) { return [self.cellProvider tableView:tableView cellForRowAtIndexPath:indexPath]; } else { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kDefaultCellIdentifier forIndexPath:indexPath]; // In this example we need to adjust the index back to the domain of the data. indexPath = [self.cellProvider adjustNonAdCellIndexPath:indexPath forStride:kRowStrideForAdCell] ?: indexPath; cell.textLabel.text = [self.tableViewContentArray objectAtIndex:indexPath.row]; return cell; } } #pragma mark - UITableViewDelegate - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // The ad cell provider knows the height of ad cells based on its configuration if ([self.cellProvider isAdCellAtIndexPath:indexPath forStride:kRowStrideForAdCell]) { return [self.cellProvider tableView:tableView heightForRowAtIndexPath:indexPath]; } else { return 80; } } #pragma mark - Orientation - (UIInterfaceOrientationMask)supportedInterfaceOrientations { return UIInterfaceOrientationMaskPortrait; } @end ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample/main.m ================================================ // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. // // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, // copy, modify, and distribute this software in source code or binary form for use // in connection with the web services and APIs provided by Facebook. // // As with any software that integrates with the Facebook platform, your use of // this software is subject to the Facebook Developer Principles and Policies // [http://developers.facebook.com/policy/]. This copyright notice shall be // included in all copies or substantial portions of the software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 58D92D5C18C7A6B10090E7E2 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D92D5A18C7A6B10090E7E2 /* AppDelegate.m */; }; 58D92D5D18C7A6B10090E7E2 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 58D92D5B18C7A6B10090E7E2 /* Images.xcassets */; }; 58D92D6C18C7A6D00090E7E2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 58D92D6818C7A6D00090E7E2 /* main.m */; }; 7DB6D5831D2EF6020095B2E3 /* CollectionViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 7DB6D5811D2EF6020095B2E3 /* CollectionViewController.m */; }; 821E0AB21FC5923300F6C1DC /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 821E0AB11FC5923200F6C1DC /* LaunchScreen.storyboard */; }; 825B69E321400B0900C130F6 /* NativeAdTemplateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B69E121400B0900C130F6 /* NativeAdTemplateViewController.m */; }; 825B69E421400B0900C130F6 /* NativeBannerAdTemplateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B69E221400B0900C130F6 /* NativeBannerAdTemplateViewController.m */; }; 825B76321FE00ED4002E9410 /* MediumRectViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B76261FE00ED2002E9410 /* MediumRectViewController.m */; }; 825B76331FE00ED4002E9410 /* RewardedVideoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B762A1FE00ED3002E9410 /* RewardedVideoViewController.m */; }; 825B76341FE00ED4002E9410 /* InstreamViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B762B1FE00ED3002E9410 /* InstreamViewController.m */; }; 825B76351FE00ED4002E9410 /* InterstitialViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B762D1FE00ED3002E9410 /* InterstitialViewController.m */; }; 825B76361FE00ED4002E9410 /* BannerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B762E1FE00ED3002E9410 /* BannerViewController.m */; }; 825B76371FE00ED4002E9410 /* MenuTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 825B762F1FE00ED4002E9410 /* MenuTableViewController.m */; }; 829C8D1A1FBF35BE00B784C1 /* SettingsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D0E1FBF35BD00B784C1 /* SettingsTableViewController.m */; }; 829C8D1B1FBF35BE00B784C1 /* AdUnitsSampleStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 829C8D0F1FBF35BD00B784C1 /* AdUnitsSampleStoryboard.storyboard */; }; 829C8D1C1FBF35BE00B784C1 /* SettingsTestAdCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D131FBF35BD00B784C1 /* SettingsTestAdCell.m */; }; 829C8D1D1FBF35BE00B784C1 /* SettingsSandboxCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D141FBF35BD00B784C1 /* SettingsSandboxCell.m */; }; 829C8D1E1FBF35BE00B784C1 /* NavigationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D151FBF35BD00B784C1 /* NavigationController.m */; }; 829C8D1F1FBF35BE00B784C1 /* SettingsTestModeCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D181FBF35BE00B784C1 /* SettingsTestModeCell.m */; }; 829C8D201FBF35BE00B784C1 /* SettingsLogLevelCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 829C8D191FBF35BE00B784C1 /* SettingsLogLevelCell.m */; }; 90E89CD41A99AE95005D3430 /* ScrollViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 90E89CD21A99AE95005D3430 /* ScrollViewController.m */; }; 9981CCDC1F696FF100935A60 /* libc++.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 9981CCDB1F696FF100935A60 /* libc++.tbd */; }; 9C86FDA720F8CF4C00077F54 /* NativeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9C86FDA520F8CF4C00077F54 /* NativeViewController.m */; }; 9CF70F3A207E0C6D002D30D2 /* NativeBannerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CF70F39207E0C6D002D30D2 /* NativeBannerViewController.m */; }; EE23E6E8198B0B0600215C81 /* TableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = EE23E6E6198B0B0600215C81 /* TableViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ B87B1D2D1DDE5CA6004828BC /* Embed Frameworks */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = ""; dstSubfolderSpec = 10; files = ( ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 58D92D1E18C7A6100090E7E2 /* AdUnitsSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AdUnitsSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 58D92D5918C7A6B10090E7E2 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 58D92D5A18C7A6B10090E7E2 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 58D92D5B18C7A6B10090E7E2 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 58D92D6618C7A6D00090E7E2 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 58D92D6718C7A6D00090E7E2 /* InfoPlist.strings */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; path = InfoPlist.strings; sourceTree = ""; }; 58D92D6818C7A6D00090E7E2 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 58D92D6918C7A6D00090E7E2 /* AdUnitsSample-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "AdUnitsSample-Prefix.pch"; sourceTree = ""; }; 7DB6D5801D2EF6020095B2E3 /* CollectionViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CollectionViewController.h; sourceTree = ""; }; 7DB6D5811D2EF6020095B2E3 /* CollectionViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CollectionViewController.m; sourceTree = ""; }; 821E0AB11FC5923200F6C1DC /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = LaunchScreen.storyboard; sourceTree = ""; }; 825B69DF21400B0800C130F6 /* NativeBannerAdTemplateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeBannerAdTemplateViewController.h; sourceTree = ""; }; 825B69E021400B0900C130F6 /* NativeAdTemplateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeAdTemplateViewController.h; sourceTree = ""; }; 825B69E121400B0900C130F6 /* NativeAdTemplateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeAdTemplateViewController.m; sourceTree = ""; }; 825B69E221400B0900C130F6 /* NativeBannerAdTemplateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeBannerAdTemplateViewController.m; sourceTree = ""; }; 825B76261FE00ED2002E9410 /* MediumRectViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MediumRectViewController.m; sourceTree = ""; }; 825B76271FE00ED2002E9410 /* InterstitialViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InterstitialViewController.h; sourceTree = ""; }; 825B76281FE00ED2002E9410 /* BannerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BannerViewController.h; sourceTree = ""; }; 825B76291FE00ED2002E9410 /* RewardedVideoViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RewardedVideoViewController.h; sourceTree = ""; }; 825B762A1FE00ED3002E9410 /* RewardedVideoViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RewardedVideoViewController.m; sourceTree = ""; }; 825B762B1FE00ED3002E9410 /* InstreamViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InstreamViewController.m; sourceTree = ""; }; 825B762C1FE00ED3002E9410 /* InstreamViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InstreamViewController.h; sourceTree = ""; }; 825B762D1FE00ED3002E9410 /* InterstitialViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = InterstitialViewController.m; sourceTree = ""; }; 825B762E1FE00ED3002E9410 /* BannerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BannerViewController.m; sourceTree = ""; }; 825B762F1FE00ED4002E9410 /* MenuTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MenuTableViewController.m; sourceTree = ""; }; 825B76301FE00ED4002E9410 /* MediumRectViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MediumRectViewController.h; sourceTree = ""; }; 825B76311FE00ED4002E9410 /* MenuTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MenuTableViewController.h; sourceTree = ""; }; 829C8D0D1FBF35BD00B784C1 /* SettingsLogLevelCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsLogLevelCell.h; sourceTree = ""; }; 829C8D0E1FBF35BD00B784C1 /* SettingsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTableViewController.m; sourceTree = ""; }; 829C8D0F1FBF35BD00B784C1 /* AdUnitsSampleStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = AdUnitsSampleStoryboard.storyboard; sourceTree = ""; }; 829C8D101FBF35BD00B784C1 /* SettingsSandboxCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsSandboxCell.h; sourceTree = ""; }; 829C8D111FBF35BD00B784C1 /* SettingsTestAdCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTestAdCell.h; sourceTree = ""; }; 829C8D121FBF35BD00B784C1 /* NavigationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NavigationController.h; sourceTree = ""; }; 829C8D131FBF35BD00B784C1 /* SettingsTestAdCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTestAdCell.m; sourceTree = ""; }; 829C8D141FBF35BD00B784C1 /* SettingsSandboxCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsSandboxCell.m; sourceTree = ""; }; 829C8D151FBF35BD00B784C1 /* NavigationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NavigationController.m; sourceTree = ""; }; 829C8D161FBF35BE00B784C1 /* SettingsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTableViewController.h; sourceTree = ""; }; 829C8D171FBF35BE00B784C1 /* SettingsTestModeCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SettingsTestModeCell.h; sourceTree = ""; }; 829C8D181FBF35BE00B784C1 /* SettingsTestModeCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsTestModeCell.m; sourceTree = ""; }; 829C8D191FBF35BE00B784C1 /* SettingsLogLevelCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsLogLevelCell.m; sourceTree = ""; }; 90E89CD11A99AE95005D3430 /* ScrollViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScrollViewController.h; sourceTree = ""; }; 90E89CD21A99AE95005D3430 /* ScrollViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ScrollViewController.m; sourceTree = ""; }; 9981CCDB1F696FF100935A60 /* libc++.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = "libc++.tbd"; path = "usr/lib/libc++.tbd"; sourceTree = SDKROOT; }; 9C86FDA520F8CF4C00077F54 /* NativeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeViewController.m; sourceTree = ""; }; 9C86FDA620F8CF4C00077F54 /* NativeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeViewController.h; sourceTree = ""; }; 9CF70F38207E0C6D002D30D2 /* NativeBannerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NativeBannerViewController.h; sourceTree = ""; }; 9CF70F39207E0C6D002D30D2 /* NativeBannerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeBannerViewController.m; sourceTree = ""; }; B81CBE1E1DC7F21400651A52 /* AdUnitsSample.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = AdUnitsSample.entitlements; sourceTree = ""; }; EE23E6E5198B0B0600215C81 /* TableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TableViewController.h; sourceTree = ""; }; EE23E6E6198B0B0600215C81 /* TableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TableViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 58D92D1B18C7A6100090E7E2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 9981CCDC1F696FF100935A60 /* libc++.tbd in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 58D92D1518C7A6100090E7E2 = { isa = PBXGroup; children = ( 58D92D2718C7A6100090E7E2 /* AdUnitsSample */, 58D92D2018C7A6100090E7E2 /* Frameworks */, 58D92D1F18C7A6100090E7E2 /* Products */, ); indentWidth = 4; sourceTree = ""; tabWidth = 4; }; 58D92D1F18C7A6100090E7E2 /* Products */ = { isa = PBXGroup; children = ( 58D92D1E18C7A6100090E7E2 /* AdUnitsSample.app */, ); name = Products; sourceTree = ""; }; 58D92D2018C7A6100090E7E2 /* Frameworks */ = { isa = PBXGroup; children = ( 9981CCDB1F696FF100935A60 /* libc++.tbd */, ); name = Frameworks; sourceTree = ""; }; 58D92D2718C7A6100090E7E2 /* AdUnitsSample */ = { isa = PBXGroup; children = ( 58D92D5918C7A6B10090E7E2 /* AppDelegate.h */, 58D92D5A18C7A6B10090E7E2 /* AppDelegate.m */, 9C6C3B9F20F8C2C800149EF6 /* FormatSamples */, 9C6C3B9E20F8C2A200149EF6 /* SettingsMenu */, 9C41349120F8C1D70032CC52 /* Resources */, 58D92D2818C7A6100090E7E2 /* Supporting Files */, ); path = AdUnitsSample; sourceTree = ""; }; 58D92D2818C7A6100090E7E2 /* Supporting Files */ = { isa = PBXGroup; children = ( 58D92D6618C7A6D00090E7E2 /* Info.plist */, 58D92D6718C7A6D00090E7E2 /* InfoPlist.strings */, 58D92D6818C7A6D00090E7E2 /* main.m */, 58D92D6918C7A6D00090E7E2 /* AdUnitsSample-Prefix.pch */, ); name = "Supporting Files"; sourceTree = ""; }; 9C41349120F8C1D70032CC52 /* Resources */ = { isa = PBXGroup; children = ( 821E0AB11FC5923200F6C1DC /* LaunchScreen.storyboard */, 829C8D0F1FBF35BD00B784C1 /* AdUnitsSampleStoryboard.storyboard */, 58D92D5B18C7A6B10090E7E2 /* Images.xcassets */, B81CBE1E1DC7F21400651A52 /* AdUnitsSample.entitlements */, ); name = Resources; sourceTree = ""; }; 9C6C3B9E20F8C2A200149EF6 /* SettingsMenu */ = { isa = PBXGroup; children = ( 829C8D0D1FBF35BD00B784C1 /* SettingsLogLevelCell.h */, 829C8D191FBF35BE00B784C1 /* SettingsLogLevelCell.m */, 829C8D101FBF35BD00B784C1 /* SettingsSandboxCell.h */, 829C8D141FBF35BD00B784C1 /* SettingsSandboxCell.m */, 829C8D161FBF35BE00B784C1 /* SettingsTableViewController.h */, 829C8D0E1FBF35BD00B784C1 /* SettingsTableViewController.m */, 829C8D111FBF35BD00B784C1 /* SettingsTestAdCell.h */, 829C8D131FBF35BD00B784C1 /* SettingsTestAdCell.m */, 829C8D171FBF35BE00B784C1 /* SettingsTestModeCell.h */, 829C8D181FBF35BE00B784C1 /* SettingsTestModeCell.m */, 825B76311FE00ED4002E9410 /* MenuTableViewController.h */, 825B762F1FE00ED4002E9410 /* MenuTableViewController.m */, 829C8D121FBF35BD00B784C1 /* NavigationController.h */, 829C8D151FBF35BD00B784C1 /* NavigationController.m */, ); name = SettingsMenu; sourceTree = ""; }; 9C6C3B9F20F8C2C800149EF6 /* FormatSamples */ = { isa = PBXGroup; children = ( 825B69E021400B0900C130F6 /* NativeAdTemplateViewController.h */, 825B69E121400B0900C130F6 /* NativeAdTemplateViewController.m */, 825B69DF21400B0800C130F6 /* NativeBannerAdTemplateViewController.h */, 825B69E221400B0900C130F6 /* NativeBannerAdTemplateViewController.m */, 825B76281FE00ED2002E9410 /* BannerViewController.h */, 825B762E1FE00ED3002E9410 /* BannerViewController.m */, 9CF70F38207E0C6D002D30D2 /* NativeBannerViewController.h */, 9CF70F39207E0C6D002D30D2 /* NativeBannerViewController.m */, 825B762C1FE00ED3002E9410 /* InstreamViewController.h */, 825B762B1FE00ED3002E9410 /* InstreamViewController.m */, 825B76271FE00ED2002E9410 /* InterstitialViewController.h */, 825B762D1FE00ED3002E9410 /* InterstitialViewController.m */, 825B76301FE00ED4002E9410 /* MediumRectViewController.h */, 825B76261FE00ED2002E9410 /* MediumRectViewController.m */, 825B76291FE00ED2002E9410 /* RewardedVideoViewController.h */, 825B762A1FE00ED3002E9410 /* RewardedVideoViewController.m */, EE23E6E5198B0B0600215C81 /* TableViewController.h */, EE23E6E6198B0B0600215C81 /* TableViewController.m */, 90E89CD11A99AE95005D3430 /* ScrollViewController.h */, 90E89CD21A99AE95005D3430 /* ScrollViewController.m */, 7DB6D5801D2EF6020095B2E3 /* CollectionViewController.h */, 7DB6D5811D2EF6020095B2E3 /* CollectionViewController.m */, 9C86FDA620F8CF4C00077F54 /* NativeViewController.h */, 9C86FDA520F8CF4C00077F54 /* NativeViewController.m */, ); name = FormatSamples; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 58D92D1D18C7A6100090E7E2 /* AdUnitsSample */ = { isa = PBXNativeTarget; buildConfigurationList = 58D92D5318C7A6110090E7E2 /* Build configuration list for PBXNativeTarget "AdUnitsSample" */; buildPhases = ( 58D92D1A18C7A6100090E7E2 /* Sources */, 58D92D1C18C7A6100090E7E2 /* Resources */, 58D92D1B18C7A6100090E7E2 /* Frameworks */, B87B1D2D1DDE5CA6004828BC /* Embed Frameworks */, ); buildRules = ( ); dependencies = ( ); name = AdUnitsSample; productName = AdUnitsSample; productReference = 58D92D1E18C7A6100090E7E2 /* AdUnitsSample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 58D92D1618C7A6100090E7E2 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0700; ORGANIZATIONNAME = Facebook; TargetAttributes = { 58D92D1D18C7A6100090E7E2 = { ProvisioningStyle = Automatic; SystemCapabilities = { }; }; }; }; buildConfigurationList = 58D92D1918C7A6100090E7E2 /* Build configuration list for PBXProject "AdUnitsSample" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 58D92D1518C7A6100090E7E2; productRefGroup = 58D92D1F18C7A6100090E7E2 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 58D92D1D18C7A6100090E7E2 /* AdUnitsSample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 58D92D1C18C7A6100090E7E2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 821E0AB21FC5923300F6C1DC /* LaunchScreen.storyboard in Resources */, 829C8D1B1FBF35BE00B784C1 /* AdUnitsSampleStoryboard.storyboard in Resources */, 58D92D5D18C7A6B10090E7E2 /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 58D92D1A18C7A6100090E7E2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 9C86FDA720F8CF4C00077F54 /* NativeViewController.m in Sources */, 829C8D1A1FBF35BE00B784C1 /* SettingsTableViewController.m in Sources */, 829C8D1F1FBF35BE00B784C1 /* SettingsTestModeCell.m in Sources */, 825B76351FE00ED4002E9410 /* InterstitialViewController.m in Sources */, 825B69E321400B0900C130F6 /* NativeAdTemplateViewController.m in Sources */, 825B76331FE00ED4002E9410 /* RewardedVideoViewController.m in Sources */, 825B76361FE00ED4002E9410 /* BannerViewController.m in Sources */, 58D92D5C18C7A6B10090E7E2 /* AppDelegate.m in Sources */, 829C8D1D1FBF35BE00B784C1 /* SettingsSandboxCell.m in Sources */, 829C8D201FBF35BE00B784C1 /* SettingsLogLevelCell.m in Sources */, 7DB6D5831D2EF6020095B2E3 /* CollectionViewController.m in Sources */, 58D92D6C18C7A6D00090E7E2 /* main.m in Sources */, 90E89CD41A99AE95005D3430 /* ScrollViewController.m in Sources */, 829C8D1C1FBF35BE00B784C1 /* SettingsTestAdCell.m in Sources */, 825B69E421400B0900C130F6 /* NativeBannerAdTemplateViewController.m in Sources */, 825B76321FE00ED4002E9410 /* MediumRectViewController.m in Sources */, 829C8D1E1FBF35BE00B784C1 /* NavigationController.m in Sources */, EE23E6E8198B0B0600215C81 /* TableViewController.m in Sources */, 825B76371FE00ED4002E9410 /* MenuTableViewController.m in Sources */, 825B76341FE00ED4002E9410 /* InstreamViewController.m in Sources */, 9CF70F3A207E0C6D002D30D2 /* NativeBannerViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 58D92D5118C7A6110090E7E2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = NO; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 58D92D5218C7A6110090E7E2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = NO; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 9.0; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 58D92D5418C7A6110090E7E2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = AdUnitsSample/AdUnitsSample.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../..//Static", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AdUnitsSample/AdUnitsSample-Prefix.pch"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = AdUnitsSample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.audiencenetwork.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "8d2650e7-a3c0-4b70-a158-1df747083300"; PROVISIONING_PROFILE_SPECIFIER = ""; WRAPPER_EXTENSION = app; }; name = Debug; }; 58D92D5518C7A6110090E7E2 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_ENTITLEMENTS = AdUnitsSample/AdUnitsSample.entitlements; CODE_SIGN_IDENTITY = "iPhone Developer"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; CODE_SIGN_STYLE = Automatic; DEVELOPMENT_TEAM = ""; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", "$(SRCROOT)/../../..//Static", ); GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = "AdUnitsSample/AdUnitsSample-Prefix.pch"; HEADER_SEARCH_PATHS = ""; INFOPLIST_FILE = AdUnitsSample/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "com.facebook.audiencenetwork.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE = "e7603b38-718e-4f37-98d5-3a5668531043"; PROVISIONING_PROFILE_SPECIFIER = ""; WRAPPER_EXTENSION = app; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 58D92D1918C7A6100090E7E2 /* Build configuration list for PBXProject "AdUnitsSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 58D92D5118C7A6110090E7E2 /* Debug */, 58D92D5218C7A6110090E7E2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 58D92D5318C7A6110090E7E2 /* Build configuration list for PBXNativeTarget "AdUnitsSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 58D92D5418C7A6110090E7E2 /* Debug */, 58D92D5518C7A6110090E7E2 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 58D92D1618C7A6100090E7E2 /* Project object */; } ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcodeproj/xcshareddata/xcschemes/AdUnitsSample.xcscheme ================================================ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: samples/ios/AdUnitsSample/AdUnitsSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: samples/ios/AdUnitsSample/Podfile ================================================ # Uncomment the next line to define a global platform for your project # platform :ios, '9.0' target 'AdUnitsSample' do # Uncomment the next line if you're using Swift or would like to use dynamic frameworks # use_frameworks! # Pods for AdUnitsSample pod 'FBAudienceNetwork' end ================================================ FILE: samples/ios/AdUnitsSample/ReadMe.txt ================================================ AdUnitsSample In this sample we demonstrate how to use the Native Ad API (FBNativeAd) from the Facebook Ads SDK for iOS. FBNativeAd gives the flexibility to the to allow developer to render the ad in a more native format that blends into their app. We also show how to wire up the delegate to get notified when the ad status changes over time or when the user interacts with the ad. When running the sample on the simulator, test ads are served by default. On a device however, real ads will be served unless you specify otherwise. If you test your app on a device, please make sure to call the following API to enable test ads: [FBAdSettings addTestDevice:@""]. How to use the sample? 1/ Launch the AdUnitsSample project using Xcode from the /samples/AdUnitsSample directory. 2/ Open the file ViewController.m and replace "YOUR_PLACEMENT_ID" with the Placement ID you created through developer.facebook.com. 3/ Run the sample on the simulator or on a device. ================================================ FILE: samples/ios/AdUnitsSample/VERSION.bzl ================================================ VERSION_CONFIG = { # These are bumped by automation # See https://our.intern.facebook.com/intern/wiki/index.php/Releng/Mobile/Version_numbers "FB_BUNDLE_VERSION_SHORT": "7.0", "FB_APP_VERSION": "7.0.0.19.473", } ================================================ FILE: samples/ios/FANSample/.gitignore ================================================ # Xcode ## Build generated build/ DerivedData/ ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ ## Other *.moved-aside *.xccheckout *.xcscmblueprint # CocoaPods Pods/ Podfile.lock ================================================ FILE: samples/ios/FANSample/FANSample/AppDelegate.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { // Override point for customization after application launch. FBAudienceNetworkAds.initialize(with: nil, completionHandler: nil) FBAdSettings.setAdvertiserTrackingEnabled(true) return true } // MARK: UISceneSession Lifecycle func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { // Called when a new scene session is being created. // Use this method to select a configuration to create the new scene with. return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) } func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set) { // Called when the user discards a scene session. // If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions. // Use this method to release any resources that were specific to the discarded scenes, as they will not return. } } ================================================ FILE: samples/ios/FANSample/FANSample/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "20x20", "scale" : "2x", "filename" : "icon_20@2x.png" }, { "idiom" : "iphone", "size" : "20x20", "scale" : "3x", "filename" : "icon_20@3x.png" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "2x", "filename" : "icon_29@2x.png" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x", "filename" : "icon_29@3x.png" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x", "filename" : "icon_40@2x.png" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x", "filename" : "icon_40@3x.png" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x", "filename" : "icon_60@2x.png" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x", "filename" : "icon_60@3x.png" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "1x", "filename" : "icon_20@1x.png" }, { "idiom" : "ipad", "size" : "20x20", "scale" : "2x", "filename" : "icon_20@2x.png" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x", "filename" : "icon_29@1x.png" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x", "filename" : "icon_29@2x.png" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x", "filename" : "icon_40@1x.png" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x", "filename" : "icon_40@2x.png" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x", "filename" : "icon_76@1x.png" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x", "filename" : "icon_76@2x.png" }, { "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x", "filename" : "icon_83.5@2x.png" }, { "idiom" : "ios-marketing", "size" : "1024x1024", "scale" : "1x", "filename" : "icon_1024@1x.png" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: samples/ios/FANSample/FANSample/Assets.xcassets/Contents.json ================================================ { "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: samples/ios/FANSample/FANSample/Assets.xcassets/fan.imageset/Contents.json ================================================ { "images" : [ { "idiom" : "universal", "scale" : "1x" }, { "idiom" : "universal", "filename" : "fan.png", "scale" : "2x" }, { "idiom" : "universal", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: samples/ios/FANSample/FANSample/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Base.lproj/Main.storyboard ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Extensions/NSObject+ClassName.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import Foundation extension NSObject { var className: String { return String(describing: type(of: self)) } class var className: String { return String(describing: self) } } ================================================ FILE: samples/ios/FANSample/FANSample/Extensions/UIView+NibContent.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit extension UIView { @discardableResult func fromNib() -> T? { guard let contentView = Bundle(for: type(of: self)).loadNibNamed(type(of: self).className, owner: self, options: nil)?.first as? T else { return nil } addSubview(contentView) contentView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ contentView.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor), contentView.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor), contentView.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor), contentView.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor) ]) return contentView } } ================================================ FILE: samples/ios/FANSample/FANSample/Extensions/UIViewController+Storyboard.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit extension UIViewController { static func create() -> ViewControllerType { UIStoryboard( name: "Main", bundle: nil ) .instantiateViewController( identifier: Self.className ) as! ViewControllerType } } ================================================ FILE: samples/ios/FANSample/FANSample/Info.plist ================================================ CFBundleDevelopmentRegion $(DEVELOPMENT_LANGUAGE) CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType $(PRODUCT_BUNDLE_PACKAGE_TYPE) CFBundleShortVersionString 1.0 CFBundleVersion 1 LSRequiresIPhoneOS UIApplicationSceneManifest UIApplicationSupportsMultipleScenes UISceneConfigurations UIWindowSceneSessionRoleApplication UISceneConfigurationName Default Configuration UISceneDelegateClassName $(PRODUCT_MODULE_NAME).SceneDelegate UISceneStoryboardFile Main UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UIStatusBarTintParameters UINavigationBar Style UIBarStyleDefault Translucent UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeRight UIInterfaceOrientationLandscapeLeft UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: samples/ios/FANSample/FANSample/Samples/BannerSampleViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork enum BannerAdType { case banner, mediumRect var title: String { switch self { case .banner: return "Banner" case .mediumRect: return "Medium Rectangle" } } } final class BannerSampleViewController: UIViewController { // MARK: - Properties private var adType: BannerAdType private var adView: FBAdView? private var adSize: FBAdSize { switch adType { case .banner: let isRegularWidth = traitCollection.horizontalSizeClass == .regular return isRegularWidth ? kFBAdSizeHeight90Banner : kFBAdSizeHeight50Banner case .mediumRect: return kFBAdSizeHeight250Rectangle } } private let statusLabel = UILabel() @IBOutlet private weak var bottomBarView: BottomBarView! // MARK: - Setup and Lifecylce static func create(adType: BannerAdType) -> BannerSampleViewController { let vc: BannerSampleViewController = BannerSampleViewController.create() vc.adType = adType return vc } override func viewDidLoad() { super.viewDidLoad() navigationItem.title = adType.title setupStatusLabel() loadAd() bottomBarView.tapHandler = { [weak self] in self?.loadAd() } } required init?(coder: NSCoder) { self.adType = .banner super.init(coder: coder) } private func setupStatusLabel() { view.addSubview(statusLabel) statusLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ statusLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), statusLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), statusLabel.bottomAnchor.constraint(equalTo: bottomBarView.topAnchor, constant: -16) ]) statusLabel.textAlignment = .center statusLabel.numberOfLines = 0 } // MARK: Helpers private func loadAd() { adView?.removeFromSuperview() adView = createNewAd() adView?.loadAd() statusLabel.text = AdStatus.isLoading.debugDescription } private func createNewAd() -> FBAdView { let adView = FBAdView(placementID: "YOUR_PLACEMENT_ID", adSize: adSize, rootViewController: self) adView.delegate = self return adView } } // MARK: FBAdViewDelegate extension BannerSampleViewController: FBAdViewDelegate { func adViewDidLoad(_ adView: FBAdView) { statusLabel.text = AdStatus.didLoad.debugDescription adView.backgroundColor = .clear adView.translatesAutoresizingMaskIntoConstraints = false view.addSubview(adView) NSLayoutConstraint.activate([ adView.heightAnchor.constraint(equalToConstant: adSize.size.height), adView.centerXAnchor.constraint(equalTo: view.centerXAnchor), adView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 30) ]) if adSize.size == kFBAdSizeHeight250Rectangle.size { NSLayoutConstraint.activate([adView.widthAnchor.constraint(equalToConstant: 300)]) } else { NSLayoutConstraint.activate([ adView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), adView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor) ]) } } func adViewDidClick(_ adView: FBAdView) { statusLabel.text = AdStatus.didClick.debugDescription } func adViewDidFinishHandlingClick(_ adView: FBAdView) { statusLabel.text = AdStatus.didFinishHandlingClick.debugDescription } func adView(_ adView: FBAdView, didFailWithError error: Error) { statusLabel.text = AdStatus.failure(error).debugDescription } func adViewWillLogImpression(_ adView: FBAdView) { statusLabel.text = AdStatus.willLogImpression.debugDescription } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/FullscreenAdSampleViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import os import UIKit import FBAudienceNetwork protocol FullscreenAd { func load() func show(from viewController: UIViewController) } extension FBInterstitialAd: FullscreenAd { func show(from viewController: UIViewController) { self.show(fromRootViewController: viewController) } } extension FBRewardedVideoAd: FullscreenAd { func show(from viewController: UIViewController) { self.show(fromRootViewController: viewController) } } extension FBRewardedInterstitialAd: FullscreenAd { func show(from viewController: UIViewController) { self.show(fromRootViewController: viewController, animated: true) } } enum FullscreenAdType { case interstitial, rewardedVideo, rewardedInterstitial var title: String { switch self { case .interstitial: return "Interstitial" case .rewardedVideo: return "Rewarded video" case .rewardedInterstitial: return "Rewarded interstitial" } } } final class FullscreenAdSampleViewController: UIViewController { // MARK: - Properties private var adType: FullscreenAdType private var ad: FullscreenAd? { didSet { if let ad = ad as? FBInterstitialAd { ad.delegate = self } else if let ad = ad as? FBRewardedVideoAd { ad.delegate = self } else if let ad = ad as? FBRewardedInterstitialAd { ad.delegate = self } } } private var state: LoadingState = .initial { didSet { switch state { case .initial: bottomBarView.set(buttonTitle: "Load Ad", isEnabled: true) case .loading: bottomBarView.set(buttonTitle: "Loading", isEnabled: false) case .loaded: bottomBarView.set(buttonTitle: "Show Ad", isEnabled: true) case .error(let message): bottomBarView.set(buttonTitle: "Retry", isEnabled: true) let alert = UIAlertController(title: "Error", message: message, preferredStyle: .alert) alert.addAction(UIAlertAction(title: "Close", style: .cancel, handler: nil)) present(alert, animated: true) } } } @IBOutlet private var bottomBarView: BottomBarView! // MARK: - Lifecycle and Setup static func create(adType: FullscreenAdType) -> UIViewController { let vc: FullscreenAdSampleViewController = FullscreenAdSampleViewController.create() vc.adType = adType return vc } required init?(coder: NSCoder) { self.adType = .interstitial super.init(coder: coder) } override func viewDidLoad() { super.viewDidLoad() ad = createNewAd() navigationItem.title = "\(adType.title) Ad" bottomBarView.tapHandler = { [weak self] in self?.handleTap() } } // MARK: - Helpers private func handleTap() { switch state { case .initial: loadAd() case .loading, .error: ad = createNewAd() loadAd() case .loaded: ad?.show(from: self) } } private func loadAd() { state = .loading ad?.load() } private func createNewAd() -> FullscreenAd { let placementID = "YOUR_PLACEMENT_ID" switch adType { case .interstitial: return FBInterstitialAd(placementID: placementID) case .rewardedVideo: return FBRewardedVideoAd(placementID: placementID) case .rewardedInterstitial: return FBRewardedInterstitialAd(placementID: placementID) } } } // MARK: - FBInterstitialAdDelegate extension FullscreenAdSampleViewController: FBInterstitialAdDelegate { func interstitialAdDidLoad(_ interstitialAd: FBInterstitialAd) { ad = interstitialAd state = .loaded } func interstitialAd(_ interstitialAd: FBInterstitialAd, didFailWithError error: Error) { state = .error(message: error.localizedDescription) } func interstitialAdDidClick(_ interstitialAd: FBInterstitialAd) { } func interstitialAdDidClose(_ interstitialAd: FBInterstitialAd) { ad = createNewAd() state = .initial } func interstitialAdWillClose(_ interstitialAd: FBInterstitialAd) { } func interstitialAdWillLogImpression(_ interstitialAd: FBInterstitialAd) { } } // MARK: - FBRewardedVideoAdDelegate extension FullscreenAdSampleViewController: FBRewardedVideoAdDelegate { func rewardedVideoAdDidLoad(_ rewardedVideoAd: FBRewardedVideoAd) { ad = rewardedVideoAd state = .loaded } func rewardedVideoAd(_ rewardedVideoAd: FBRewardedVideoAd, didFailWithError error: Error) { state = .error(message: error.localizedDescription) } func rewardedVideoAdDidClick(_ rewardedVideoAd: FBRewardedVideoAd) { } func rewardedVideoAdDidClose(_ rewardedVideoAd: FBRewardedVideoAd) { ad = createNewAd() state = .initial } func rewardedVideoAdServerRewardDidFail(_ rewardedVideoAd: FBRewardedVideoAd) { } func rewardedVideoAdVideoComplete(_ rewardedVideoAd: FBRewardedVideoAd) { } func rewardedVideoAdServerRewardDidSucceed(_ rewardedVideoAd: FBRewardedVideoAd) { } func rewardedVideoAdWillClose(_ rewardedVideoAd: FBRewardedVideoAd) { } func rewardedVideoAdWillLogImpression(_ rewardedVideoAd: FBRewardedVideoAd) { } } extension FullscreenAdSampleViewController: FBRewardedInterstitialAdDelegate { func rewardedInterstitialAdDidLoad(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded interstitial ad was loaded. Can present now.") ad = rewardedInterstitialAd state = .loaded } func rewardedInterstitialAd(_ rewardedInterstitialAd: FBRewardedInterstitialAd, didFailWithError error: Error) { let error = error as NSError os_log("Rewarded interstitial failed to load with error: %@", error.description) state = .error(message: "Rewarded interstitial ad failed to load. \(error.localizedDescription)") } func rewardedInterstitialAdDidClick(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded interstitial was clicked.") } func rewardedInterstitialAdDidClose(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded interstitial closed.") } func rewardedInterstitialAdWillClose(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded interstitial will close.") } func rewardedInterstitialAdWillLogImpression(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded impression is being captured.") } func rewardedInterstitialAdVideoComplete(_ rewardedInterstitialAd: FBRewardedInterstitialAd) { os_log("Rewarded interstitial ad video completed.") } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/Native/NativeAdScreenViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class NativeAdScreenViewController: UIViewController { // MARK: - Properties override var shouldAutorotate: Bool { false } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { [.portrait, .portraitUpsideDown] } @IBOutlet private var bottomBarView: BottomBarView! private var adView: NativeAdView! private let statusLabel = UILabel() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() navigationItem.title = AdFormatInfo.native.title setupSubviews() bottomBarView.tapHandler = { [weak adView] in adView?.load() } } // MARK: - UI Setup private func setupSubviews() { // Configure a status label that reports ad load status view.addSubview(statusLabel) statusLabel.translatesAutoresizingMaskIntoConstraints = false statusLabel.textAlignment = .center statusLabel.numberOfLines = 0 // Configure an Ad view that shows the layout of the ad adView = NativeAdView(ownerViewController: self) { [weak self] status in self?.statusLabel.text = status.debugDescription } view.addSubview(adView) adView.translatesAutoresizingMaskIntoConstraints = false // Setup constraints NSLayoutConstraint.activate([ statusLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), statusLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), statusLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16) ]) NSLayoutConstraint.activate([ adView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), adView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), adView.bottomAnchor.constraint(equalTo: bottomBarView.safeAreaLayoutGuide.topAnchor, constant: -32), adView.heightAnchor.constraint(equalToConstant: 300) ]) } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/Native/NativeAdView.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class NativeAdView: UIView { // MARK: - Properties @IBOutlet private var iconView: FBMediaView! @IBOutlet private var coverView: FBMediaView! @IBOutlet private var optionsView: FBAdOptionsView! @IBOutlet private var titleLabel: UILabel! @IBOutlet private var bodyLabel: UILabel! @IBOutlet private var sponsoredLabel: UILabel! @IBOutlet private var socialContextLabel: UILabel! @IBOutlet private var callToActionButton: UIButton! @IBOutlet private var bodyLabelTrailingToCTAButtonConstraint: NSLayoutConstraint! @IBOutlet private var bodyLabelTrailingToSuperviewConstraint: NSLayoutConstraint! private var ad: FBNativeAd? private let updateStatus: AdStatusUpdate private weak var ownerViewController: UIViewController? // MARK: - Setup init(ownerViewController: UIViewController, updateStatus: @escaping AdStatusUpdate) { self.ownerViewController = ownerViewController self.updateStatus = updateStatus super.init(frame: .zero) fromNib() coverView.delegate = self optionsView.isHidden = true } @available(*, unavailable) required init?(coder: NSCoder) { nil } func load() { updateStatus(.isLoading) /// Hide the view before loading a new one isHidden = true // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. let ad = FBNativeAd(placementID: "YOUR_PLACEMENT_ID") // Set the delegate of the ad object before loading the ad ad.delegate = self // Initiate a request to load an ad. ad.loadAd() } private func setupCallToActionButton(with title: String?) { guard let title = title else { callToActionButton.isHidden = true return } callToActionButton.isHidden = false callToActionButton.setTitle(title, for: .normal) } } // MARK - FBNativeAdDelegate extension NativeAdView: FBNativeAdDelegate { func nativeAdDidLoad(_ nativeAd: FBNativeAd) { updateStatus(.didLoad) if let ad = ad { ad.unregisterView() } isHidden = false ad = nativeAd titleLabel.text = nativeAd.advertiserName bodyLabel.text = nativeAd.bodyText socialContextLabel.text = nativeAd.socialContext sponsoredLabel.text = nativeAd.sponsoredTranslation setupCallToActionButton(with: nativeAd.callToAction) if let callToAction = nativeAd.callToAction, !callToAction.isEmpty { bodyLabelTrailingToCTAButtonConstraint.priority = .defaultHigh bodyLabelTrailingToSuperviewConstraint.priority = .defaultLow } else { bodyLabelTrailingToSuperviewConstraint.priority = .defaultHigh bodyLabelTrailingToCTAButtonConstraint.priority = .defaultLow } print("Register UIView for impression and click...") // Set native ad view tags to declare roles of your views for better analysis in future // We will be able to provide you statistics how often these views were clicked by users // Views provided by Facebook already have appropriate tag set titleLabel.nativeAdViewTag = .title bodyLabel.nativeAdViewTag = .body socialContextLabel.nativeAdViewTag = .socialContext callToActionButton.nativeAdViewTag = .callToAction // Specify the clickable areas. Views you were using to set ad view tags should be clickable. let clickableViews: [UIView] = [ iconView, titleLabel, bodyLabel, socialContextLabel, callToActionButton ] nativeAd.registerView( forInteraction: self, mediaView: coverView, iconView: iconView, viewController: ownerViewController, clickableViews: clickableViews ) // You may want to use this method if you want to have all subviews clickable // nativeAd.registerView( // forInteraction: self, // mediaView: coverView, // iconView: iconView, // viewController: ownerViewController // ) optionsView.isHidden = false optionsView.nativeAd = nativeAd layoutIfNeeded() } func nativeAdDidClick(_ nativeAd: FBNativeAd) { updateStatus(.didClick) } func nativeAdDidDownloadMedia(_ nativeAd: FBNativeAd) { updateStatus(.didDownloadMedia) } func nativeAdWillLogImpression(_ nativeAd: FBNativeAd) { updateStatus(.willLogImpression) } func nativeAdDidFinishHandlingClick(_ nativeAd: FBNativeAd) { updateStatus(.didFinishHandlingClick) } func nativeAd(_ nativeAd: FBNativeAd, didFailWithError error: Error) { updateStatus(.failure(error)) } } // MARK: - FBMediaViewDelegate extension NativeAdView: FBMediaViewDelegate { func mediaViewDidLoad(_ mediaView: FBMediaView) { print("Media view did load") } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/Native/NativeAdView.xib ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeBanner/NativeBannerAdScreenViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class NativeBannerAdScreenViewController: UIViewController { // MARK: - Properties @IBOutlet private var bottomBarView: BottomBarView! private var adView: NativeBannerAdView! private let statusLabel = UILabel() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() navigationItem.title = AdFormatInfo.nativeBanner.title setupStatusLabel() setupAdView() bottomBarView.tapHandler = { [weak adView] in adView?.load() } } // MARK: - UI Setup private func setupStatusLabel() { view.addSubview(statusLabel) statusLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ statusLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), statusLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), statusLabel.centerYAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerYAnchor) ]) statusLabel.textAlignment = .center statusLabel.numberOfLines = 0 } private func setupAdView() { adView = NativeBannerAdView(ownerViewController: self) { [weak self] status in self?.statusLabel.text = status.debugDescription } view.addSubview(adView) adView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ adView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), adView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), adView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeBanner/NativeBannerAdView.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class NativeBannerAdView: UIView { // MARK: - Properties @IBOutlet private var iconView: FBMediaView! @IBOutlet private var optionsView: FBAdOptionsView! @IBOutlet private var titleLabel: UILabel! @IBOutlet private var callToActionButton: UIButton! @IBOutlet private var sponsoredLabel: UILabel! private var ad: FBNativeBannerAd? private let updateStatus: AdStatusUpdate private weak var ownerViewController: UIViewController? // MARK: - Setup init(ownerViewController: UIViewController, updateStatus: @escaping AdStatusUpdate) { self.ownerViewController = ownerViewController self.updateStatus = updateStatus super.init(frame: .zero) fromNib() optionsView.isHidden = true } @available(*, unavailable) required init?(coder: NSCoder) { nil } func load() { updateStatus(.isLoading) /// Hide the view before loading a new one isHidden = true // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. let ad = FBNativeBannerAd(placementID: "YOUR_PLACEMENT_ID") // Set the delegate of the ad object before loading the ad ad.delegate = self // Initiate a request to load an ad. ad.loadAd() } private func setupCallToActionButton(with title: String?) { guard let title = title else { callToActionButton.isHidden = true return } callToActionButton.isHidden = false callToActionButton.setTitle(title, for: .normal) } } // MARK: - FBNativeBannerAdDelegate extension NativeBannerAdView: FBNativeBannerAdDelegate { func nativeBannerAdDidLoad(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didLoad) if let ad = ad { ad.unregisterView() } ad = nativeBannerAd isHidden = false titleLabel.text = nativeBannerAd.advertiserName sponsoredLabel.text = nativeBannerAd.sponsoredTranslation setupCallToActionButton(with: nativeBannerAd.callToAction) print("Register UIView for impression and click...") // Set native banner ad view tags to declare roles of your views for better analysis in future // We will be able to provide you statistics how often these views were clicked by users // Views provided by Facebook already have appropriate tag set titleLabel.nativeAdViewTag = .title callToActionButton.nativeAdViewTag = FBNativeAdViewTag.callToAction // Specify the clickable areas. View you were using to set ad view tags should be clickable. let clickableViews: [UIView] = [callToActionButton] nativeBannerAd.registerView( forInteraction: self, iconView: iconView, viewController: ownerViewController, clickableViews: clickableViews ) // If you don't want to provide native ad view tags you can simply // wire up UIView with the native banner ad and the whole UIView will be clickable. // nativeBannerAd.registerView( // forInteraction: iconView, // iconView: iconView, // viewController: ownerViewController // ) optionsView.nativeAd = nativeBannerAd optionsView.isHidden = false } func nativeBannerAdDidDownloadMedia(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didDownloadMedia) } func nativeBannerAdWillLogImpression(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.willLogImpression) } func nativeBannerAd(_ nativeBannerAd: FBNativeBannerAd, didFailWithError error: Error) { updateStatus(.failure(error)) } func nativeBannerAdDidClick(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didClick) } func nativeBannerAdDidFinishHandlingClick(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didFinishHandlingClick) } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeBanner/NativeBannerAdView.xib ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeBannerTemplate/NativeBannerTemplateAdScreenViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class NativeBannerTemplateAdScreenViewController: UIViewController { // MARK: - Properties @IBOutlet private var bottomBarView: BottomBarView! private var adView: NativeBannerTemplateAdView! private let statusLabel = UILabel() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() navigationItem.title = AdFormatInfo.nativeBannerTemplate.title setupSubviews() bottomBarView.tapHandler = { [weak adView] in adView?.load() } } private func setupSubviews() { adView = NativeBannerTemplateAdView { [weak self] status in self?.statusLabel.text = status.debugDescription } view.addSubview(adView) view.addSubview(statusLabel) statusLabel.textAlignment = .center statusLabel.numberOfLines = 0 adView.adViewType = .genericHeight50 statusLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ statusLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), statusLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), statusLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16) ]) NSLayoutConstraint.activate([ adView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor), adView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor), adView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor) ]) } // MARK: - IBActions @IBAction private func segmentedControlValueChanged(sender: UISegmentedControl) { switch sender.selectedSegmentIndex { case 0: adView.adViewType = .genericHeight50 case 1: adView.adViewType = .genericHeight100 default: adView.adViewType = .genericHeight120 } } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeBannerTemplate/NativeBannerTemplateAdView.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork extension FBNativeBannerAdViewType { var heightInPoints: CGFloat { switch self { case .genericHeight50: return 50 case .genericHeight100: return 100 case .genericHeight120: return 120 @unknown default: print("Unknown `FBNativeBannerAdViewType` type. Returning \(FBNativeBannerAdViewType.genericHeight50) instead.") return FBNativeBannerAdViewType.genericHeight50.heightInPoints } } } final class NativeBannerTemplateAdView: UIView { // MARK: - Properties var adViewType: FBNativeBannerAdViewType = .genericHeight50 { didSet { heightConstraint.constant = adViewType.heightInPoints load() } } private var adView: FBNativeBannerAdView! private var ad: FBNativeBannerAd? private let updateStatus: AdStatusUpdate private var heightConstraint: NSLayoutConstraint! // MARK: - Setup init(updateStatus: @escaping AdStatusUpdate) { self.updateStatus = updateStatus super.init(frame: .zero) translatesAutoresizingMaskIntoConstraints = false heightConstraint = heightAnchor.constraint(equalToConstant: adViewType.heightInPoints) heightConstraint.isActive = true } @available(*, unavailable) required init?(coder: NSCoder) { nil } func load() { /// Hide the view before loading a new one adView?.removeFromSuperview() // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. let ad = FBNativeBannerAd(placementID: "YOUR_PLACEMENT_ID") // Set the delegate of the ad object before loading the ad ad.delegate = self // Initiate a request to load an ad. ad.loadAd() } } extension NativeBannerTemplateAdView: FBNativeBannerAdDelegate { func nativeBannerAdDidLoad(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didLoad) if let ad = ad { ad.unregisterView() adView?.removeFromSuperview() adView = nil } guard nativeBannerAd.isAdValid else { updateStatus(.invalid) return } ad = nativeBannerAd adView = FBNativeBannerAdView(nativeBannerAd: nativeBannerAd, with: adViewType) adView.frame = bounds adView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(adView) layoutIfNeeded() } func nativeBannerAdDidDownloadMedia(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didDownloadMedia) } func nativeBannerAdWillLogImpression(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.willLogImpression) } func nativeBannerAd(_ nativeBannerAd: FBNativeBannerAd, didFailWithError error: Error) { updateStatus(.failure(error)) } func nativeBannerAdDidClick(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didClick) } func nativeBannerAdDidFinishHandlingClick(_ nativeBannerAd: FBNativeBannerAd) { updateStatus(.didFinishHandlingClick) } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeTemplate/NativeTemplateAdView.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class NativeTemplateAdView: UIView { // MARK: - Properties private lazy var adAttributes: FBNativeAdViewAttributes = { let attributes = FBNativeAdViewAttributes() attributes.backgroundColor = .white attributes.advertiserNameColor = UIColor(red: 0.11, green: 0.12, blue: 0.13, alpha: 1) attributes.buttonColor = UIColor(red: 0.235, green: 0.485, blue: 1, alpha: 1) attributes.buttonTitleColor = .white attributes.titleColor = .darkGray attributes.descriptionColor = .gray return attributes }() private var ad: FBNativeAd? private var adView: FBNativeAdView! private let updateStatus: AdStatusUpdate // MARK: - Setup init(updateStatus: @escaping AdStatusUpdate) { self.updateStatus = updateStatus super.init(frame: .zero) backgroundColor = .white } @available(*, unavailable) required init?(coder: NSCoder) { nil } func load() { updateStatus(.isLoading) // Remove the previous view before loading a new one adView?.removeFromSuperview() // Create a native ad request with a unique placement ID (generate your own on the Facebook app settings). // Use different ID for each ad placement in your app. let ad = FBNativeAd(placementID: "YOUR_PLACEMENT_ID") // Set the delegate of the ad object before loading the ad ad.delegate = self // Initiate a request to load an ad. ad.loadAd() } } // MARK - FBNativeAdDelegate extension NativeTemplateAdView: FBNativeAdDelegate { func nativeAdDidLoad(_ nativeAd: FBNativeAd) { updateStatus(.didLoad) if let ad = ad { ad.unregisterView() adView?.removeFromSuperview() adView = nil } guard nativeAd.isAdValid else { updateStatus(.invalid) return } ad = nativeAd adView = FBNativeAdView(nativeAd: nativeAd, with: adAttributes) adView.frame = bounds adView.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(adView) layoutIfNeeded() } func nativeAdDidClick(_ nativeAd: FBNativeAd) { updateStatus(.didClick) } func nativeAdDidDownloadMedia(_ nativeAd: FBNativeAd) { updateStatus(.didDownloadMedia) } func nativeAdWillLogImpression(_ nativeAd: FBNativeAd) { updateStatus(.willLogImpression) } func nativeAdDidFinishHandlingClick(_ nativeAd: FBNativeAd) { updateStatus(.didFinishHandlingClick) } func nativeAd(_ nativeAd: FBNativeAd, didFailWithError error: Error) { updateStatus(.failure(error)) } } ================================================ FILE: samples/ios/FANSample/FANSample/Samples/NativeTemplate/NativeTemplateScreenViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class NativeTemplateScreenViewController: UIViewController { // MARK: - Constants private enum Constants { enum Width { static let min: Float = 120 static let `default`: Float = 250 static let max: Float = 320 } enum Height { static let min: Float = 150 static let `default`: Float = 250 static let max: Float = 400 } } override var shouldAutorotate: Bool { false } override var supportedInterfaceOrientations: UIInterfaceOrientationMask { [.portrait, .portraitUpsideDown] } @IBOutlet private var widthSlider: UISlider! @IBOutlet private var heightSlider: UISlider! @IBOutlet private var slidersStackView: UIStackView! @IBOutlet private var bottomBarView: BottomBarView! private var heightConstraint: NSLayoutConstraint! private var widthConstraint: NSLayoutConstraint! private var adView: NativeTemplateAdView! private let statusLabel = UILabel() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() navigationItem.title = AdFormatInfo.nativeTemplate.title setupSubviews() bottomBarView.tapHandler = { [weak adView] in adView?.load() } } // MARK: - UI Setup private func setupSubviews() { adView = NativeTemplateAdView { [weak self] status in self?.statusLabel.text = status.debugDescription } view.addSubview(adView) view.addSubview(statusLabel) statusLabel.textAlignment = .center statusLabel.numberOfLines = 0 widthSlider.minimumValue = Constants.Width.min widthSlider.maximumValue = Constants.Width.max widthSlider.value = Constants.Width.default heightSlider.minimumValue = Constants.Height.min heightSlider.maximumValue = Constants.Height.max heightSlider.value = Constants.Height.default statusLabel.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ statusLabel.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 16), statusLabel.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -16), statusLabel.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 16) ]) adView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ adView.centerXAnchor.constraint(equalTo: view.safeAreaLayoutGuide.centerXAnchor), adView.bottomAnchor.constraint(equalTo: slidersStackView.topAnchor, constant: -32) ]) heightConstraint = adView.heightAnchor.constraint(equalToConstant: CGFloat(heightSlider.value)) heightConstraint.isActive = true widthConstraint = adView.widthAnchor.constraint(equalToConstant: CGFloat(widthSlider.value)) widthConstraint.isActive = true } // MARK: - IBActions @IBAction private func widthSliderValueChanged(sender: UISlider) { widthConstraint.constant = CGFloat(sender.value) } @IBAction private func heightSliderValueChanged(sender: UISlider) { heightConstraint.constant = CGFloat(sender.value) } } ================================================ FILE: samples/ios/FANSample/FANSample/SamplesViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class SamplesViewController: UITableViewController { // MARK: - Types private struct Section { let title: String let objects: [AdFormatInfo] } // MARK: - Properties private let sections: [Section] = { let nativeSection = Section( title: "Native", objects: [.native, .nativeTemplate, .nativeBanner, .nativeBannerTemplate] ) let bannerSection = Section( title: "Banner", objects: [.banner, .mediumRect] ) let fullscreenSection = Section( title: "Fullscreen", objects: [.interstitial, .rewardedVideo, .rewardedInterstitial] ) return [nativeSection, bannerSection, fullscreenSection] }() private let sdkInfoLabel: UILabel = { let sdkInfoLabel = UILabel(frame: CGRect(x: 0, y: 0, width: 0, height: 50)) sdkInfoLabel.textAlignment = .center sdkInfoLabel.text = "AN SDK \(FB_AD_SDK_VERSION)" return sdkInfoLabel }() // MARK: - Lifecycle override func viewDidLoad() { super.viewDidLoad() tableView.tableFooterView = sdkInfoLabel } private func createViewController(for adFormat: AdFormatInfo) -> UIViewController? { let vc: UIViewController? switch adFormat { case .interstitial: vc = FullscreenAdSampleViewController.create(adType: .interstitial) case .rewardedVideo: vc = FullscreenAdSampleViewController.create(adType: .rewardedVideo) case .rewardedInterstitial: vc = FullscreenAdSampleViewController.create(adType: .rewardedInterstitial) case .banner: vc = BannerSampleViewController.create(adType: .banner) case .native: vc = NativeAdScreenViewController.create() case .nativeBanner: vc = NativeBannerAdScreenViewController.create() case .nativeTemplate: vc = NativeTemplateScreenViewController.create() case .mediumRect: vc = BannerSampleViewController.create(adType: .mediumRect) case .nativeBannerTemplate: vc = NativeBannerTemplateAdScreenViewController.create() } return vc } // MARK: - Settings @IBAction private func settingsButtonTapped() { let navigationController = NavigationController(nibName: nil, bundle: nil) navigationController.viewControllers = [SettingScreenViewController.create()] self.navigationController?.present(navigationController, animated: true, completion: nil) } // MARK: - Table View override func numberOfSections(in tableView: UITableView) -> Int { sections.count } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { sections[section].objects.count } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) let currentObject = sections[indexPath.section].objects[indexPath.row] guard let vc = createViewController(for: currentObject) else { return } navigationController?.pushViewController(vc, animated: true) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let currentSection = sections[indexPath.section] let cell = tableView.dequeueReusableCell(withIdentifier: "AdFormatCell", for: indexPath) cell.textLabel?.text = currentSection.objects[indexPath.row].title return cell } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { sections[section].title } } ================================================ FILE: samples/ios/FANSample/FANSample/SceneDelegate.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit class SceneDelegate: UIResponder, UIWindowSceneDelegate, UISplitViewControllerDelegate { var window: UIWindow? func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. // This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead). } func sceneDidDisconnect(_ scene: UIScene) { // Called as the scene is being released by the system. // This occurs shortly after the scene enters the background, or when its session is discarded. // Release any resources associated with this scene that can be re-created the next time the scene connects. // The scene may re-connect later, as its session was not neccessarily discarded (see `application:didDiscardSceneSessions` instead). } func sceneDidBecomeActive(_ scene: UIScene) { // Called when the scene has moved from an inactive state to an active state. // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. } func sceneWillResignActive(_ scene: UIScene) { // Called when the scene will move from an active state to an inactive state. // This may occur due to temporary interruptions (ex. an incoming phone call). } func sceneWillEnterForeground(_ scene: UIScene) { // Called as the scene transitions from the background to the foreground. // Use this method to undo the changes made on entering the background. } func sceneDidEnterBackground(_ scene: UIScene) { // Called as the scene transitions from the foreground to the background. // Use this method to save data, release shared resources, and store enough scene-specific state information // to restore the scene back to its current state. } } ================================================ FILE: samples/ios/FANSample/FANSample/Settings/Picker/PickerTableViewCell.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class PickerTableViewCell: UITableViewCell { // MARK: - Properties var dataSource: PickerCellViewModelAPI? { didSet { guard let dataSource = dataSource else { return } pickerView.selectRow(dataSource.selectedRow, inComponent: 0, animated: false) titleLabel.text = dataSource.title textField.text = dataSource.name(by: dataSource.selectedRow) } } private let pickerView = UIPickerView() @IBOutlet private var titleLabel: UILabel! @IBOutlet private var textField: UITextField! // MARK: - Lifecycle override func awakeFromNib() { super.awakeFromNib() pickerView.dataSource = self pickerView.delegate = self textField.inputView = pickerView textField.inputAccessoryView = createToolbar() } override func prepareForReuse() { super.prepareForReuse() dataSource = nil } private func createToolbar() -> UIToolbar { let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44)) let flexItem = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) let doneItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneButtonTapped)) toolbar.items = [flexItem, doneItem] toolbar.sizeToFit() return toolbar } // MARK: - Actions @objc private func doneButtonTapped() { textField.resignFirstResponder() } } // MARK: - UIPickerViewDelegate, UIPickerViewDataSource extension PickerTableViewCell: UIPickerViewDelegate, UIPickerViewDataSource { func numberOfComponents(in pickerView: UIPickerView) -> Int { 1 } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { dataSource?.numberOfRows ?? 0 } func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { dataSource?.name(by: row) } func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { dataSource?.select(index: row) textField.text = dataSource?.name(by: row) } } ================================================ FILE: samples/ios/FANSample/FANSample/Settings/Picker/PickerTableViewCell.xib ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Settings/Picker/ViewModels.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import Foundation import FBAudienceNetwork protocol PickerCellViewModelAPI { var title: String { get } var selectedRow: Int { get } var numberOfRows: Int { get } func name(by index: Int) -> String? func select(index: Int) } struct LogLevelCellViewModel: PickerCellViewModelAPI { let title = "Log Level" var numberOfRows: Int { nameByLevel.count } var selectedRow: Int { FBAdSettings.getLogLevel().rawValue } private let nameByLevel: [FBAdLogLevel: String] = [ .none : "None", .notification : "Notification", .error : "Error", .warning : "Warning", .log : "Log", .debug : "Debug", .verbose : "Verbose" ] func name(by index: Int) -> String? { guard let type = FBAdLogLevel(rawValue: index) else { print("Error: unable to map index to `FBAdLogLevel`") return nil } return nameByLevel[type] } func select(index: Int) { guard let level = FBAdLogLevel(rawValue: index) else { return } FBAdSettings.setLogLevel(level) } } struct AdTypeCellViewModel: PickerCellViewModelAPI { let title = "Ad Type" var numberOfRows: Int { nameByType.count } var selectedRow: Int { FBAdSettings.testAdType.rawValue } private let nameByType: [FBAdTestAdType: String] = [ .default : "default", .img_16_9_App_Install : "image_install", .img_16_9_Link : "image_link", .vid_HD_16_9_46s_App_Install : "video_16x9_46s_install", .vid_HD_16_9_46s_Link : "video_16x9_46s_link", .vid_HD_16_9_15s_App_Install : "video_16x9_15s_install", .vid_HD_16_9_15s_Link : "video_16x9_15s_link", .vid_HD_9_16_39s_App_Install : "video_9x16_39s_install", .vid_HD_9_16_39s_Link : "video_9x16_39s_link", .carousel_Img_Square_App_Install : "carousel_install", .carousel_Img_Square_Link : "carousel_link", .carousel_Vid_Square_Link : "carousel_video", .playable : "playable" ] func name(by index: Int) -> String? { guard let type = FBAdTestAdType(rawValue: index) else { print("Error: unable to map index to `FBAdTestAdType`") return nil } return nameByType[type] } func select(index: Int) { guard let type = FBAdTestAdType(rawValue: index) else { return } FBAdSettings.testAdType = type } } ================================================ FILE: samples/ios/FANSample/FANSample/Settings/SettingScreenViewController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class SettingScreenViewController: UITableViewController { // MARK: - Properties private lazy var adTypeCellViewModel = AdTypeCellViewModel() private lazy var logLevelCellViewModel = LogLevelCellViewModel() // MARK: - Lifecylce override func viewDidLoad() { super.viewDidLoad() navigationItem.title = "Settings" tableView.register( UINib(nibName: "TestModeTableViewCell", bundle: nil), forCellReuseIdentifier: "TestModeTableViewCell" ) tableView.register( UINib(nibName: "PickerTableViewCell", bundle: nil), forCellReuseIdentifier: "PickerTableViewCell" ) tableView.rowHeight = 48 tableView.allowsSelection = false } // MARK: - Table View override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 3 } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch indexPath.row { case 0: let cell = tableView.dequeueReusableCell(withIdentifier: "TestModeTableViewCell", for: indexPath) as! TestModeTableViewCell return cell case 1: let cell = tableView.dequeueReusableCell(withIdentifier: "PickerTableViewCell", for: indexPath) as! PickerTableViewCell cell.dataSource = adTypeCellViewModel return cell case 2: let cell = tableView.dequeueReusableCell(withIdentifier: "PickerTableViewCell", for: indexPath) as! PickerTableViewCell cell.dataSource = logLevelCellViewModel return cell default: return UITableViewCell() } } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { "SDK Version \(FB_AD_SDK_VERSION)" } // MARK: - Actions @IBAction private func dismissButtonTapped() { dismiss(animated: true, completion: nil) } } ================================================ FILE: samples/ios/FANSample/FANSample/Settings/TestMode/TestModeTableViewCell.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class TestModeTableViewCell: UITableViewCell { @IBOutlet private var testModeSwitch: UISwitch! override func awakeFromNib() { super.awakeFromNib() testModeSwitch.isOn = FBAdSettings.isTestMode() } @IBAction private func testModeSwitchValueChanged(sender: UISwitch) { let testDeviceHash = FBAdSettings.testDeviceHash() if sender.isOn { FBAdSettings.addTestDevice(testDeviceHash) } else { FBAdSettings.clearTestDevice(testDeviceHash) } } } ================================================ FILE: samples/ios/FANSample/FANSample/Settings/TestMode/TestModeTableViewCell.xib ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Utils/AdUtils.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import Foundation typealias AdStatusUpdate = (AdStatus) -> Void enum AdStatus: CustomDebugStringConvertible { case willLogImpression case failure(Error) case invalid case didClick case didFinishHandlingClick case isLoading case didLoad case didDownloadMedia var debugDescription: String { switch self { case .didClick: return "Ad was clicked" case .failure(let error): return "Ad failed to load with error: " + error.localizedDescription case .invalid: return "Ad is invalid" case .didLoad: return "Ad did load" case .isLoading: return "Ad is loading" case .didDownloadMedia: return "Ad did download media" case .willLogImpression: return "Ad impression is being captured" case .didFinishHandlingClick: return "Ad did finish handling click" } } } enum LoadingState { case initial case loading case loaded case error(message: String) } enum AdFormatInfo { case native case nativeTemplate case nativeBanner case nativeBannerTemplate case banner case mediumRect case interstitial case rewardedVideo case rewardedInterstitial var title: String { switch self { case .native: return "Native" case .nativeTemplate: return "Native (Template)" case .nativeBanner: return "Native Banner" case .nativeBannerTemplate: return "Native Banner (Template)" case .banner: return "Banner" case .mediumRect: return "Medium Rectangle" case .interstitial: return "Interstitial" case .rewardedVideo: return "Rewarded Video" case .rewardedInterstitial: return "Rewarded Interstitial" } } } ================================================ FILE: samples/ios/FANSample/FANSample/Utils/BottomBarView.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit import FBAudienceNetwork final class BottomBarView: UIView { // MARK: - Types typealias TapHandler = () -> Void // MARK: - Properties var tapHandler: TapHandler! @IBOutlet private var button: UIButton! @IBOutlet private var testModeSwitch: UISwitch! // MARK: - Setup override init(frame: CGRect) { super.init(frame: frame) setup() } required init?(coder: NSCoder) { super.init(coder: coder) setup() } private func setup() { fromNib() testModeSwitch.isOn = FBAdSettings.isTestMode() } // MARK: - Actions @IBAction private func buttonTapped() { tapHandler() } @IBAction private func testModeSwitchValueChanged(sender: UISwitch) { let testDeviceHash = FBAdSettings.testDeviceHash() if sender.isOn { FBAdSettings.addTestDevice(testDeviceHash) } else { FBAdSettings.clearTestDevice(testDeviceHash) } } func set(buttonTitle: String, isEnabled: Bool) { button.setTitle(buttonTitle, for: .normal) button.isEnabled = isEnabled } } ================================================ FILE: samples/ios/FANSample/FANSample/Utils/BottomBarView.xib ================================================ ================================================ FILE: samples/ios/FANSample/FANSample/Utils/NavigationController.swift ================================================ // (c) Facebook, Inc. and its affiliates. Confidential and proprietary. import UIKit final class NavigationController: UINavigationController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { topViewController?.supportedInterfaceOrientations ?? .all } override var shouldAutorotate: Bool { topViewController?.shouldAutorotate ?? false } } ================================================ FILE: samples/ios/FANSample/FANSample.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 51; objects = { /* Begin PBXBuildFile section */ 1437CFB92538A405003DB489 /* UIViewController+Storyboard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1437CFB82538A405003DB489 /* UIViewController+Storyboard.swift */; }; 14548A11253E0DC000E62C49 /* AdUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 14548A10253E0DC000E62C49 /* AdUtils.swift */; }; 145A31CE253ED12000A83B62 /* PickerTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31CC253ED12000A83B62 /* PickerTableViewCell.swift */; }; 145A31CF253ED12000A83B62 /* PickerTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 145A31CD253ED12000A83B62 /* PickerTableViewCell.xib */; }; 145A31D6253EE15A00A83B62 /* ViewModels.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31D5253EE15A00A83B62 /* ViewModels.swift */; }; 145A31F8253EF50300A83B62 /* FullscreenAdSampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31E8253EF50300A83B62 /* FullscreenAdSampleViewController.swift */; }; 145A31F9253EF50300A83B62 /* NativeAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31EA253EF50300A83B62 /* NativeAdView.swift */; }; 145A31FA253EF50300A83B62 /* NativeAdScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31EB253EF50300A83B62 /* NativeAdScreenViewController.swift */; }; 145A31FB253EF50300A83B62 /* NativeAdView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 145A31EC253EF50300A83B62 /* NativeAdView.xib */; }; 145A31FC253EF50300A83B62 /* NativeBannerTemplateAdScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31EE253EF50300A83B62 /* NativeBannerTemplateAdScreenViewController.swift */; }; 145A31FD253EF50300A83B62 /* NativeBannerTemplateAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31EF253EF50300A83B62 /* NativeBannerTemplateAdView.swift */; }; 145A31FE253EF50300A83B62 /* NativeBannerAdScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31F1253EF50300A83B62 /* NativeBannerAdScreenViewController.swift */; }; 145A31FF253EF50300A83B62 /* NativeBannerAdView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 145A31F2253EF50300A83B62 /* NativeBannerAdView.xib */; }; 145A3200253EF50300A83B62 /* NativeBannerAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31F3253EF50300A83B62 /* NativeBannerAdView.swift */; }; 145A3201253EF50300A83B62 /* NativeTemplateAdView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31F5253EF50300A83B62 /* NativeTemplateAdView.swift */; }; 145A3202253EF50300A83B62 /* NativeTemplateScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31F6253EF50300A83B62 /* NativeTemplateScreenViewController.swift */; }; 145A3203253EF50300A83B62 /* BannerSampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A31F7253EF50300A83B62 /* BannerSampleViewController.swift */; }; 145A3206253EF57800A83B62 /* SamplesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A3205253EF57800A83B62 /* SamplesViewController.swift */; }; 145A320A253EF5BC00A83B62 /* BottomBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A3208253EF5BC00A83B62 /* BottomBarView.swift */; }; 145A320B253EF5BC00A83B62 /* BottomBarView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 145A3209253EF5BC00A83B62 /* BottomBarView.xib */; }; 145A320E253EF61D00A83B62 /* NavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 145A320D253EF61D00A83B62 /* NavigationController.swift */; }; 1468FC7A252F33B7004E2CD9 /* NSObject+ClassName.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1468FC79252F33B7004E2CD9 /* NSObject+ClassName.swift */; }; 1468FC7C252F33D1004E2CD9 /* UIView+NibContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1468FC7B252F33D1004E2CD9 /* UIView+NibContent.swift */; }; 1499C93E253E495A003E0FE5 /* SettingScreenViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1499C93D253E495A003E0FE5 /* SettingScreenViewController.swift */; }; 1499C945253E4DA3003E0FE5 /* TestModeTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1499C943253E4DA3003E0FE5 /* TestModeTableViewCell.swift */; }; 1499C946253E4DA3003E0FE5 /* TestModeTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1499C944253E4DA3003E0FE5 /* TestModeTableViewCell.xib */; }; 82B89F4623F7F95900DF6E14 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B89F4523F7F95900DF6E14 /* AppDelegate.swift */; }; 82B89F4823F7F95900DF6E14 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 82B89F4723F7F95900DF6E14 /* SceneDelegate.swift */; }; 82B89F4F23F7F95900DF6E14 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82B89F4D23F7F95900DF6E14 /* Main.storyboard */; }; 82B89F5123F7F95B00DF6E14 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 82B89F5023F7F95B00DF6E14 /* Assets.xcassets */; }; 82B89F5423F7F95B00DF6E14 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 82B89F5223F7F95B00DF6E14 /* LaunchScreen.storyboard */; }; 9E769FD66DA26D7240AE192E /* Pods_FANSample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5A2B6B472CA61D8834794B3B /* Pods_FANSample.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 1437CFB82538A405003DB489 /* UIViewController+Storyboard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIViewController+Storyboard.swift"; sourceTree = ""; }; 14548A10253E0DC000E62C49 /* AdUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdUtils.swift; sourceTree = ""; }; 145A31CC253ED12000A83B62 /* PickerTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickerTableViewCell.swift; sourceTree = ""; }; 145A31CD253ED12000A83B62 /* PickerTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PickerTableViewCell.xib; sourceTree = ""; }; 145A31D5253EE15A00A83B62 /* ViewModels.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewModels.swift; sourceTree = ""; }; 145A31E8253EF50300A83B62 /* FullscreenAdSampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FullscreenAdSampleViewController.swift; sourceTree = ""; }; 145A31EA253EF50300A83B62 /* NativeAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeAdView.swift; sourceTree = ""; }; 145A31EB253EF50300A83B62 /* NativeAdScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeAdScreenViewController.swift; sourceTree = ""; }; 145A31EC253EF50300A83B62 /* NativeAdView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NativeAdView.xib; sourceTree = ""; }; 145A31EE253EF50300A83B62 /* NativeBannerTemplateAdScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeBannerTemplateAdScreenViewController.swift; sourceTree = ""; }; 145A31EF253EF50300A83B62 /* NativeBannerTemplateAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeBannerTemplateAdView.swift; sourceTree = ""; }; 145A31F1253EF50300A83B62 /* NativeBannerAdScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeBannerAdScreenViewController.swift; sourceTree = ""; }; 145A31F2253EF50300A83B62 /* NativeBannerAdView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = NativeBannerAdView.xib; sourceTree = ""; }; 145A31F3253EF50300A83B62 /* NativeBannerAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeBannerAdView.swift; sourceTree = ""; }; 145A31F5253EF50300A83B62 /* NativeTemplateAdView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeTemplateAdView.swift; sourceTree = ""; }; 145A31F6253EF50300A83B62 /* NativeTemplateScreenViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NativeTemplateScreenViewController.swift; sourceTree = ""; }; 145A31F7253EF50300A83B62 /* BannerSampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BannerSampleViewController.swift; sourceTree = ""; }; 145A3205253EF57800A83B62 /* SamplesViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SamplesViewController.swift; sourceTree = ""; }; 145A3208253EF5BC00A83B62 /* BottomBarView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomBarView.swift; sourceTree = ""; }; 145A3209253EF5BC00A83B62 /* BottomBarView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = BottomBarView.xib; sourceTree = ""; }; 145A320D253EF61D00A83B62 /* NavigationController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationController.swift; sourceTree = ""; }; 145A321B253F22C800A83B62 /* README.md */ = {isa = PBXFileReference; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = SOURCE_ROOT; }; 1468FC79252F33B7004E2CD9 /* NSObject+ClassName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSObject+ClassName.swift"; sourceTree = ""; }; 1468FC7B252F33D1004E2CD9 /* UIView+NibContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIView+NibContent.swift"; sourceTree = ""; }; 1499C93D253E495A003E0FE5 /* SettingScreenViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingScreenViewController.swift; sourceTree = ""; }; 1499C943253E4DA3003E0FE5 /* TestModeTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TestModeTableViewCell.swift; sourceTree = ""; }; 1499C944253E4DA3003E0FE5 /* TestModeTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TestModeTableViewCell.xib; sourceTree = ""; }; 4F0CF2FBCD28B527F12C5658 /* Pods-FANSample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FANSample.debug.xcconfig"; path = "Target Support Files/Pods-FANSample/Pods-FANSample.debug.xcconfig"; sourceTree = ""; }; 5A2B6B472CA61D8834794B3B /* Pods_FANSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_FANSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 7344E3D24EBE09AC50121E89 /* Pods-FANSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-FANSample.release.xcconfig"; path = "Target Support Files/Pods-FANSample/Pods-FANSample.release.xcconfig"; sourceTree = ""; }; 82B89F4223F7F95900DF6E14 /* FANSample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = FANSample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 82B89F4523F7F95900DF6E14 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 82B89F4723F7F95900DF6E14 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 82B89F4E23F7F95900DF6E14 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 82B89F5023F7F95B00DF6E14 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 82B89F5323F7F95B00DF6E14 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 82B89F5523F7F95B00DF6E14 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 82B89F3F23F7F95900DF6E14 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( 9E769FD66DA26D7240AE192E /* Pods_FANSample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 14548A0F253E0DA300E62C49 /* Utils */ = { isa = PBXGroup; children = ( 145A320D253EF61D00A83B62 /* NavigationController.swift */, 145A3208253EF5BC00A83B62 /* BottomBarView.swift */, 145A3209253EF5BC00A83B62 /* BottomBarView.xib */, 14548A10253E0DC000E62C49 /* AdUtils.swift */, ); path = Utils; sourceTree = ""; }; 145A31D3253EE13800A83B62 /* Picker */ = { isa = PBXGroup; children = ( 145A31CC253ED12000A83B62 /* PickerTableViewCell.swift */, 145A31CD253ED12000A83B62 /* PickerTableViewCell.xib */, 145A31D5253EE15A00A83B62 /* ViewModels.swift */, ); path = Picker; sourceTree = ""; }; 145A31D4253EE14600A83B62 /* TestMode */ = { isa = PBXGroup; children = ( 1499C943253E4DA3003E0FE5 /* TestModeTableViewCell.swift */, 1499C944253E4DA3003E0FE5 /* TestModeTableViewCell.xib */, ); path = TestMode; sourceTree = ""; }; 145A31E7253EF50300A83B62 /* Samples */ = { isa = PBXGroup; children = ( 145A31F7253EF50300A83B62 /* BannerSampleViewController.swift */, 145A31E8253EF50300A83B62 /* FullscreenAdSampleViewController.swift */, 145A31E9253EF50300A83B62 /* Native */, 145A31ED253EF50300A83B62 /* NativeBannerTemplate */, 145A31F0253EF50300A83B62 /* NativeBanner */, 145A31F4253EF50300A83B62 /* NativeTemplate */, ); path = Samples; sourceTree = ""; }; 145A31E9253EF50300A83B62 /* Native */ = { isa = PBXGroup; children = ( 145A31EA253EF50300A83B62 /* NativeAdView.swift */, 145A31EB253EF50300A83B62 /* NativeAdScreenViewController.swift */, 145A31EC253EF50300A83B62 /* NativeAdView.xib */, ); path = Native; sourceTree = ""; }; 145A31ED253EF50300A83B62 /* NativeBannerTemplate */ = { isa = PBXGroup; children = ( 145A31EE253EF50300A83B62 /* NativeBannerTemplateAdScreenViewController.swift */, 145A31EF253EF50300A83B62 /* NativeBannerTemplateAdView.swift */, ); path = NativeBannerTemplate; sourceTree = ""; }; 145A31F0253EF50300A83B62 /* NativeBanner */ = { isa = PBXGroup; children = ( 145A31F1253EF50300A83B62 /* NativeBannerAdScreenViewController.swift */, 145A31F2253EF50300A83B62 /* NativeBannerAdView.xib */, 145A31F3253EF50300A83B62 /* NativeBannerAdView.swift */, ); path = NativeBanner; sourceTree = ""; }; 145A31F4253EF50300A83B62 /* NativeTemplate */ = { isa = PBXGroup; children = ( 145A31F5253EF50300A83B62 /* NativeTemplateAdView.swift */, 145A31F6253EF50300A83B62 /* NativeTemplateScreenViewController.swift */, ); path = NativeTemplate; sourceTree = ""; }; 1468FC78252F33A5004E2CD9 /* Extensions */ = { isa = PBXGroup; children = ( 1468FC79252F33B7004E2CD9 /* NSObject+ClassName.swift */, 1468FC7B252F33D1004E2CD9 /* UIView+NibContent.swift */, 1437CFB82538A405003DB489 /* UIViewController+Storyboard.swift */, ); path = Extensions; sourceTree = ""; }; 1499C942253E4CDF003E0FE5 /* Settings */ = { isa = PBXGroup; children = ( 1499C93D253E495A003E0FE5 /* SettingScreenViewController.swift */, 145A31D4253EE14600A83B62 /* TestMode */, 145A31D3253EE13800A83B62 /* Picker */, ); path = Settings; sourceTree = ""; }; 57008FCE14BB49DABB99EE2F /* Pods */ = { isa = PBXGroup; children = ( 4F0CF2FBCD28B527F12C5658 /* Pods-FANSample.debug.xcconfig */, 7344E3D24EBE09AC50121E89 /* Pods-FANSample.release.xcconfig */, ); path = Pods; sourceTree = ""; }; 82B89F3923F7F95900DF6E14 = { isa = PBXGroup; children = ( 82B89F4423F7F95900DF6E14 /* FANSample */, 82B89F4323F7F95900DF6E14 /* Products */, 57008FCE14BB49DABB99EE2F /* Pods */, D1A18B97378710965348E129 /* Frameworks */, ); sourceTree = ""; }; 82B89F4323F7F95900DF6E14 /* Products */ = { isa = PBXGroup; children = ( 82B89F4223F7F95900DF6E14 /* FANSample.app */, ); name = Products; sourceTree = ""; }; 82B89F4423F7F95900DF6E14 /* FANSample */ = { isa = PBXGroup; children = ( 145A321B253F22C800A83B62 /* README.md */, 82B89F5523F7F95B00DF6E14 /* Info.plist */, 82B89F5023F7F95B00DF6E14 /* Assets.xcassets */, 82B89F5223F7F95B00DF6E14 /* LaunchScreen.storyboard */, 82B89F4D23F7F95900DF6E14 /* Main.storyboard */, 82B89F4523F7F95900DF6E14 /* AppDelegate.swift */, 82B89F4723F7F95900DF6E14 /* SceneDelegate.swift */, 145A3205253EF57800A83B62 /* SamplesViewController.swift */, 145A31E7253EF50300A83B62 /* Samples */, 1499C942253E4CDF003E0FE5 /* Settings */, 1468FC78252F33A5004E2CD9 /* Extensions */, 14548A0F253E0DA300E62C49 /* Utils */, ); path = FANSample; sourceTree = ""; }; D1A18B97378710965348E129 /* Frameworks */ = { isa = PBXGroup; children = ( 5A2B6B472CA61D8834794B3B /* Pods_FANSample.framework */, ); name = Frameworks; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 82B89F4123F7F95900DF6E14 /* FANSample */ = { isa = PBXNativeTarget; buildConfigurationList = 82B89F5823F7F95B00DF6E14 /* Build configuration list for PBXNativeTarget "FANSample" */; buildPhases = ( A1609BF6C269CF969F41C6B1 /* [CP] Check Pods Manifest.lock */, 82B89F3E23F7F95900DF6E14 /* Sources */, 82B89F3F23F7F95900DF6E14 /* Frameworks */, 82B89F4023F7F95900DF6E14 /* Resources */, 63A734DE5EB10572F77F4766 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); dependencies = ( ); name = FANSample; productName = FANSample; productReference = 82B89F4223F7F95900DF6E14 /* FANSample.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 82B89F3A23F7F95900DF6E14 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 1130; LastUpgradeCheck = 1130; ORGANIZATIONNAME = "Facebook, Inc."; TargetAttributes = { 82B89F4123F7F95900DF6E14 = { CreatedOnToolsVersion = 11.3; LastSwiftMigration = 1160; }; }; }; buildConfigurationList = 82B89F3D23F7F95900DF6E14 /* Build configuration list for PBXProject "FANSample" */; compatibilityVersion = "Xcode 9.3"; developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 82B89F3923F7F95900DF6E14; productRefGroup = 82B89F4323F7F95900DF6E14 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 82B89F4123F7F95900DF6E14 /* FANSample */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 82B89F4023F7F95900DF6E14 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 82B89F5423F7F95B00DF6E14 /* LaunchScreen.storyboard in Resources */, 82B89F5123F7F95B00DF6E14 /* Assets.xcassets in Resources */, 82B89F4F23F7F95900DF6E14 /* Main.storyboard in Resources */, 1499C946253E4DA3003E0FE5 /* TestModeTableViewCell.xib in Resources */, 145A31FF253EF50300A83B62 /* NativeBannerAdView.xib in Resources */, 145A31FB253EF50300A83B62 /* NativeAdView.xib in Resources */, 145A31CF253ED12000A83B62 /* PickerTableViewCell.xib in Resources */, 145A320B253EF5BC00A83B62 /* BottomBarView.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ 63A734DE5EB10572F77F4766 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-FANSample/Pods-FANSample-frameworks-${CONFIGURATION}-input-files.xcfilelist", ); name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( "${PODS_ROOT}/Target Support Files/Pods-FANSample/Pods-FANSample-frameworks-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-FANSample/Pods-FANSample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; A1609BF6C269CF969F41C6B1 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); inputPaths = ( "${PODS_PODFILE_DIR_PATH}/Podfile.lock", "${PODS_ROOT}/Manifest.lock", ); name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( "$(DERIVED_FILE_DIR)/Pods-FANSample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 82B89F3E23F7F95900DF6E14 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 145A3200253EF50300A83B62 /* NativeBannerAdView.swift in Sources */, 1499C945253E4DA3003E0FE5 /* TestModeTableViewCell.swift in Sources */, 1468FC7C252F33D1004E2CD9 /* UIView+NibContent.swift in Sources */, 145A31FE253EF50300A83B62 /* NativeBannerAdScreenViewController.swift in Sources */, 14548A11253E0DC000E62C49 /* AdUtils.swift in Sources */, 145A3202253EF50300A83B62 /* NativeTemplateScreenViewController.swift in Sources */, 1499C93E253E495A003E0FE5 /* SettingScreenViewController.swift in Sources */, 145A31FD253EF50300A83B62 /* NativeBannerTemplateAdView.swift in Sources */, 82B89F4623F7F95900DF6E14 /* AppDelegate.swift in Sources */, 145A31CE253ED12000A83B62 /* PickerTableViewCell.swift in Sources */, 145A320A253EF5BC00A83B62 /* BottomBarView.swift in Sources */, 82B89F4823F7F95900DF6E14 /* SceneDelegate.swift in Sources */, 145A3203253EF50300A83B62 /* BannerSampleViewController.swift in Sources */, 145A31FA253EF50300A83B62 /* NativeAdScreenViewController.swift in Sources */, 145A31FC253EF50300A83B62 /* NativeBannerTemplateAdScreenViewController.swift in Sources */, 145A320E253EF61D00A83B62 /* NavigationController.swift in Sources */, 145A31D6253EE15A00A83B62 /* ViewModels.swift in Sources */, 1468FC7A252F33B7004E2CD9 /* NSObject+ClassName.swift in Sources */, 145A3206253EF57800A83B62 /* SamplesViewController.swift in Sources */, 145A3201253EF50300A83B62 /* NativeTemplateAdView.swift in Sources */, 145A31F8253EF50300A83B62 /* FullscreenAdSampleViewController.swift in Sources */, 1437CFB92538A405003DB489 /* UIViewController+Storyboard.swift in Sources */, 145A31F9253EF50300A83B62 /* NativeAdView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 82B89F4D23F7F95900DF6E14 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 82B89F4E23F7F95900DF6E14 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 82B89F5223F7F95B00DF6E14 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 82B89F5323F7F95B00DF6E14 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 82B89F5623F7F95B00DF6E14 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.2; MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; 82B89F5723F7F95B00DF6E14 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_WEAK = YES; CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_DOCUMENTATION_COMMENTS = YES; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; IPHONEOS_DEPLOYMENT_TARGET = 13.2; MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; SWIFT_COMPILATION_MODE = wholemodule; SWIFT_OPTIMIZATION_LEVEL = "-O"; VALIDATE_PRODUCT = YES; }; name = Release; }; 82B89F5923F7F95B00DF6E14 /* Debug */ = { isa = XCBuildConfiguration; baseConfigurationReference = 4F0CF2FBCD28B527F12C5658 /* Pods-FANSample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = V9WTTPBFK9; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; INFOPLIST_FILE = FANSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = com.facebook.audiencenetwork.FANSample; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "Facebook Generic"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 82B89F5A23F7F95B00DF6E14 /* Release */ = { isa = XCBuildConfiguration; baseConfigurationReference = 7344E3D24EBE09AC50121E89 /* Pods-FANSample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; DEVELOPMENT_TEAM = V9WTTPBFK9; GCC_WARN_ABOUT_DEPRECATED_FUNCTIONS = NO; INFOPLIST_FILE = FANSample/Info.plist; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", ); PRODUCT_BUNDLE_IDENTIFIER = com.facebook.audiencenetwork.FANSample; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = "Facebook Generic"; SWIFT_VERSION = 5.0; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 82B89F3D23F7F95900DF6E14 /* Build configuration list for PBXProject "FANSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 82B89F5623F7F95B00DF6E14 /* Debug */, 82B89F5723F7F95B00DF6E14 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 82B89F5823F7F95B00DF6E14 /* Build configuration list for PBXNativeTarget "FANSample" */ = { isa = XCConfigurationList; buildConfigurations = ( 82B89F5923F7F95B00DF6E14 /* Debug */, 82B89F5A23F7F95B00DF6E14 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 82B89F3A23F7F95900DF6E14 /* Project object */; } ================================================ FILE: samples/ios/FANSample/FANSample.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: samples/ios/FANSample/FANSample.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: samples/ios/FANSample/FANSample.xcodeproj/xcshareddata/xcschemes/FANSample.xcscheme ================================================ ================================================ FILE: samples/ios/FANSample/FANSample.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: samples/ios/FANSample/FANSample.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist ================================================ IDEDidComputeMac32BitWarning ================================================ FILE: samples/ios/FANSample/Podfile ================================================ # Uncomment the next line to define a global platform for your project platform :ios, '9.0' use_frameworks! target 'FANSample' do pod 'FBAudienceNetwork' end ================================================ FILE: samples/ios/FANSample/README.md ================================================ # FANSample This Swift sample project demonstrates how to use various ad units supported by our Facebook Ads SDK. Native ads will give you the flexibility to render the ad in a more native format that blends into your app. We also show how to wire up the delegate to get notified when the ad status changes over time or when the user interacts with the ad. ### Brief usage example `FBNativeAd` can be used to show a native ad with a few simple steps: ```Swift // Instantiate an ad with placement ID let ad = FBNativeAd(placementID: "YOUR_PLACEMENT_ID") // Wire up the FBNativeAdDelegate delegate (See documentation for more information). // It is a good practice to set the delegate of the ad and implement the callback methods. ad.delegate = self // Load the ad ad.loadAd() ``` More information regarding API usage can be found in the sample project. ### Samples shown in this project - Interstitial ad (a full screen ad) - Rewarded video ad (a full screen ad that shows a video). - Native banner ad composed of native views. - Native ad from template (layout that can be shown in various sizes) - Native banner ad from template (layout that can be shown in various sizes). ### How to setup the project 1. Make sure [CocoaPods](https://cocoapods.org/) is installed on your machine. 2. Go to the project directory and run `pod install`. 3. A workspace file named `FANSample.xcworkspace` will be generated. Open it using Xcode. 4. You can find the samples under `FANSamples/Samples`. Replace "YOUR_PLACEMENT_ID" with the Placement ID you created through [developer.facebook.com](https://developers.facebook.com/). 5. Run the project either on a simulator or a device. ### Test ads When running the project on a simulator, test ads are served by default. However, on a device real ads will be served unless you specify otherwise. If you test your app on a device, please make sure to call the following API to enable test ads: `FBAdSettings.addTestDevice("")` ### Additional resources - [Audience Network Docs](https://developers.facebook.com/docs/audience-network) - [Getting Started](https://developers.facebook.com/docs/audience-network/get-started/ios) - [SDK Reference Documentation](https://developers.facebook.com/docs/audience-network/reference/) ================================================ FILE: samples/ios/README.md ================================================ Samples for iOS =============== Facebook Audience Network allows you to monetize your iOS apps with Facebook ads. Here we have a list of sample apps that implements different ad placements for your reference. Please make sure that you have completed the [Audience Network Getting Started][1] and [iOS Getting Started][2] guides before you proceed. The sample projects are setup with [Cocoa Pods][7]. You would need to run `pod install` in the project folder from command line to download the latest Audience Network SDK. Sample list ----------- These sample projects include demonstration for different placement formats including [Banner][3], [Interstitial][4], [Rewarded Video][9], [In-stream Video][8] [Native][5] and [Native Banner Ads][10]. - [AdUnitsSample](./AdUnitsSample) - An Objective C sample project. - [FANSample](./FANSample) - A Swift sample project. [1]: https://developers.facebook.com/docs/audience-network/getting-started [2]: https://developers.facebook.com/docs/audience-network/ios [3]: https://developers.facebook.com/docs/audience-network/ios-banners [4]: https://developers.facebook.com/docs/audience-network/ios-interstitial [5]: https://developers.facebook.com/docs/audience-network/ios-native [8]: https://developers.facebook.com/docs/audience-network/ios/instream-video [9]: https://developers.facebook.com/docs/audience-network/ios/rewarded-video [10]: https://developers.facebook.com/docs/audience-network/ios-native-banner ================================================ FILE: samples/python/ReportingAPISamples/.gitignore ================================================ # Created by .ignore support plugin (hsz.mobi) ### Python template # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] *$py.class # C extensions *.so # Distribution / packaging .Python env/ build/ develop-eggs/ dist/ downloads/ eggs/ .eggs/ lib/ lib64/ parts/ sdist/ var/ *.egg-info/ .installed.cfg *.egg # PyInstaller # Usually these files are written by a python script from a template # before PyInstaller builds the exe, so as to inject date/other infos into it. *.manifest *.spec # Installer logs pip-log.txt pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ .coverage .coverage.* .cache nosetests.xml coverage.xml *,cover .hypothesis/ # Translations *.mo *.pot # Django stuff: *.log local_settings.py # Flask stuff: instance/ .webassets-cache # Scrapy stuff: .scrapy # Sphinx documentation docs/_build/ # PyBuilder target/ # IPython Notebook .ipynb_checkpoints # pyenv .python-version # celery beat schedule file celerybeat-schedule # dotenv .env # virtualenv venv/ ENV/ # Spyder project settings .spyderproject # Rope project settings .ropeproject ### VirtualEnv template # Virtualenv # http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ .Python [Bb]in [Ii]nclude [Ll]ib [Ll]ib64 [Ll]ocal [Ss]cripts pyvenv.cfg .venv pip-selfcheck.json ### JetBrains template # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff: .idea/workspace.xml .idea/tasks.xml .idea/dictionaries .idea/vcs.xml .idea/jsLibraryMappings.xml # Sensitive or high-churn files: .idea/dataSources.ids .idea/dataSources.xml .idea/dataSources.local.xml .idea/sqlDataSources.xml .idea/dynamic.xml .idea/uiDesigner.xml # Gradle: .idea/gradle.xml .idea/libraries # Mongo Explorer plugin: .idea/mongoSettings.xml .idea/ ## File-based project format: *.iws ## Plugin-specific files: # IntelliJ /out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-build.properties fabric.properties ================================================ FILE: samples/python/ReportingAPISamples/CONTRIBUTING.md ================================================ # Contributing to audience-network-reporting-api-samples We want to make contributing to this project as easy and transparent as possible. ## Our Development Process audience-network-reporting-api-samples is maintained and developed on github. Send us your pull requests, and we'd be happy to provide feedback and merge as appropriate. ## Pull Requests We actively welcome your pull requests. 1. Fork the repo and create your branch from `master`. 2. If you've added code that should be tested, add tests 3. If you've changed APIs, update the documentation. 4. Make sure your code lints (e.g., pyflakes, PEP8, etc) 5. If you haven't already, complete the Contributor License Agreement ("CLA"). ## Contributor License Agreement ("CLA") In order to accept your pull request, we need you to submit a CLA. You only need to do this once to work on any of Facebook's open source projects. Complete your CLA here: ## Issues We use GitHub issues to track public bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue. ## License By contributing to audience-network-reporting-api-samples, you agree that your contributions will be licensed under the LICENSE file in the root directory of this source tree. ================================================ FILE: samples/python/ReportingAPISamples/LICENSE.md ================================================ BSD License For audience-network-reporting-api-samples software Copyright (c) 2017-present, Facebook, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name Facebook nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ================================================ FILE: samples/python/ReportingAPISamples/PATENTS.md ================================================ Additional Grant of Patent Rights Version 2 "Software" means the audience-network-reporting-api-samples software contributed by Facebook, Inc. Facebook, Inc. ("Facebook") hereby grants to each recipient of the Software ("you") a perpetual, worldwide, royalty-free, non-exclusive, irrevocable (subject to the termination provision below) license under any Necessary Claims, to make, have made, use, sell, offer to sell, import, and otherwise transfer the Software. For avoidance of doubt, no license is granted under Facebook’s rights in any patent claims that are infringed by (i) modifications to the Software made by you or any third party or (ii) the Software in combination with any software or other technology. The license granted hereunder will terminate, automatically and without notice, if you (or any of your subsidiaries, corporate affiliates or agents) initiate directly or indirectly, or take a direct financial interest in, any Patent Assertion: (i) against Facebook or any of its subsidiaries or corporate affiliates, (ii) against any party if such Patent Assertion arises in whole or in part from any software, technology, product or service of Facebook or any of its subsidiaries or corporate affiliates, or (iii) against any party relating to the Software. Notwithstanding the foregoing, if Facebook or any of its subsidiaries or corporate affiliates files a lawsuit alleging patent infringement against you in the first instance, and you respond by filing a patent infringement counterclaim in that lawsuit against that party that is unrelated to the Software, the license granted hereunder will not terminate under section (i) of this paragraph due to such counterclaim. A "Necessary Claim" is a claim of a patent owned by Facebook that is necessarily infringed by the Software standing alone. A "Patent Assertion" is any lawsuit or other action alleging direct, indirect, or contributory infringement or inducement to infringe any patent, including a cross-claim or counterclaim. ================================================ FILE: samples/python/ReportingAPISamples/README.md ================================================ # Audience Network Reporting API Samples The Audience Network Reporting API lets you automate downloading performance data for your Business and Properties. This sample project walks through key API features and use cases in Python to send requests (sync or async) to fetch performance data and save them as .csv file. The API now supports sync (GET request) and async (POST request). Sync requests are light and immediately return data. Async requests are designed to handle heavier data loads and return a query ID for you to retrieve the data at a later time. More info below. This repository includes contents as follows: ## Recommendation We highly recommend you include our adnw_examples.py into your project because those examples are the best practices for accessing our end point. After you fetch query ids successfully, please wait for a few seconds (i.e. 10 seconds) before you send another "async" request with query ids such that you are guaranteed to get results. Also, please do not try to request more than 50 times within 60 seconds. ## Run Reporting API Examples In adnw_examples.py, it provides examples using adnw_requests to build sync and async requests to get data. Uncomment corresponding test cases in adnw_examples.py and run it. ## Versions The python version is 3.6.
The [requests library](https://github.com/requests/requests) version is 2.18.4. ================================================ FILE: samples/python/ReportingAPISamples/adnw_examples.py ================================================ from adnw_requests import * from adnw_utils import * from adnw_response import * from time import sleep import datetime """ Run sync request, but there are some limitations. Support only one metric and two max breakdowns per request. """ def run_sync_request(app_id, access_token): builder = ADNWRequestBuilder(app_id, access_token) builder.add_metric(Metric.ADNW_REQUEST) builder.add_filter(Filter(Breakdown.COUNTRY, FilterOperator.IN, ['US', 'JP'])) builder.add_filter(Filter(Breakdown.PLATFORM, FilterOperator.IN, ['ios', 'android', 'unknown'])) builder.add_breakdown(Breakdown.COUNTRY) builder.add_breakdown(Breakdown.PLATFORM) builder.set_date_range(datetime.date(2018, 4, 1), datetime.date(2018, 4, 1)) builder.set_limit(MAX_ROW_LIMIT_SYNC) sync_request = builder.build_sync_request() ADNWResponse.get_instance().validate_response(sync_request) adnw_utils.write_to_csv(sync_request.json()) """ Run async request to get request id (no limitations on params), then run sync request with request id. No max metric and breakdowns per request. """ def run_async_request_1(app_id, access_token): builder = ADNWRequestBuilder(app_id, access_token) builder.add_metric(Metric.ADNW_IMPRESSION) builder.add_metric(Metric.ADNW_REQUEST) builder.add_filter(Filter(Breakdown.COUNTRY, FilterOperator.IN, ['US', 'JP'])) builder.add_filter(Filter(Breakdown.PLATFORM, FilterOperator.IN, ['ios', 'android'])) builder.add_breakdown(Breakdown.COUNTRY) builder.add_breakdown(Breakdown.PLACEMENT) builder.set_date_range(datetime.date(2018, 4, 1), datetime.date(2018, 4, 1)) builder.set_limit(MAX_ROW_LIMIT_ASYNC) async_request = builder.build_async_request() adnw_response = ADNWResponse.get_instance() adnw_response.validate_response(async_request) query_id = adnw_response.get_query_id(async_request.json()) print("Successfully get valid query id: " + query_id) return query_id """ Run multiple async request to get request ids (no limitations on params), then run sync request with multiple request ids. No max metric and breakdowns per request. """ def run_async_request_2(app_id, access_token): builder = ADNWRequestBuilder(app_id, access_token) builder.add_metric(Metric.ADNW_CMP) builder.add_metric(Metric.ADNW_CLICK) builder.add_filter(Filter(Breakdown.COUNTRY, FilterOperator.IN, ['MK', 'SB'])) builder.add_filter(Filter(Breakdown.PLATFORM, FilterOperator.IN, ['ios', 'unknown'])) builder.add_breakdown(Breakdown.PLATFORM) builder.add_breakdown(Breakdown.PLACEMENT) builder.set_limit(MAX_ROW_LIMIT_ASYNC) async_request = builder.build_async_request() adnw_response = ADNWResponse.get_instance() adnw_response.validate_response(async_request) query_id = adnw_response.get_query_id(async_request.json()) print("Successfully get valid query id: " + query_id) return query_id def run_async_request_for_result_1(app_id, access_token): query_id = run_async_request_1(app_id, access_token) """The waiting period here is to make sure the results have been generated on our backend.""" sleep(10) try_run_async_request_with_query_ids(app_id, access_token, [query_id]) def run_async_request_for_result_2(app_id, access_token): query_id_1 = run_async_request_1(app_id, access_token) query_id_2 = run_async_request_2(app_id, access_token) """The waiting period here is to make sure the results have been generated on our backend.""" sleep(10) try_run_async_request_with_query_ids(app_id, access_token, [query_id_1, query_id_2]) def try_run_async_request_with_query_ids(app_id, access_token, query_ids: [string]): for i in range(0, 3): try: run_async_request_with_query_ids(app_id, access_token, query_ids) break except adnw_exception.ValidationError as error: print(error.message) """Waiting 60 seconds if first async request fails, because clustering too many requests in our backend will slow your process of fetching results.""" sleep(60) continue def run_async_request_with_query_ids(app_id, access_token, query_ids: [string]): builder = ADNWRequestBuilder(app_id, access_token) builder.set_query_ids(query_ids) sync_request = builder.build_sync_request_with_query_ids() ADNWResponse.get_instance().validate_response(sync_request) adnw_utils.write_to_csv(sync_request.json()) if __name__ == '__main__': """Replace with your app_id and valid access_token to start your testing.""" _app_id = "YOUR_APP_ID" _access_token = "USER_ACCESS_TOKEN" """Uncomment corresponding function for testing.""" # run_sync_request(_app_id, _access_token) run_async_request_for_result_1(_app_id, _access_token) # run_async_request_for_result_2(_app_id, _access_token) ================================================ FILE: samples/python/ReportingAPISamples/adnw_exception.py ================================================ class ValidationError(Exception): def __init__(self, message, errors=None): super().__init__(message) self.errors = errors self.message = message class HttpResponseError(Exception): def __init__(self, message, errors=None): super().__init__(message) self.errors = errors self.message = message class InvalidQueryIdError(Exception): def __init__(self, message, errors=None): super().__init__(message) self.errors = errors self.message = message ================================================ FILE: samples/python/ReportingAPISamples/adnw_params.py ================================================ import enum import string # Params Key METRICS = 'metrics' BREAKDOWNS = 'breakdowns' FILTERS = 'filters' VALUES = 'values' ORDERING_COLUMN = 'ordering_column' ORDERING_TYPE = 'ordering_type' LIMIT = 'limit' AGGREGATION_PERIOD = 'aggregation_period' Date_SINCE = 'since' Date_UNTIL = 'until' # Required Parameters for Sync Request without query ids class Metric(enum.Enum): ADNW_REVENUE = 'fb_ad_network_revenue' ADNW_REQUEST = 'fb_ad_network_request' ADNW_CMP = 'fb_ad_network_cpm' ADNW_CLICK = 'fb_ad_network_click' ADNW_IMPRESSION = 'fb_ad_network_imp' ADNW_FILLED_REQUEST = 'fb_ad_network_filled_request' ADNW_FILL_RATE = 'fb_ad_network_fill_rate' ADNW_CTR = 'fb_ad_network_ctr' ADNW_SHOW_RATE = 'fb_ad_network_show_rate' ADNW_VIDEO_GUARANTEE_REVENUE = 'fb_ad_network_video_guarantee_revenue' ADNW_VIDEO_VIEW = 'fb_ad_network_video_view' ADNW_VIDEO_VIEW_RATE = 'fb_ad_network_video_view_rate' ADNW_VIDEO_MRC = 'fb_ad_network_video_mrc' ADNW_VIDEO_MRC_RATE = 'fb_ad_network_video_mrc_rate' ADNW_BIDDING_REQUEST = 'fb_ad_network_bidding_request' ADNW_BIDDING_RESPONSE = 'fb_ad_network_bidding_response' # Optional Parameters class Breakdown(enum.Enum): COUNTRY = 'country' DELIVERY_METHOD = 'delivery_method' PLATFORM = 'platform' APP = 'app' PROPERTY = 'property' PLACEMENT = 'placement' DEAL = 'deal' class FilterOperator(enum.Enum): IN = 'in' class Filter: def __init__(self, condition: Breakdown, operator: FilterOperator, filters: [string]): self.condition = condition self.operator = operator self.filters = filters def raw_value(self): return {'field': self.condition.value, 'operator': self.operator.value, 'values': self.filters} def __hash__(self): return self.condition.__hash__() def __eq__(self, other): return self.condition == other.condition class OrderingColumn(enum.Enum): TIME = 'time' VALUE = 'value' class OrderingType(enum.Enum): ASCENDING = 'ascending' DESCENDING = 'descending' class AggregationPeriod(enum.Enum): DAY = 'day' TOTAL = 'total' ================================================ FILE: samples/python/ReportingAPISamples/adnw_requests.py ================================================ import datetime import requests import json import adnw_utils from adnw_params import * # Base URL BASE_URL = 'https://graph.facebook.com' API_VERSION = 'v10.0' ADNW_REQUEST_API = '/adnetworkanalytics' ADNW_REQUEST_API_BY_QUERY_IDS = '/adnetworkanalytics_results' ACCESS_TOKEN_KEY = 'access_token' QUERY_IDS = 'query_ids' MAX_ROW_LIMIT_ASYNC = 10000 MAX_ROW_LIMIT_SYNC = 1000 now = datetime.datetime.now() date_format = "%Y-%m-%d" class ADNWRequestBuilder(object): def __init__(self, app_id: string, access_token: string): self.url = BASE_URL + '/' + API_VERSION + '/' + app_id self.access_token = access_token self.metrics = set() self.breakdowns = set() self.date_since = now.date() + datetime.timedelta(days=-6) self.date_until = now.date() self.filters = set() self.ordering_column = OrderingColumn.TIME self.ordering_type = OrderingType.ASCENDING self.limit = MAX_ROW_LIMIT_SYNC self.aggregation_period = AggregationPeriod.DAY self.query_ids = set() def add_metrics(self, metrics: [Metric]): self.metrics.add(metrics) def add_metric(self, metric: Metric): self.metrics.add(metric) def add_breakdowns(self, breakdowns: [Breakdown]): self.breakdowns.add(breakdowns) def add_breakdown(self, breakdown: Breakdown): self.breakdowns.add(breakdown) def set_date_range(self, date_since: datetime.date, date_until: datetime.date): self.date_since = date_since self.date_until = date_until def add_filters(self, filters: [Filter]): self.filters.add(filters) def add_filter(self, _filter: Filter): self.filters.add(_filter) def set_ordering_type(self, ordering_type: OrderingType): self.ordering_type = ordering_type def set_ordering_column(self, ordering_column: OrderingColumn): self.ordering_column = ordering_column def set_aggregation_period(self, aggregation_period: AggregationPeriod): self.aggregation_period = aggregation_period def set_limit(self, limit: int): self.limit = limit def set_query_ids(self, query_ids: [string]): self.query_ids = query_ids """ Build sync request with provided params.""" def build_sync_request(self): sync_url = self.url + ADNW_REQUEST_API + '/' self.validate_params() return requests.get(sync_url, self.get_params()) """ Build sync request with query ids and access token. Any other param will be ignored. """ def build_sync_request_with_query_ids(self): sync_url = self.url + ADNW_REQUEST_API_BY_QUERY_IDS + '/' print("You are using query ids to get results." " The fields except for query ids and access token will be ignored.") self.validate_params(is_using_query_ids=True) params = { ACCESS_TOKEN_KEY: self.access_token, QUERY_IDS: json.dumps(self.query_ids) } return requests.get(sync_url, params) """ Build async request to fetch query id.""" def build_async_request(self): async_url = self.url + ADNW_REQUEST_API + '/' self.validate_params(is_sync_request=False) return requests.post(async_url, json=self.get_params()) def get_params(self): metrics_list = list(map(adnw_utils.raw_value, self.metrics)) breakdowns_list = list(map(adnw_utils.raw_value, self.breakdowns)) filters_list = list(map(adnw_utils.raw_statement, self.filters)) return { ACCESS_TOKEN_KEY: self.access_token, METRICS: json.dumps(metrics_list), BREAKDOWNS: json.dumps(breakdowns_list), Date_SINCE: self.date_since.strftime(date_format), Date_UNTIL: self.date_until.strftime(date_format), FILTERS: json.dumps(filters_list), ORDERING_COLUMN: self.ordering_column.value, ORDERING_TYPE: self.ordering_type.value, LIMIT: self.limit, AGGREGATION_PERIOD: self.aggregation_period.value } def validate_params(self, is_sync_request: bool = True, is_using_query_ids: bool = False): if not is_using_query_ids and len(self.metrics) == 0: raise Exception("The parameter metrics is required.") diff = (self.date_until - self.date_since).days if diff >= 7 or diff < 0: print("date since: " + str(self.date_since)) print("date since: " + str(self.date_until)) if diff >= 7: raise Exception("The time range needs to be at most 7 days.") if diff < 0: raise Exception("The time range is invalid.") if is_sync_request: if len(self.metrics) > 1: raise Exception("The parameter metrics cannot be more than 1 with Sync Request.") if len(self.breakdowns) > 2: raise Exception("The parameter breakdowns cannot be more than 2 with Sync Request.") if self.limit > 1000: raise Exception("The parameter limit cannot be more than 1000 with Sync Request.") else: if self.limit > 10000: raise Exception("The parameter limit cannot be more than 10000 with Async Request.") if is_using_query_ids: if len(self.query_ids) <= 0: raise Exception("The query ids are not valid in the request.") ================================================ FILE: samples/python/ReportingAPISamples/adnw_response.py ================================================ import json import requests import adnw_utils import adnw_exception class ADNWResponse(object): __instance = None @staticmethod def get_instance(): if ADNWResponse.__instance is None: ADNWResponse() return ADNWResponse.__instance def __init__(self): if ADNWResponse.__instance: raise Exception("ADNWResponse class is a singleton!") else: ADNWResponse.__instance = self """ Check error message if status_code is not 200. Validate response (make sure the status in Json is "complete") from sync request with query ids if status_code is 200. """ def validate_response(self, _request: requests.request): _json = _request.json() if _request.status_code != 200: _error = _json["error"] _message = _error["message"] raise adnw_exception.HttpResponseError(_message) else: try: _data = _json["data"] if adnw_utils.is_list_empty(_data): raise adnw_exception.InvalidQueryIdError("query id is invalid.") else: for each in _data: if each["status"] != "complete": raise adnw_exception.ValidationError("Report is not ready in Backend, please retry later.") except KeyError: return def get_query_id(self, _json: json): try: query_id = _json["query_id"] except KeyError: raise adnw_exception.InvalidQueryIdError("Unable to get valid query id.") return query_id ================================================ FILE: samples/python/ReportingAPISamples/adnw_utils.py ================================================ from adnw_params import * import datetime import json import csv import shutil import os.path flat_item = {} REPORTS_DIR = 'csv_reports' def raw_value(enum_val: enum.Enum): return enum_val.value def raw_statement(_filter: Filter): return _filter.raw_value() def validate(date_text: string): try: datetime.datetime.strptime(date_text, '%Y-%m-%d') except ValueError: raise ValueError("Invalid data format, should be YYYY-MM-DD") """ Flatten nested Json object.""" def flatten_item(value, key=None): global flat_item if type(value) is list: for item in value: flatten_item(item) elif type(value) is dict: (sub_key, sub_value) = add_separated_key_value_if_needed(value) if not (sub_key or sub_value): for (sub_key, sub_value) in value.items(): flatten_item(sub_value, sub_key) else: flat_item[sub_key] = sub_value elif type(key) is str: flat_item[key] = value """ Flatten nested Json and save to csv file""" def write_to_csv(_json: json): if os.path.exists(REPORTS_DIR): shutil.rmtree(REPORTS_DIR) if not _json: print("Failed to writing results to csv, json results: \n" + str(_json)) return flat_datas = list() global flat_item data_array = _json["data"] for data in data_array: flat_items = list() for item in data["results"]: flat_item = {} flatten_item(item) flat_items.append(flat_item) flat_datas.append(flat_items) if is_list_empty(flat_datas) or is_list_empty(flat_datas[0]): print("Failed to writing results to csv, json results: \n" + str(_json)) return if not os.path.exists(REPORTS_DIR): os.makedirs(REPORTS_DIR) i = 0 for flat_items in flat_datas: if is_list_empty(flat_items): continue csv_output = csv.DictWriter(open(REPORTS_DIR + "/report_" + str(i) + ".csv", "w+"), flat_items[0].keys(), quoting=csv.QUOTE_ALL) csv_output.writeheader() for flat_item in flat_items: csv_output.writerow(flat_item) i += 1 print("json response: " + str(_json)) print("Finish writing results to csv, check 'csv_reports/report.csv' in root directory.") def add_separated_key_value_if_needed(node: dict): key = None value = None for (sub_key, sub_value) in node.items(): if sub_key == 'key': key = sub_value elif sub_key == 'value': value = sub_value else: break return key, value def is_list_empty(_list: list): return _list is None or len(_list) == 0