├── .gitignore
├── .gitmodules
├── .travis.yml
├── LICENSE
├── README.md
├── banner
├── .gitignore
├── README.md
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── flurry
│ │ └── sample
│ │ └── banner
│ │ ├── BannerSampleApplication.java
│ │ └── MainActivity.java
│ └── res
│ ├── layout
│ └── activity_main.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── interstitial
├── .gitignore
├── README.md
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── flurry
│ │ └── sample
│ │ └── interstitial
│ │ ├── InterstitialOnExitActivity.java
│ │ ├── InterstitialSampleApplication.java
│ │ └── MainActivity.java
│ └── res
│ ├── layout
│ ├── activity_interstitial_on_exit.xml
│ └── activity_main.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── mopub
├── .gitignore
├── README.md
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ ├── flurry
│ │ └── sample
│ │ │ └── mopub
│ │ │ ├── MainActivity.java
│ │ │ ├── MopubNativeActivity.java
│ │ │ └── MopubSampleApplication.java
│ │ └── mopub
│ │ ├── mobileads
│ │ ├── FlurryAgentWrapper.java
│ │ ├── FlurryCustomEventBanner.java
│ │ └── FlurryCustomEventInterstitial.java
│ │ └── nativeads
│ │ ├── FlurryCustomEventNative.java
│ │ └── FlurryStaticNativeAd.java
│ └── res
│ ├── layout
│ ├── activity_banner_ads.xml
│ ├── activity_main.xml
│ ├── activity_native_ads.xml
│ └── list_item_native_ads.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
├── native
├── .gitignore
├── README.md
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── flurry
│ │ └── sample
│ │ └── gemini
│ │ ├── BaseAdFragment.java
│ │ ├── MainActivity.java
│ │ ├── NativeAdChooserFragment.java
│ │ ├── SingleAdFragment.java
│ │ ├── StreamApplication.java
│ │ ├── StreamListViewFragment.java
│ │ └── entities
│ │ └── NewsArticle.java
│ └── res
│ ├── drawable
│ └── scrim_gradient_bottom_dark.xml
│ ├── layout
│ ├── activity_single_pane.xml
│ ├── fragment_main_stream.xml
│ ├── fragment_single_ad.xml
│ ├── list_item_ad.xml
│ └── list_item_article.xml
│ ├── menu
│ └── menu_main.xml
│ ├── mipmap-xxhdpi
│ └── ic_launcher.png
│ ├── values-w820dp
│ └── dimens.xml
│ └── values
│ ├── arrays.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── strings.xml
│ └── styles.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | # Built application files
2 | *.apk
3 | *.ap_
4 |
5 | *.iml
6 | .idea/
7 |
8 | # Files for the Dalvik VM
9 | *.dex
10 |
11 | # Java class files
12 | *.class
13 |
14 | # Generated files
15 | bin/
16 | gen/
17 |
18 | # Gradle files
19 | .gradle/
20 | build/
21 |
22 | # Local configuration file (sdk path, etc)
23 | local.properties
24 |
25 | # Proguard folder generated by Eclipse
26 | proguard/
27 |
28 | .DS_Store
29 |
--------------------------------------------------------------------------------
/.gitmodules:
--------------------------------------------------------------------------------
1 | [submodule "StreamAds-Android"]
2 | path = StreamAds-Android
3 | url = git@github.com:flurry/StreamAds-Android.git
4 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | # Copyright 2015 Yahoo Inc.
2 |
3 | # This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
4 |
5 | # Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
6 |
7 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
8 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
9 | # 3. This notice may not be removed or altered from any source distribution.
10 |
11 | git:
12 | submodules: false
13 |
14 | before_install:
15 | - sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
16 | - git submodule update --init --recursive
17 |
18 | language: android
19 |
20 | android:
21 | components:
22 | - tools
23 | - platform-tools
24 | - build-tools-23.0.2
25 | - android-23
26 | - extra-android-m2repository
27 | - extra-google-m2repository
28 |
29 | script: ./gradlew build
30 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright 2015 Yahoo Inc.
2 |
3 | This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
4 |
5 | Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
6 |
7 | 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
8 | 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
9 | 3. This notice may not be removed or altered from any source distribution.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/flurry/android-AdIntegrationSamples)
2 |
3 | Android Ad Integration Sample
4 | ============================
5 |
6 | Detailed integration instructions are available on [Flurry Getting Started](https://developer.yahoo.com/flurry/docs/analytics/gettingstarted/android/)
7 | and [Flurry Android Publisher](https://developer.yahoo.com/flurry/docs/publisher/code/android/) pages.
8 |
9 | This sample shows a number of modules that integrate various ad types from Flurry. All you need to get started is to put in your ad space and API key where necessary.
10 |
11 | When cloning this repo please use the following:
12 | git clone --recursive git@github.com:flurry/android-AdIntegrationSamples.git
13 |
14 | For further help and information, please check out the [Flurry Documentations](https://developer.yahoo.com/flurry) or contact [Flurry Support](mailto:support@flurry.com).
15 |
16 | ## Copyright
17 |
18 | Copyright 2015 Yahoo Inc.
19 | Licensed under the terms of the zLib license. Please see LICENSE file for terms.
20 |
--------------------------------------------------------------------------------
/banner/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/banner/README.md:
--------------------------------------------------------------------------------
1 | Flurry Banner Ad Integration
2 | =========================
3 |
4 | This module shows how to integrate a standard banner into your apps using Flurry.
5 |
6 | To run this sample, put in your API key into `BannerSampleApplication` and your banner ad space name
7 | into `MainActivity`.
--------------------------------------------------------------------------------
/banner/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.flurry.sample.banner"
9 | minSdkVersion 10
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile 'com.google.android.gms:play-services-basement:8.4.0'
24 | compile 'com.android.support:appcompat-v7:23.1.1'
25 | compile 'com.android.support:support-v4:23.1.1'
26 | compile 'com.flurry.android:ads:6.2.0'
27 | }
28 |
--------------------------------------------------------------------------------
/banner/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add any project specific keep options here:
2 |
3 | # If your project uses WebView with JS, uncomment the following
4 | # and specify the fully qualified class name to the JavaScript interface
5 | # class:
6 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
7 | # public *;
8 | #}
9 |
--------------------------------------------------------------------------------
/banner/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
20 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/banner/src/main/java/com/flurry/sample/banner/BannerSampleApplication.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.banner;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.flurry.android.FlurryAgent;
7 |
8 | public class BannerSampleApplication extends Application {
9 | private final static String TAG = BannerSampleApplication.class.getSimpleName();
10 |
11 | @Override
12 | public void onCreate() {
13 | super.onCreate();
14 | FlurryAgent.setLogEnabled(false);
15 | FlurryAgent.setLogLevel(Log.VERBOSE);
16 | FlurryAgent.setLogEvents(true);
17 | FlurryAgent.init(this, "JQVT87W7TGN5W7SWY2FH");
18 | Log.i(TAG, "Flurry SDK initialized");
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/banner/src/main/java/com/flurry/sample/banner/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.banner;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.util.Log;
6 | import android.view.Menu;
7 | import android.view.MenuItem;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import com.flurry.android.ads.FlurryAdBanner;
12 | import com.flurry.android.ads.FlurryAdBannerListener;
13 | import com.flurry.android.ads.FlurryAdErrorType;
14 |
15 | public class MainActivity extends AppCompatActivity {
16 |
17 | public static final String STATE_PERSIST_STANDARD = "com.flurry.sample.banner.persiststandard";
18 | private FlurryAdBanner mFlurryAdStandardBanner = null;
19 | private final static String TAG = MainActivity.class.getSimpleName();
20 | private boolean mShouldRestoreStandardBanner;
21 |
22 | @Override
23 | protected void onCreate(Bundle savedInstanceState) {
24 | super.onCreate(savedInstanceState);
25 | setContentView(R.layout.activity_main);
26 |
27 | if (savedInstanceState != null) {
28 | mShouldRestoreStandardBanner = savedInstanceState
29 | .getBoolean(STATE_PERSIST_STANDARD, false);
30 |
31 | if (mShouldRestoreStandardBanner) {
32 | loadStandardBanner();
33 | }
34 | }
35 |
36 | findViewById(R.id.standard_ad_btn).setOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | mShouldRestoreStandardBanner = true;
40 |
41 | if (mFlurryAdStandardBanner != null) {
42 | mFlurryAdStandardBanner.destroy();
43 | ((ViewGroup) findViewById(R.id.banner_layout)).removeAllViews();
44 | }
45 | loadStandardBanner();
46 | }
47 | });
48 | }
49 |
50 | @Override
51 | public void onSaveInstanceState(Bundle outState) {
52 | outState.putBoolean(STATE_PERSIST_STANDARD, mShouldRestoreStandardBanner);
53 | super.onSaveInstanceState(outState);
54 | }
55 |
56 | @Override
57 | protected void onStop() {
58 | if (mFlurryAdStandardBanner != null) {
59 | mFlurryAdStandardBanner.destroy();
60 | }
61 |
62 | super.onStop();
63 | }
64 |
65 | @Override
66 | public boolean onCreateOptionsMenu(Menu menu) {
67 | // Inflate the menu; this adds items to the action bar if it is present.
68 | getMenuInflater().inflate(R.menu.menu_main, menu);
69 | return true;
70 | }
71 |
72 | @Override
73 | public boolean onOptionsItemSelected(MenuItem item) {
74 | // Handle action bar item clicks here. The action bar will
75 | // automatically handle clicks on the Home/Up button, so long
76 | // as you specify a parent activity in AndroidManifest.xml.
77 | int id = item.getItemId();
78 |
79 | //noinspection SimplifiableIfStatement
80 | if (id == R.id.action_settings) {
81 | return true;
82 | }
83 |
84 | return super.onOptionsItemSelected(item);
85 | }
86 |
87 | private void loadStandardBanner() {
88 | ViewGroup bannerAdLayout = (ViewGroup) findViewById(R.id.banner_layout);
89 | mFlurryAdStandardBanner = new FlurryAdBanner(MainActivity.this, bannerAdLayout,
90 | "StandardBannerTestAd");
91 | mFlurryAdStandardBanner.setListener(mAdBannerListener);
92 | Log.i(TAG, "Fetching banner ad");
93 |
94 | mFlurryAdStandardBanner.fetchAd();
95 | }
96 |
97 | FlurryAdBannerListener mAdBannerListener = new FlurryAdBannerListener() {
98 | @Override
99 | public void onFetched(FlurryAdBanner flurryAdBanner) {
100 | Log.i(TAG, "Banner ad fetched");
101 | mFlurryAdStandardBanner.displayAd();
102 | }
103 |
104 | @Override
105 | public void onRendered(FlurryAdBanner flurryAdBanner) {
106 |
107 | }
108 |
109 | @Override
110 | public void onShowFullscreen(FlurryAdBanner flurryAdBanner) {
111 |
112 | }
113 |
114 | @Override
115 | public void onCloseFullscreen(FlurryAdBanner flurryAdBanner) {
116 |
117 | }
118 |
119 | @Override
120 | public void onAppExit(FlurryAdBanner flurryAdBanner) {
121 |
122 | }
123 |
124 | @Override
125 | public void onClicked(FlurryAdBanner flurryAdBanner) {
126 |
127 | }
128 |
129 | @Override
130 | public void onVideoCompleted(FlurryAdBanner flurryAdBanner) {
131 |
132 | }
133 |
134 | @Override
135 | public void onError(FlurryAdBanner flurryAdBanner, FlurryAdErrorType flurryAdErrorType, int i) {
136 | Log.e(TAG, "Banner ad load error - Error type: " + flurryAdErrorType + " Code: " + i);
137 | mFlurryAdStandardBanner.destroy();
138 | }
139 | };
140 | }
141 |
--------------------------------------------------------------------------------
/banner/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
17 |
24 |
25 |
26 |
32 |
33 |
--------------------------------------------------------------------------------
/banner/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/banner/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flurry/android-AdIntegrationSamples/7a374376efea6fd03be73a3094f68961b8b4146f/banner/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/banner/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/banner/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/banner/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Flurry Banner Sample
3 |
4 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce
5 | viverra elit vitae dolor sollicitudin, vehicula aliquam turpis pharetra. In molestie,
6 | sem pharetra tristique fringilla, diam libero placerat orci, eu sodales mauris nunc non
7 | velit. Vestibulum consequat augue magna, quis egestas ante semper sit amet. Fusce mollis
8 | tempus mollis. Ut volutpat et felis et ultrices. Ut in tempor quam, non viverra sapien.
9 | Duis convallis nisi sed mauris aliquam cursus. Donec cursus at mauris semper imperdiet.
10 | Donec rutrum eget lorem id semper. Aliquam feugiat rhoncus suscipit. Aliquam tempor
11 | tristique dolor, consequat venenatis quam facilisis vel.
12 |
13 |
14 | Settings
15 | Load standard banner
16 |
17 |
--------------------------------------------------------------------------------
/banner/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath 'com.android.tools.build:gradle:1.5.0'
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | jcenter()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | # Default value: -Xmx10248m -XX:MaxPermSize=256m
13 | # org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
14 |
15 | # When configured, Gradle will run in incubating parallel mode.
16 | # This option should only be used with decoupled projects. More details, visit
17 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flurry/android-AdIntegrationSamples/7a374376efea6fd03be73a3094f68961b8b4146f/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Apr 10 15:27:10 PDT 2013
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # For Cygwin, ensure paths are in UNIX format before anything is touched.
46 | if $cygwin ; then
47 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
48 | fi
49 |
50 | # Attempt to set APP_HOME
51 | # Resolve links: $0 may be a link
52 | PRG="$0"
53 | # Need this for relative symlinks.
54 | while [ -h "$PRG" ] ; do
55 | ls=`ls -ld "$PRG"`
56 | link=`expr "$ls" : '.*-> \(.*\)$'`
57 | if expr "$link" : '/.*' > /dev/null; then
58 | PRG="$link"
59 | else
60 | PRG=`dirname "$PRG"`"/$link"
61 | fi
62 | done
63 | SAVED="`pwd`"
64 | cd "`dirname \"$PRG\"`/" >&-
65 | APP_HOME="`pwd -P`"
66 | cd "$SAVED" >&-
67 |
68 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin, switch paths to Windows format before running java
114 | if $cygwin ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | # We build the pattern for arguments to be converted via cygpath
119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
120 | SEP=""
121 | for dir in $ROOTDIRSRAW ; do
122 | ROOTDIRS="$ROOTDIRS$SEP$dir"
123 | SEP="|"
124 | done
125 | OURCYGPATTERN="(^($ROOTDIRS))"
126 | # Add a user-defined pattern to the cygpath arguments
127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
129 | fi
130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
131 | i=0
132 | for arg in "$@" ; do
133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
135 |
136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
138 | else
139 | eval `echo args$i`="\"$arg\""
140 | fi
141 | i=$((i+1))
142 | done
143 | case $i in
144 | (0) set -- ;;
145 | (1) set -- "$args0" ;;
146 | (2) set -- "$args0" "$args1" ;;
147 | (3) set -- "$args0" "$args1" "$args2" ;;
148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
154 | esac
155 | fi
156 |
157 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
158 | function splitJvmOpts() {
159 | JVM_OPTS=("$@")
160 | }
161 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
162 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
163 |
164 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
165 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/interstitial/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/interstitial/README.md:
--------------------------------------------------------------------------------
1 | Flurry Interstitial (full-screen) Ad Integration
2 | ===============================================
3 |
4 | This module shows how to integrate various kinds of interstitial ads into your apps using Flurry.
5 |
6 | For this sample, a test API key and various ad space names are already configured. Do not forget
7 | to change the ad space name and API key if copying code from here.
8 |
9 | The various interstitial configurations in this sample are:
10 | - `InterstitialTest`: The bare minimum default for an interstitial ad space configuration
11 | - `SkippableVideoTest`: An ad space that shows skippable videos
12 | - `UnskippableVideoTest`: An ad space that shows unskippable videos
13 | - `ClientSideRewardedAd`: An ad space that is set up to receive client-side rewarded video ads.
--------------------------------------------------------------------------------
/interstitial/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.flurry.sample.interstitial"
9 | minSdkVersion 10
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | debuggable false
19 | }
20 | debug {
21 | debuggable true
22 | }
23 | }
24 | }
25 |
26 | dependencies {
27 | compile 'com.google.android.gms:play-services-basement:8.4.0'
28 | compile 'com.android.support:appcompat-v7:23.1.1'
29 | compile 'com.android.support:support-v4:23.1.1'
30 | compile 'com.flurry.android:ads:6.2.0'
31 | }
32 |
--------------------------------------------------------------------------------
/interstitial/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add any project specific keep options here:
2 |
3 | # If your project uses WebView with JS, uncomment the following
4 | # and specify the fully qualified class name to the JavaScript interface
5 | # class:
6 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
7 | # public *;
8 | #}
9 |
--------------------------------------------------------------------------------
/interstitial/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
30 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/interstitial/src/main/java/com/flurry/sample/interstitial/InterstitialOnExitActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.interstitial;
2 |
3 | import android.os.Bundle;
4 | import android.os.PersistableBundle;
5 | import android.support.v7.app.ActionBarActivity;
6 | import android.util.Log;
7 | import android.view.MenuItem;
8 | import android.widget.Toast;
9 |
10 | import com.flurry.android.ads.FlurryAdErrorType;
11 | import com.flurry.android.ads.FlurryAdInterstitial;
12 | import com.flurry.android.ads.FlurryAdInterstitialListener;
13 |
14 | public class InterstitialOnExitActivity extends ActionBarActivity {
15 |
16 | private final static String TAG = InterstitialOnExitActivity.class.getSimpleName();
17 |
18 | @Override
19 | public void onCreate(Bundle savedInstanceState) {
20 | super.onCreate(savedInstanceState);
21 | setContentView(R.layout.activity_interstitial_on_exit);
22 | }
23 |
24 | @Override
25 | public boolean onOptionsItemSelected(MenuItem item) {
26 | switch (item.getItemId()) {
27 | case android.R.id.home:
28 | showTransitionAd();
29 | return true;
30 | }
31 | return super.onOptionsItemSelected(item);
32 | }
33 |
34 | @Override
35 | public void onBackPressed() {
36 | showTransitionAd();
37 | }
38 |
39 | private void showTransitionAd() {
40 | FlurryAdInterstitial flurryAdInterstitial = new FlurryAdInterstitial(this, "InterstitialTest");
41 | flurryAdInterstitial.setListener(new FlurryAdInterstitialListener() {
42 | @Override
43 | public void onFetched(FlurryAdInterstitial flurryAdInterstitial) {
44 | Log.i(TAG, "Full screen ad fetched");
45 | flurryAdInterstitial.displayAd();
46 | }
47 |
48 | @Override
49 | public void onRendered(FlurryAdInterstitial flurryAdInterstitial) {
50 |
51 | }
52 |
53 | @Override
54 | public void onDisplay(FlurryAdInterstitial flurryAdInterstitial) {
55 |
56 | }
57 |
58 | @Override
59 | public void onClose(FlurryAdInterstitial flurryAdInterstitial) {
60 | InterstitialOnExitActivity.this.finish();
61 | }
62 |
63 | @Override
64 | public void onAppExit(FlurryAdInterstitial flurryAdInterstitial) {
65 |
66 | }
67 |
68 | @Override
69 | public void onClicked(FlurryAdInterstitial flurryAdInterstitial) {
70 |
71 | }
72 |
73 | @Override
74 | public void onVideoCompleted(FlurryAdInterstitial flurryAdInterstitial) {
75 |
76 | }
77 |
78 | @Override
79 | public void onError(FlurryAdInterstitial flurryAdInterstitial,
80 | FlurryAdErrorType flurryAdErrorType, int i) {
81 | Log.e(TAG, "Full screen ad load error - Error type: " + flurryAdErrorType + " Code: " + i);
82 | Toast.makeText(InterstitialOnExitActivity.this, "Ad load failed", Toast.LENGTH_SHORT).show();
83 | InterstitialOnExitActivity.this.finish();
84 | }
85 | });
86 | flurryAdInterstitial.fetchAd();
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/interstitial/src/main/java/com/flurry/sample/interstitial/InterstitialSampleApplication.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.interstitial;
2 |
3 | import android.app.Application;
4 | import android.util.Log;
5 |
6 | import com.flurry.android.FlurryAgent;
7 |
8 | public class InterstitialSampleApplication extends Application {
9 |
10 | private final static String TAG = InterstitialSampleApplication.class.getSimpleName();
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 | FlurryAgent.setLogEnabled(true);
16 | FlurryAgent.setLogLevel(Log.VERBOSE);
17 | FlurryAgent.setLogEvents(true);
18 | // NOTE: Use your own Flurry API key. This is left here to make sample review easier
19 | FlurryAgent.init(this, "JQVT87W7TGN5W7SWY2FH");
20 | Log.i(TAG, "Flurry SDK initialized");
21 | }
22 | }
--------------------------------------------------------------------------------
/interstitial/src/main/java/com/flurry/sample/interstitial/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.interstitial;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.util.Log;
7 | import android.view.Menu;
8 | import android.view.MenuItem;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.AdapterView;
12 | import android.widget.ArrayAdapter;
13 | import android.widget.ListView;
14 | import android.widget.TextView;
15 | import android.widget.Toast;
16 |
17 | import com.flurry.android.ads.FlurryAdErrorType;
18 | import com.flurry.android.ads.FlurryAdInterstitial;
19 | import com.flurry.android.ads.FlurryAdInterstitialListener;
20 | import com.flurry.android.ads.FlurryAdTargeting;
21 |
22 | import java.util.Arrays;
23 |
24 | public class MainActivity extends AppCompatActivity {
25 |
26 | FlurryAdInterstitial mFlurryAdInterstitial;
27 | ListView mListView;
28 | private final static String TAG = MainActivity.class.getSimpleName();
29 |
30 | @Override
31 | protected void onCreate(Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | setContentView(R.layout.activity_main);
34 |
35 | final ArrayAdapter adapter = new ArrayAdapter(
36 | this, android.R.layout.simple_list_item_2, android.R.id.text1,
37 | // NOTE: Use your own Flurry ad space names. This is left here to make sample review easier
38 | Arrays.asList(new SimpleAdSpaceConfig[]{
39 | new SimpleAdSpaceConfig("Basic interstitial ad", "InterstitialTest"),
40 | new SimpleAdSpaceConfig("Skippable video ad", "SkippableVideoTest"),
41 | new SimpleAdSpaceConfig("Unskippable video ad", "UnskippableVideoTest"),
42 | new SimpleAdSpaceConfig("Client-side rewarded ad", "ClientSideRewardedAd"),
43 | new SimpleAdSpaceConfig("Test-mode video ad", "TestModeVideoTest"),
44 | new SimpleAdSpaceConfig("Interstitial on Activity finish", "InterstitialTest"),
45 | })
46 | ) {
47 | @Override
48 | public View getView(int position, View convertView, ViewGroup parent) {
49 | View view = super.getView(position, convertView, parent);
50 | TextView text1 = (TextView) view.findViewById(android.R.id.text1);
51 | TextView text2 = (TextView) view.findViewById(android.R.id.text2);
52 |
53 | text1.setText(getItem(position).mAdSpaceDescription);
54 | text2.setText((getItem(position)).mAdSpaceName);
55 |
56 | return view;
57 | }
58 | };
59 |
60 | mListView = (ListView)findViewById(R.id.list_view);
61 | mListView.setAdapter(adapter);
62 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
63 | @Override
64 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
65 | if (position == 5) {
66 | Intent intent = new Intent(MainActivity.this, InterstitialOnExitActivity.class);
67 | startActivity(intent);
68 | } else {
69 | Log.i(TAG, "Loading full screen ad");
70 | String clickedAdSpaceName = adapter.getItem(position).mAdSpaceName;
71 | mFlurryAdInterstitial = new FlurryAdInterstitial(MainActivity.this, clickedAdSpaceName);
72 | mFlurryAdInterstitial.setListener(mAdInterstitialListener);
73 |
74 | if (position == 4) { // Enable test-mode for consistent ad fill.
75 | FlurryAdTargeting testTarget = new FlurryAdTargeting();
76 | testTarget.setEnableTestAds(true);
77 | mFlurryAdInterstitial.setTargeting(testTarget);
78 | }
79 |
80 | mFlurryAdInterstitial.fetchAd();
81 |
82 | mListView.setEnabled(false);
83 |
84 | Toast.makeText(MainActivity.this, "Please wait for ad", Toast.LENGTH_LONG).show();
85 | }
86 | }
87 | });
88 | }
89 |
90 | @Override
91 | protected void onStop() {
92 | super.onStop();
93 | }
94 |
95 | @Override
96 | protected void onDestroy() {
97 | if (mFlurryAdInterstitial != null) {
98 | mFlurryAdInterstitial.destroy();
99 | }
100 |
101 | super.onDestroy();
102 | }
103 |
104 | @Override
105 | public boolean onCreateOptionsMenu(Menu menu) {
106 | // Inflate the menu; this adds items to the action bar if it is present.
107 | getMenuInflater().inflate(R.menu.menu_main, menu);
108 | return true;
109 | }
110 |
111 | @Override
112 | public boolean onOptionsItemSelected(MenuItem item) {
113 | // Handle action bar item clicks here. The action bar will
114 | // automatically handle clicks on the Home/Up button, so long
115 | // as you specify a parent activity in AndroidManifest.xml.
116 | int id = item.getItemId();
117 |
118 | //noinspection SimplifiableIfStatement
119 | if (id == R.id.action_settings) {
120 | return true;
121 | }
122 |
123 | return super.onOptionsItemSelected(item);
124 | }
125 |
126 | FlurryAdInterstitialListener mAdInterstitialListener = new FlurryAdInterstitialListener() {
127 | @Override
128 | public void onFetched(FlurryAdInterstitial flurryAdInterstitial) {
129 | Log.i(TAG, "Full screen ad fetched");
130 | mListView.setEnabled(true);
131 | flurryAdInterstitial.displayAd();
132 | }
133 |
134 | @Override
135 | public void onRendered(FlurryAdInterstitial flurryAdInterstitial) {
136 | Log.i(TAG, "Ad rendered");
137 | }
138 |
139 | @Override
140 | public void onDisplay(FlurryAdInterstitial flurryAdInterstitial) {
141 | Log.i(TAG, "Ad displayed");
142 | }
143 |
144 | @Override
145 | public void onClose(FlurryAdInterstitial flurryAdInterstitial) {
146 | Log.i(TAG, "Ad closed");
147 | }
148 |
149 | @Override
150 | public void onAppExit(FlurryAdInterstitial flurryAdInterstitial) {
151 | Log.i(TAG, "App closing");
152 | }
153 |
154 | @Override
155 | public void onClicked(FlurryAdInterstitial flurryAdInterstitial) {
156 | Log.i(TAG, "Ad clicked");
157 | }
158 |
159 | @Override
160 | public void onVideoCompleted(FlurryAdInterstitial flurryAdInterstitial) {
161 | Log.i(TAG, "Video is completed");
162 | Toast.makeText(MainActivity.this, "Video completed, where's my reward",
163 | Toast.LENGTH_LONG).show();
164 | }
165 |
166 | @Override
167 | public void onError(FlurryAdInterstitial flurryAdInterstitial, FlurryAdErrorType flurryAdErrorType, int i) {
168 | Log.e(TAG, "Full screen ad load error - Error type: " + flurryAdErrorType + " Code: " + i);
169 | Toast.makeText(MainActivity.this, "Ad load failed - try again", Toast.LENGTH_SHORT).show();
170 | mListView.setEnabled(true);
171 | }
172 | };
173 |
174 | class SimpleAdSpaceConfig {
175 |
176 | SimpleAdSpaceConfig(String adSpaceDescription, String adSpaceName) {
177 | this.mAdSpaceDescription = adSpaceDescription;
178 | this.mAdSpaceName = adSpaceName;
179 | }
180 |
181 | String mAdSpaceDescription;
182 | String mAdSpaceName;
183 | }
184 | }
185 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/layout/activity_interstitial_on_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
16 |
17 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flurry/android-AdIntegrationSamples/7a374376efea6fd03be73a3094f68961b8b4146f/interstitial/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/interstitial/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Flurry Interstitial Sample
3 |
4 | Hello world!
5 | Settings
6 | This should show an interstitial ad after you press the back button
7 |
8 |
--------------------------------------------------------------------------------
/interstitial/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/mopub/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/mopub/README.md:
--------------------------------------------------------------------------------
1 | Flurry mediated by [MoPub](http://www.mopub.com/platform/ad-network-mediation/)
2 | ===========================================
3 |
4 | This module shows how Flurry mediation via MoPub works.
5 |
6 | To run this sample, put in your MoPub ad unit IDs into `MopubNativeActivity` and `MainActivity`.
--------------------------------------------------------------------------------
/mopub/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.flurry.sample.mopub"
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile 'com.android.support:appcompat-v7:23.1.1'
24 | compile 'com.android.support:design:23.1.1'
25 | compile 'com.mopub:mopub-sdk:4.2.0'
26 | compile 'com.flurry.android:ads:6.2.0'
27 | }
28 |
--------------------------------------------------------------------------------
/mopub/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add any project specific keep options here:
2 |
3 | # If your project uses WebView with JS, uncomment the following
4 | # and specify the fully qualified class name to the JavaScript interface
5 | # class:
6 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
7 | # public *;
8 | #}
9 |
--------------------------------------------------------------------------------
/mopub/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
32 |
33 |
34 |
35 |
36 |
37 |
40 |
41 |
42 |
43 |
44 |
--------------------------------------------------------------------------------
/mopub/src/main/java/com/flurry/sample/mopub/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.mopub;
2 |
3 | import android.content.Intent;
4 | import android.os.Bundle;
5 | import android.support.v7.app.AppCompatActivity;
6 | import android.support.design.widget.Snackbar;
7 | import android.util.Log;
8 | import android.view.Menu;
9 | import android.view.MenuItem;
10 | import android.view.View;
11 | import android.widget.AdapterView;
12 | import android.widget.ArrayAdapter;
13 | import android.widget.ListView;
14 | import android.widget.Toast;
15 |
16 | import com.mopub.mobileads.MoPubErrorCode;
17 | import com.mopub.mobileads.MoPubInterstitial;
18 | import com.mopub.mobileads.MoPubView;
19 |
20 | import java.util.Arrays;
21 |
22 | public class MainActivity extends AppCompatActivity
23 | implements MoPubInterstitial.InterstitialAdListener, MoPubView.BannerAdListener {
24 |
25 | public static final String INVALID_MOPUB_INTERSTITIAL_AD_UNIT_ID = "MOPUB_INTERSTITIAL_AD_UNIT_ID";
26 | public static final String INVALID_MOPUB_BANNER_AD_UNIT_ID = "MOPUB_BANNER_AD_UNIT_ID";
27 | // FIXME: Replace the MoPub ad unit IDs below with your app's valid ad units
28 | public static final String MOPUB_INTERSTITIAL_AD_UNIT_ID = INVALID_MOPUB_INTERSTITIAL_AD_UNIT_ID;
29 | public static final String MOPUB_BANNER_AD_UNIT_ID = INVALID_MOPUB_BANNER_AD_UNIT_ID;
30 | private MoPubInterstitial mInterstitial;
31 | private MoPubView mBanner;
32 | private ListView mListView;
33 | private final static String TAG = MainActivity.class.getSimpleName();
34 |
35 | @Override
36 | protected void onCreate(Bundle savedInstanceState) {
37 | super.onCreate(savedInstanceState);
38 | setContentView(R.layout.activity_main);
39 |
40 | final ArrayAdapter adapter = new ArrayAdapter<>(
41 | this, android.R.layout.simple_list_item_1, android.R.id.text1,
42 | Arrays.asList(new String[]{
43 | "Test native ads",
44 | "Test interstitial ads",
45 | "Test banner ads",
46 | })
47 | );
48 |
49 | mListView = (ListView)findViewById(R.id.list_view);
50 | mListView.setAdapter(adapter);
51 | mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
52 | @Override
53 | public void onItemClick(AdapterView> parent, View view, int position, long id) {
54 | switch (position) {
55 | case 0:
56 | Intent intent = new Intent(MainActivity.this, MopubNativeActivity.class);
57 | startActivity(intent);
58 | break;
59 | case 1:
60 | mListView.setEnabled(false);
61 | mInterstitial.load();
62 | Toast.makeText(MainActivity.this, "Loading interstitial ad", Toast.LENGTH_SHORT).show();
63 | break;
64 | case 2:
65 | mBanner.loadAd();
66 | break;
67 | }
68 | }
69 | });
70 |
71 |
72 | if (MOPUB_BANNER_AD_UNIT_ID == INVALID_MOPUB_BANNER_AD_UNIT_ID ||
73 | MOPUB_INTERSTITIAL_AD_UNIT_ID == INVALID_MOPUB_INTERSTITIAL_AD_UNIT_ID) {
74 | View rootView = findViewById(R.id.root_view);
75 | final Snackbar warningSnackBar = Snackbar.make(rootView,
76 | "No MoPub ad unit IDs set. Add your ad unit IDs in code.",
77 | Snackbar.LENGTH_INDEFINITE)
78 | .setAction("DISMISS", new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) { }
81 | });
82 | warningSnackBar.show();
83 | }
84 |
85 | mInterstitial = new MoPubInterstitial(this, MOPUB_INTERSTITIAL_AD_UNIT_ID);
86 | mInterstitial.setInterstitialAdListener(this);
87 | mBanner = (MoPubView)findViewById(R.id.mopub_banner);
88 | mBanner.setAdUnitId(MOPUB_BANNER_AD_UNIT_ID);
89 | mBanner.setBannerAdListener(this);
90 | }
91 |
92 | @Override
93 | protected void onDestroy() {
94 | super.onDestroy();
95 | mInterstitial.destroy();
96 | mBanner.destroy();
97 | }
98 |
99 | @Override
100 | public boolean onCreateOptionsMenu(Menu menu) {
101 | // Inflate the menu; this adds items to the action bar if it is present.
102 | getMenuInflater().inflate(R.menu.menu_main, menu);
103 | return true;
104 | }
105 |
106 | @Override
107 | public boolean onOptionsItemSelected(MenuItem item) {
108 | // Handle action bar item clicks here. The action bar will
109 | // automatically handle clicks on the Home/Up button, so long
110 | // as you specify a parent activity in AndroidManifest.xml.
111 | int id = item.getItemId();
112 |
113 | //noinspection SimplifiableIfStatement
114 | if (id == R.id.action_settings) {
115 | return true;
116 | }
117 |
118 | return super.onOptionsItemSelected(item);
119 | }
120 |
121 | //region MoPubInterstitial.InterstitialAdListener implementation
122 | @Override
123 | public void onInterstitialLoaded(MoPubInterstitial interstitial) {
124 | if (mInterstitial.isReady()) {
125 | Log.w(TAG, "Interstitial ad is loaded");
126 | mInterstitial.show();
127 | } else {
128 | Toast.makeText(this, "Interstitial ad is loaded but not ready", Toast.LENGTH_SHORT).show();
129 | Log.w(TAG, "Interstitial ad is loaded but not ready");
130 | }
131 | mListView.setEnabled(true);
132 | }
133 |
134 | @Override
135 | public void onInterstitialFailed(MoPubInterstitial interstitial, MoPubErrorCode errorCode) {
136 | Toast.makeText(this, "Interstitial ad failed to load. Error code: " + errorCode,
137 | Toast.LENGTH_SHORT).show();
138 | Log.w(TAG, "Interstitial ad failed to load. Error code: " + errorCode);
139 | mListView.setEnabled(true);
140 | }
141 |
142 | @Override
143 | public void onInterstitialShown(MoPubInterstitial interstitial) {
144 | Toast.makeText(this, "Interstitial ad is visible", Toast.LENGTH_SHORT).show();
145 | Log.w(TAG, "Interstitial ad is visible");
146 | }
147 |
148 | @Override
149 | public void onInterstitialClicked(MoPubInterstitial interstitial) {
150 | Toast.makeText(this, "Interstitial ad clicked", Toast.LENGTH_SHORT).show();
151 | Log.w(TAG, "Interstitial ad clicked");
152 | }
153 |
154 | @Override
155 | public void onInterstitialDismissed(MoPubInterstitial interstitial) {
156 | Toast.makeText(this, "Interstitial ad dismissed", Toast.LENGTH_SHORT).show();
157 | Log.w(TAG, "Interstitial ad dismissed");
158 | }
159 | //endregion
160 |
161 | //region MoPubView.BannerAdListener implementation
162 | @Override
163 | public void onBannerLoaded(MoPubView banner) {
164 | Log.w(TAG, "Banner ad is loaded");
165 | }
166 |
167 | @Override
168 | public void onBannerFailed(MoPubView banner, MoPubErrorCode errorCode) {
169 | Toast.makeText(this, "Banner ad failed to load. Error code: " + errorCode,
170 | Toast.LENGTH_SHORT).show();
171 | Log.w(TAG, "Banner ad failed to load. Error code: " + errorCode);
172 | }
173 |
174 | @Override
175 | public void onBannerClicked(MoPubView banner) {
176 | Toast.makeText(this, "Banner ad clicked", Toast.LENGTH_SHORT).show();
177 | Log.w(TAG, "Banner ad clicked");
178 | }
179 |
180 | @Override
181 | public void onBannerExpanded(MoPubView banner) {
182 |
183 | }
184 |
185 | @Override
186 | public void onBannerCollapsed(MoPubView banner) {
187 |
188 | }
189 | //endregion
190 | }
191 |
--------------------------------------------------------------------------------
/mopub/src/main/java/com/flurry/sample/mopub/MopubNativeActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.mopub;
2 |
3 | import android.os.Bundle;
4 | import android.support.v7.app.AppCompatActivity;
5 | import android.widget.ArrayAdapter;
6 | import android.widget.ListView;
7 |
8 | import com.mopub.nativeads.MoPubAdAdapter;
9 | import com.mopub.nativeads.MoPubAdRenderer;
10 | import com.mopub.nativeads.MoPubNativeAdPositioning;
11 | import com.mopub.nativeads.MoPubStaticNativeAdRenderer;
12 | import com.mopub.nativeads.ViewBinder;
13 |
14 | import java.util.Arrays;
15 |
16 | public class MopubNativeActivity extends AppCompatActivity {
17 |
18 | MoPubAdAdapter mAdAdapter;
19 |
20 | public static final String INVALID_MOPUB_NATIVE_AD_UNIT_ID = "MOPUB_NATIVE_AD_UNIT_ID";
21 | // FIXME: Replace the MoPub ad unit IDs below with your app's valid ad units
22 | public static final String MOPUB_NATIVE_AD_UNIT_ID = INVALID_MOPUB_NATIVE_AD_UNIT_ID;
23 |
24 | @Override
25 | protected void onCreate(Bundle savedInstanceState) {
26 | super.onCreate(savedInstanceState);
27 | setContentView(R.layout.activity_native_ads);
28 |
29 | setupStreamAds();
30 | }
31 |
32 | @Override
33 | protected void onResume() {
34 | super.onResume();
35 |
36 | mAdAdapter.loadAds(MOPUB_NATIVE_AD_UNIT_ID);
37 | }
38 |
39 | private void setupStreamAds() {
40 | ViewBinder mViewBinder = new ViewBinder.Builder(R.layout.list_item_native_ads)
41 | .iconImageId(R.id.native_ad_icon_image)
42 | .mainImageId(R.id.native_ad_main_image)
43 | .titleId(R.id.native_ad_title)
44 | .textId(R.id.native_ad_text)
45 | .build();
46 |
47 | MoPubAdRenderer mAdRenderer = new MoPubStaticNativeAdRenderer(mViewBinder);
48 | MoPubNativeAdPositioning.MoPubClientPositioning mAdPositioning =
49 | MoPubNativeAdPositioning.clientPositioning()
50 | .addFixedPosition(2)
51 | .enableRepeatingPositions(4);
52 |
53 | ArrayAdapter adapter = new ArrayAdapter<>(
54 | MopubNativeActivity.this, android.R.layout.simple_list_item_2, android.R.id.text1,
55 | Arrays.asList(new String[]{
56 | "Filler data 1", "Filler data 2", "Filler data 3", "Filler data 4",
57 | "Filler data 5", "Filler data 6", "Filler data 7", "Filler data 8",
58 | "Filler data 9", "Filler data 10", "Filler data 11", "Filler data 12",
59 | "Filler data 13", "Filler data 14", "Filler data 15", "Filler data 16",
60 | "Filler data 17", "Filler data 18", "Filler data 19", "Filler data 20"}));
61 | mAdAdapter = new MoPubAdAdapter(MopubNativeActivity.this, adapter, mAdPositioning);
62 | mAdAdapter.registerAdRenderer(mAdRenderer);
63 |
64 | ListView lv = (ListView)findViewById(R.id.lv_native);
65 | lv.setAdapter(mAdAdapter);
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/mopub/src/main/java/com/flurry/sample/mopub/MopubSampleApplication.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.mopub;
2 |
3 | import android.app.Application;
4 |
5 | import com.flurry.android.FlurryAgent;
6 |
7 | public class MopubSampleApplication extends Application {
8 |
9 | @Override
10 | public void onCreate() {
11 | super.onCreate();
12 | /*
13 | Optional initialization: It is also done for you in com.mopub.FlurryAgentWrapper
14 | from the Flurry adapter for Mopub. Only use this init if you are already using
15 | Flurry analytics. In that case, remove the FlurryAgent.init(Context, String) and
16 | FlurryAgent.onStartSession(Context) in com.mopub.FlurryAgentWrapper
17 | */
18 |
19 | // FlurryAgent.init(this, "YOUR_FLURRY_API_KEY");
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/mopub/src/main/java/com/mopub/mobileads/FlurryAgentWrapper.java:
--------------------------------------------------------------------------------
1 | package com.mopub.mobileads;
2 |
3 | import android.content.Context;
4 | import android.os.Build;
5 | import android.text.TextUtils;
6 | import android.util.Log;
7 |
8 | import com.flurry.android.FlurryAgent;
9 |
10 | import java.util.WeakHashMap;
11 |
12 | /**
13 | * PLEASE NOTE:
14 | *
15 | * This class is not required for Flurry Analytics users and may safely be deleted
16 | * for apps that already integrate Analytics. However, if removing this file, please
17 | * add FlurryAgent.addOrigin("Flurry_Mopub_Android", "6.1.0") before calling
18 | * {@link FlurryAgent.init(Context, String)} in your code.
19 | */
20 | public final class FlurryAgentWrapper {
21 | private static FlurryAgentWrapper sWrapper;
22 |
23 | public static synchronized FlurryAgentWrapper getInstance() {
24 | if (sWrapper == null) {
25 | sWrapper = new FlurryAgentWrapper();
26 | }
27 |
28 | return sWrapper;
29 | }
30 |
31 | private final WeakHashMap mContextMap = new WeakHashMap<>();
32 |
33 | private FlurryAgentWrapper() {
34 | FlurryAgent.setLogEnabled(false);
35 | FlurryAgent.setLogLevel(Log.INFO);
36 | FlurryAgent.addOrigin("Flurry_Mopub_Android", "6.2.0");
37 | }
38 |
39 | public synchronized void onStartSession(Context context, String apiKey) {
40 | // validate parameters
41 | if (context == null || TextUtils.isEmpty(apiKey)) {
42 | return;
43 | }
44 |
45 | // init
46 | FlurryAgent.init(context, apiKey);
47 |
48 | // sessions are automatic on ICS+
49 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
50 | return;
51 | }
52 |
53 | if (mContextMap.get(context) != null) {
54 | int refCount = mContextMap.get(context);
55 | mContextMap.put(context, ++refCount);
56 | }
57 | else {
58 | mContextMap.put(context, 1);
59 | FlurryAgent.onStartSession(context);
60 | }
61 | }
62 |
63 | public synchronized void onEndSession(Context context) {
64 | // validate parameters
65 | if (context == null) {
66 | return;
67 | }
68 |
69 | // sessions are automatic on ICS+
70 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
71 | return;
72 | }
73 |
74 | if (mContextMap.get(context) != null) {
75 | int refCount = mContextMap.get(context);
76 | if (--refCount == 0) {
77 | mContextMap.remove(context);
78 | FlurryAgent.onEndSession(context);
79 | }
80 | else {
81 | mContextMap.put(context, refCount);
82 | }
83 | }
84 | }
85 | }
--------------------------------------------------------------------------------
/mopub/src/main/java/com/mopub/mobileads/FlurryCustomEventBanner.java:
--------------------------------------------------------------------------------
1 | package com.mopub.mobileads;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.util.Log;
6 | import android.widget.FrameLayout;
7 |
8 | import com.flurry.android.ads.FlurryAdBanner;
9 | import com.flurry.android.ads.FlurryAdBannerListener;
10 | import com.flurry.android.ads.FlurryAdErrorType;
11 |
12 | import java.util.Map;
13 |
14 | import static com.mopub.mobileads.MoPubErrorCode.ADAPTER_CONFIGURATION_ERROR;
15 | import static com.mopub.mobileads.MoPubErrorCode.NETWORK_INVALID_STATE;
16 | import static com.mopub.mobileads.MoPubErrorCode.NETWORK_NO_FILL;
17 |
18 | public class FlurryCustomEventBanner extends com.mopub.mobileads.CustomEventBanner {
19 | public static final String LOG_TAG = FlurryCustomEventBanner.class.getSimpleName();
20 |
21 | private static final String API_KEY = "apiKey";
22 | private static final String AD_SPACE_NAME = "adSpaceName";
23 |
24 | private Context mContext;
25 | private CustomEventBannerListener mListener;
26 | private FrameLayout mLayout;
27 |
28 | private String mApiKey;
29 | private String mAdSpaceName;
30 |
31 | private FlurryAdBanner mBanner;
32 |
33 | public FlurryCustomEventBanner() {
34 | super();
35 | }
36 |
37 | // CustomEventBanner
38 | @Override
39 | protected void loadBanner(Context context,
40 | CustomEventBannerListener listener,
41 | Map localExtras, Map serverExtras) {
42 | if (context == null) {
43 | Log.e(LOG_TAG, "Context cannot be null.");
44 | listener.onBannerFailed(ADAPTER_CONFIGURATION_ERROR);
45 | return;
46 | }
47 |
48 | if (listener == null) {
49 | Log.e(LOG_TAG, "CustomEventBannerListener cannot be null.");
50 | return;
51 | }
52 |
53 | if (!(context instanceof Activity)) {
54 | Log.e(LOG_TAG, "Ad can be rendered only in Activity context.");
55 | listener.onBannerFailed(ADAPTER_CONFIGURATION_ERROR);
56 | return;
57 | }
58 |
59 | if (!extrasAreValid(serverExtras)) {
60 | listener.onBannerFailed(ADAPTER_CONFIGURATION_ERROR);
61 | return;
62 | }
63 |
64 | mContext = context;
65 | mListener = listener;
66 | mLayout = new FrameLayout(context);
67 |
68 | mApiKey = serverExtras.get(API_KEY);
69 | mAdSpaceName = serverExtras.get(AD_SPACE_NAME);
70 |
71 | // Not needed for Flurry Analytics users
72 | FlurryAgentWrapper.getInstance().onStartSession(context, mApiKey);
73 |
74 | Log.d(LOG_TAG, "fetch Flurry Ad (" + mAdSpaceName + ") -- " + mLayout.toString());
75 | mBanner = new FlurryAdBanner(mContext, mLayout, mAdSpaceName);
76 | mBanner.setListener(new FlurryMopubBannerListener());
77 | mBanner.fetchAd();
78 | }
79 |
80 | @Override
81 | protected void onInvalidate() {
82 | if (mContext == null) {
83 | return;
84 | }
85 |
86 | Log.d(LOG_TAG, "MoPub issued onInvalidate (" + mAdSpaceName + ")");
87 |
88 | if (mBanner != null) {
89 | mBanner.destroy();
90 | mBanner = null;
91 | }
92 |
93 | // Not needed for Flurry Analytics users
94 | FlurryAgentWrapper.getInstance().onEndSession(mContext);
95 |
96 | mContext = null;
97 | mListener = null;
98 | mLayout = null;
99 | }
100 |
101 | private boolean extrasAreValid(Map serverExtras) {
102 | if (serverExtras == null) {
103 | return false;
104 | }
105 |
106 | return serverExtras.containsKey(API_KEY) && serverExtras.containsKey(AD_SPACE_NAME);
107 | }
108 |
109 | // FlurryAdListener
110 | private class FlurryMopubBannerListener implements FlurryAdBannerListener {
111 | private final String LOG_TAG = getClass().getSimpleName();
112 |
113 | @Override
114 | public void onFetched(FlurryAdBanner adBanner) {
115 | Log.d(LOG_TAG, "onFetched(" + adBanner.toString() + ")");
116 |
117 | if (mBanner != null) {
118 | mBanner.displayAd();
119 | }
120 | }
121 |
122 | @Override
123 | public void onRendered(FlurryAdBanner adBanner) {
124 | Log.d(LOG_TAG, "onRendered(" + adBanner.toString() + ")");
125 |
126 | if (mListener != null) {
127 | mListener.onBannerLoaded(mLayout);
128 | }
129 | }
130 |
131 | @Override
132 | public void onShowFullscreen(FlurryAdBanner adBanner) {
133 | Log.d(LOG_TAG, "onShowFullscreen(" + adBanner.toString() + ")");
134 |
135 | if (mListener != null) {
136 | mListener.onBannerExpanded();
137 | }
138 | }
139 |
140 | @Override
141 | public void onCloseFullscreen(FlurryAdBanner adBanner) {
142 | Log.d(LOG_TAG, "onCloseFullscreen(" + adBanner.toString() + ")");
143 |
144 | if (mListener != null) {
145 | mListener.onBannerCollapsed();
146 | }
147 | }
148 |
149 | @Override
150 | public void onAppExit(FlurryAdBanner adBanner) {
151 | Log.d(LOG_TAG, "onAppExit(" + adBanner.toString() + ")");
152 |
153 | if (mListener != null) {
154 | mListener.onLeaveApplication();
155 | }
156 | }
157 |
158 | @Override
159 | public void onClicked(FlurryAdBanner adBanner) {
160 | Log.d(LOG_TAG, "onClicked " + adBanner.toString());
161 |
162 | if (mListener != null) {
163 | mListener.onBannerClicked();
164 | }
165 | }
166 |
167 | @Override
168 | public void onVideoCompleted(FlurryAdBanner adBanner) {
169 | Log.d(LOG_TAG, "onVideoCompleted " + adBanner.toString());
170 |
171 | // no-op
172 | }
173 |
174 | @Override
175 | public void onError(FlurryAdBanner adBanner, FlurryAdErrorType adErrorType, int errorCode) {
176 | Log.d(LOG_TAG, "onError(" + adBanner.toString() + adErrorType.toString() + errorCode + ")");
177 |
178 | if (mListener != null) {
179 | if (FlurryAdErrorType.FETCH.equals(adErrorType)) {
180 | mListener.onBannerFailed(NETWORK_NO_FILL);
181 | } else if (FlurryAdErrorType.RENDER.equals(adErrorType)) {
182 | mListener.onBannerFailed(NETWORK_INVALID_STATE);
183 | }
184 | }
185 | }
186 | }
187 | }
--------------------------------------------------------------------------------
/mopub/src/main/java/com/mopub/mobileads/FlurryCustomEventInterstitial.java:
--------------------------------------------------------------------------------
1 | package com.mopub.mobileads;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.util.Log;
6 |
7 | import com.flurry.android.ads.FlurryAdErrorType;
8 | import com.flurry.android.ads.FlurryAdInterstitial;
9 | import com.flurry.android.ads.FlurryAdInterstitialListener;
10 |
11 | import java.util.Map;
12 |
13 | import static com.mopub.mobileads.MoPubErrorCode.ADAPTER_CONFIGURATION_ERROR;
14 | import static com.mopub.mobileads.MoPubErrorCode.NETWORK_INVALID_STATE;
15 | import static com.mopub.mobileads.MoPubErrorCode.NETWORK_NO_FILL;
16 |
17 | public class FlurryCustomEventInterstitial extends com.mopub.mobileads.CustomEventInterstitial {
18 | public static final String LOG_TAG = FlurryCustomEventInterstitial.class.getSimpleName();
19 |
20 | private static final String API_KEY = "apiKey";
21 | private static final String AD_SPACE_NAME = "adSpaceName";
22 |
23 | private Context mContext;
24 | private CustomEventInterstitialListener mListener;
25 |
26 | private String mApiKey;
27 | private String mAdSpaceName;
28 |
29 | private FlurryAdInterstitial mInterstitial;
30 |
31 | public FlurryCustomEventInterstitial() {
32 | super();
33 | }
34 |
35 | // CustomEventInterstitial
36 | @Override
37 | protected void loadInterstitial(Context context,
38 | CustomEventInterstitialListener listener,
39 | Map localExtras, Map serverExtras) {
40 | if (context == null) {
41 | Log.e(LOG_TAG, "Context cannot be null.");
42 | listener.onInterstitialFailed(ADAPTER_CONFIGURATION_ERROR);
43 | return;
44 | }
45 |
46 | if (listener == null) {
47 | Log.e(LOG_TAG, "CustomEventInterstitialListener cannot be null.");
48 | return;
49 | }
50 |
51 | if (!(context instanceof Activity)) {
52 | Log.e(LOG_TAG, "Ad can be rendered only in Activity context.");
53 | listener.onInterstitialFailed(ADAPTER_CONFIGURATION_ERROR);
54 | return;
55 | }
56 |
57 | if (!extrasAreValid(serverExtras)) {
58 | listener.onInterstitialFailed(ADAPTER_CONFIGURATION_ERROR);
59 | return;
60 | }
61 |
62 | mContext = context;
63 | mListener = listener;
64 |
65 | mApiKey = serverExtras.get(API_KEY);
66 | mAdSpaceName = serverExtras.get(AD_SPACE_NAME);
67 |
68 | // Not needed for Flurry Analytics users
69 | FlurryAgentWrapper.getInstance().onStartSession(context, mApiKey);
70 |
71 | Log.d(LOG_TAG, "fetch Flurry ad (" + mAdSpaceName + ")");
72 | mInterstitial = new FlurryAdInterstitial(mContext, mAdSpaceName);
73 | mInterstitial.setListener(new FlurryMopubInterstitialListener());
74 | mInterstitial.fetchAd();
75 | }
76 |
77 | @Override
78 | protected void onInvalidate() {
79 | if (mContext == null) {
80 | return;
81 | }
82 |
83 | Log.d(LOG_TAG, "MoPub issued onInvalidate (" + mAdSpaceName + ")");
84 |
85 | if (mInterstitial != null) {
86 | mInterstitial.destroy();
87 | mInterstitial = null;
88 | }
89 |
90 | // Not needed for Flurry Analytics users
91 | FlurryAgentWrapper.getInstance().onEndSession(mContext);
92 |
93 | mContext = null;
94 | mListener = null;
95 | }
96 |
97 | private boolean extrasAreValid(Map serverExtras) {
98 | if (serverExtras == null) {
99 | return false;
100 | }
101 |
102 | return serverExtras.containsKey(API_KEY) && serverExtras.containsKey(AD_SPACE_NAME);
103 | }
104 |
105 | @Override
106 | protected void showInterstitial() {
107 | Log.d(LOG_TAG, "MoPub issued showInterstitial (" + mAdSpaceName + ")");
108 |
109 | if (mInterstitial != null) {
110 | mInterstitial.displayAd();
111 | }
112 | }
113 |
114 | // FlurryAdListener
115 | private class FlurryMopubInterstitialListener implements FlurryAdInterstitialListener {
116 | private final String LOG_TAG = getClass().getSimpleName();
117 |
118 | @Override
119 | public void onFetched(FlurryAdInterstitial adInterstitial) {
120 | Log.d(LOG_TAG, "onFetched(" + adInterstitial.toString() + ")");
121 |
122 | if (mListener != null) {
123 | mListener.onInterstitialLoaded();
124 | }
125 | }
126 |
127 | @Override
128 | public void onRendered(FlurryAdInterstitial adInterstitial) {
129 | Log.d(LOG_TAG, "onRendered(" + adInterstitial.toString() + ")");
130 |
131 | if (mListener != null) {
132 | mListener.onInterstitialShown();
133 | }
134 | }
135 |
136 | @Override
137 | public void onDisplay(FlurryAdInterstitial adInterstitial) {
138 | Log.d(LOG_TAG, "onDisplay(" + adInterstitial.toString() + ")");
139 |
140 | // no-op
141 | }
142 |
143 | @Override
144 | public void onClose(FlurryAdInterstitial adInterstitial) {
145 | Log.d(LOG_TAG, "onClose(" + adInterstitial.toString() + ")");
146 |
147 | if (mListener != null) {
148 | mListener.onInterstitialDismissed();
149 | }
150 | }
151 |
152 | @Override
153 | public void onAppExit(FlurryAdInterstitial adInterstitial) {
154 | Log.d(LOG_TAG, "onAppExit(" + adInterstitial.toString() + ")");
155 |
156 | if (mListener != null) {
157 | mListener.onLeaveApplication();
158 | }
159 | }
160 |
161 | @Override
162 | public void onClicked(FlurryAdInterstitial adInterstitial) {
163 | Log.d(LOG_TAG, "onClicked " + adInterstitial.toString());
164 |
165 | if (mListener != null) {
166 | mListener.onInterstitialClicked();
167 | }
168 | }
169 |
170 | @Override
171 | public void onVideoCompleted(FlurryAdInterstitial adInterstitial) {
172 | Log.d(LOG_TAG, "onVideoCompleted " + adInterstitial.toString());
173 |
174 | // no-op
175 | }
176 |
177 | @Override
178 | public void onError(FlurryAdInterstitial adBanner, FlurryAdErrorType adErrorType, int errorCode) {
179 | Log.d(LOG_TAG, "onError(" + adBanner.toString() + adErrorType.toString() + errorCode + ")");
180 |
181 | if (mListener != null) {
182 | if (FlurryAdErrorType.FETCH.equals(adErrorType)) {
183 | mListener.onInterstitialFailed(NETWORK_NO_FILL);
184 | } else if (FlurryAdErrorType.RENDER.equals(adErrorType)) {
185 | mListener.onInterstitialFailed(NETWORK_INVALID_STATE);
186 | }
187 | }
188 | }
189 | }
190 | }
--------------------------------------------------------------------------------
/mopub/src/main/java/com/mopub/nativeads/FlurryCustomEventNative.java:
--------------------------------------------------------------------------------
1 | package com.mopub.nativeads;
2 |
3 | import android.app.Activity;
4 | import android.support.annotation.NonNull;
5 | import android.util.Log;
6 |
7 | import com.flurry.android.ads.FlurryAdNative;
8 | import com.mopub.mobileads.FlurryAgentWrapper;
9 |
10 | import java.util.Map;
11 |
12 | public class FlurryCustomEventNative extends CustomEventNative {
13 |
14 | private static final String kLogTag = FlurryCustomEventNative.class.getSimpleName();
15 | private static final String FLURRY_APIKEY = "apiKey";
16 | private static final String FLURRY_ADSPACE = "adSpaceName";
17 |
18 | @Override
19 | protected void loadNativeAd(@NonNull final Activity activity,
20 | @NonNull final CustomEventNativeListener customEventNativeListener,
21 | @NonNull final Map localExtras,
22 | @NonNull final Map serverExtras) {
23 |
24 | final String flurryApiKey;
25 | final String flurryAdSpace;
26 |
27 | //Get the FLURRY_APIKEY and FLURRY_ADSPACE from the server.
28 | if (validateExtras(serverExtras)) {
29 | flurryApiKey = serverExtras.get(FLURRY_APIKEY);
30 | flurryAdSpace = serverExtras.get(FLURRY_ADSPACE);
31 |
32 | // Not needed for Flurry Analytics users
33 | FlurryAgentWrapper.getInstance().onStartSession(activity, flurryApiKey);
34 | } else {
35 | customEventNativeListener.onNativeAdFailed(NativeErrorCode.NATIVE_ADAPTER_CONFIGURATION_ERROR);
36 | Log.i(kLogTag, "Failed Native AdFetch: Missing required server extras [FLURRY_APIKEY and/or FLURRY_ADSPACE].");
37 | return;
38 | }
39 |
40 | final FlurryStaticNativeAd mflurryStaticNativeAd =
41 | new FlurryStaticNativeAd(activity,
42 | new FlurryAdNative(activity, flurryAdSpace), customEventNativeListener);
43 | mflurryStaticNativeAd.fetchAd();
44 | }
45 |
46 | private boolean validateExtras(final Map serverExtras) {
47 | final String flurryApiKey = serverExtras.get(FLURRY_APIKEY);
48 | final String flurryAdSpace = serverExtras.get(FLURRY_ADSPACE);
49 | Log.i(kLogTag, "ServerInfo fetched from Mopub " + FLURRY_APIKEY + " : "
50 | + flurryApiKey + " and " + FLURRY_ADSPACE + " :" + flurryAdSpace);
51 | return ((flurryApiKey != null && flurryApiKey.length() > 0)
52 | && (flurryAdSpace != null && flurryAdSpace.length() > 0));
53 | }
54 |
55 | }
--------------------------------------------------------------------------------
/mopub/src/main/java/com/mopub/nativeads/FlurryStaticNativeAd.java:
--------------------------------------------------------------------------------
1 | package com.mopub.nativeads;
2 |
3 | import android.content.Context;
4 | import android.support.annotation.NonNull;
5 | import android.support.annotation.Nullable;
6 | import android.text.TextUtils;
7 | import android.util.Log;
8 | import android.view.View;
9 |
10 | import com.flurry.android.ads.FlurryAdErrorType;
11 | import com.flurry.android.ads.FlurryAdNative;
12 | import com.flurry.android.ads.FlurryAdNativeAsset;
13 | import com.flurry.android.ads.FlurryAdNativeListener;
14 | import com.mopub.mobileads.FlurryAgentWrapper;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | public class FlurryStaticNativeAd extends StaticNativeAd {
20 |
21 | private static final String kLogTag = FlurryStaticNativeAd.class.getSimpleName();
22 | private static final int IMPRESSION_VIEW_MIN_TIME = 1000;
23 | private static final String CALL_TO_ACTION = "callToAction";
24 |
25 | private final Context mContext;
26 | private final CustomEventNative.CustomEventNativeListener mCustomEventNativeListener;
27 | private final FlurryStaticNativeAd mFlurryStaticNativeAd;
28 |
29 | private static final String ASSET_SEC_HQ_IMAGE = "secHqImage";
30 | private static final String ASSET_SEC_IMAGE = "secImage";
31 | private static final String ASSET_SEC_HQ_RATING_IMG = "secHqRatingImg";
32 | private static final String ASSET_SEC_RATING_IMG = "secRatingImg";
33 | private static final String ASSET_APP_RATING = "appRating";
34 | private static final String ASSET_APP_CATEGORY = "appCategory";
35 | private static final String ASSET_HEADLINE = "headline";
36 | private static final String ASSET_SUMMARY = "summary";
37 | private static final double MOPUB_STAR_RATING_SCALE = StaticNativeAd.MAX_STAR_RATING;
38 |
39 | public static final String EXTRA_STAR_RATING_IMG = "starratingimage";
40 | public static final String EXTRA_APP_CATEGORY = "appcategory";
41 |
42 | private FlurryAdNative nativeAd;
43 |
44 | FlurryStaticNativeAd(Context context, FlurryAdNative adNative,
45 | CustomEventNative.CustomEventNativeListener mCustomEventNativeListener) {
46 | this.mContext = context;
47 | this.nativeAd = adNative;
48 | this.mCustomEventNativeListener = mCustomEventNativeListener;
49 | this.mFlurryStaticNativeAd = this;
50 | }
51 |
52 | public synchronized void fetchAd() {
53 | Context context = mContext;
54 | if (context != null) {
55 | Log.d(kLogTag, "Fetching Flurry Native Ad now.");
56 | nativeAd.setListener(listener);
57 | nativeAd.fetchAd();
58 | } else {
59 | Log.d(kLogTag, "Context is null, not fetching Flurry Native Ad.");
60 | }
61 | }
62 |
63 | private synchronized void onFetched(FlurryAdNative adNative) {
64 | if (adNative != null) {
65 | Log.d(kLogTag, "onFetched: Native Ad fetched successfully!"
66 | + adNative.toString());
67 | setupNativeAd(adNative);
68 | }
69 | }
70 |
71 | private synchronized void onFetchFailed(FlurryAdNative adNative) {
72 | Log.d(kLogTag, "onFetchFailed: Native ad not available. "
73 | + adNative.toString());
74 | if (mCustomEventNativeListener != null) {
75 | mCustomEventNativeListener.onNativeAdFailed(NativeErrorCode.NETWORK_NO_FILL);
76 | }
77 | }
78 |
79 | private synchronized void setupNativeAd(FlurryAdNative adNative) {
80 | if (adNative != null) {
81 | nativeAd = adNative;
82 | FlurryAdNativeAsset coverImageAsset = nativeAd.getAsset(ASSET_SEC_HQ_IMAGE);
83 | FlurryAdNativeAsset iconImageAsset = nativeAd.getAsset(ASSET_SEC_IMAGE);
84 |
85 | if (coverImageAsset != null && !TextUtils.isEmpty(coverImageAsset.getValue())) {
86 | setMainImageUrl(coverImageAsset.getValue());
87 | }
88 | if (iconImageAsset != null && !TextUtils.isEmpty(iconImageAsset.getValue())) {
89 | setIconImageUrl(iconImageAsset.getValue());
90 | }
91 |
92 | setTitle(nativeAd.getAsset(ASSET_HEADLINE).getValue());
93 | setText(nativeAd.getAsset(ASSET_SUMMARY).getValue());
94 |
95 | if(isAppInstallAd()) {
96 | // App rating image URL may be null
97 | FlurryAdNativeAsset ratingHqImageAsset = nativeAd.getAsset(ASSET_SEC_HQ_RATING_IMG);
98 | if (ratingHqImageAsset != null && !TextUtils.isEmpty(ratingHqImageAsset.getValue())) {
99 | addExtra(EXTRA_STAR_RATING_IMG, ratingHqImageAsset.getValue());
100 | } else {
101 | FlurryAdNativeAsset ratingImageAsset = nativeAd.getAsset(ASSET_SEC_RATING_IMG);
102 | if (ratingImageAsset != null && !TextUtils.isEmpty(ratingImageAsset.getValue())) {
103 | addExtra(EXTRA_STAR_RATING_IMG, ratingImageAsset.getValue());
104 | }
105 | }
106 |
107 | FlurryAdNativeAsset appCategoryAsset = nativeAd.getAsset(ASSET_APP_CATEGORY);
108 | if (appCategoryAsset != null) {
109 | addExtra(EXTRA_APP_CATEGORY, appCategoryAsset.getValue());
110 | }
111 | FlurryAdNativeAsset appRatingAsset = nativeAd.getAsset(ASSET_APP_RATING);
112 | if(appRatingAsset != null) {
113 | setStarRating(getStarRatingValue(appRatingAsset.getValue()));
114 | }
115 | }
116 |
117 | FlurryAdNativeAsset ctaAsset = nativeAd.getAsset(CALL_TO_ACTION);
118 | if(ctaAsset != null){
119 | setCallToAction(ctaAsset.getValue());
120 | }
121 |
122 | setImpressionMinTimeViewed(IMPRESSION_VIEW_MIN_TIME);
123 |
124 | if (getImageUrls() == null || getImageUrls().isEmpty()) {
125 | Log.d(kLogTag, "preCacheImages: No images to cache. Flurry Ad Native: " + nativeAd.toString());
126 | mCustomEventNativeListener.onNativeAdLoaded(mFlurryStaticNativeAd);
127 | } else {
128 | NativeImageHelper.preCacheImages(mContext, getImageUrls(), new NativeImageHelper.ImageListener() {
129 | @Override
130 | public void onImagesCached() {
131 | if (mCustomEventNativeListener != null) {
132 | Log.d(kLogTag, "preCacheImages: Ad image cached.");
133 | mCustomEventNativeListener.onNativeAdLoaded(mFlurryStaticNativeAd);
134 | } else {
135 | Log.d(kLogTag, "Unable to notify cache failure: CustomEventNativeListener is null.");
136 | }
137 | }
138 |
139 | @Override
140 | public void onImagesFailedToCache(NativeErrorCode errorCode) {
141 | if (mCustomEventNativeListener != null) {
142 | Log.d(kLogTag, "preCacheImages: Unable to cache Ad image. Error[" + errorCode.toString() + "]");
143 | mCustomEventNativeListener.onNativeAdFailed(errorCode);
144 | } else {
145 | Log.d(kLogTag, "Unable to notify cache failure: CustomEventNativeListener is null.");
146 | }
147 | }
148 | });
149 | }
150 | }
151 | else{
152 | Log.d(kLogTag, "Flurry Native Ad setup failed: ad object is null.");
153 | }
154 | }
155 |
156 | private List getImageUrls() {
157 | final List imageUrls = new ArrayList(2);
158 | final String mainImageUrl = getMainImageUrl();
159 |
160 | if (mainImageUrl != null) {
161 | imageUrls.add(getMainImageUrl());
162 | Log.d(kLogTag, "Flurry Native Ad main image found.");
163 | }
164 |
165 | final String iconUrl = getIconImageUrl();
166 | if (iconUrl != null) {
167 | imageUrls.add(this.getIconImageUrl());
168 | Log.d(kLogTag, "Flurry Native Ad icon image found.");
169 | }
170 | return imageUrls;
171 | }
172 |
173 | private Double getStarRatingValue(@Nullable String appRatingString) {
174 | // App rating String should be of the form X/Y. E.g. 80/100
175 | Double rating = null;
176 | if (appRatingString != null) {
177 | String[] ratingParts = appRatingString.split("/");
178 | if (ratingParts.length == 2) {
179 | try {
180 | float numer = Integer.valueOf(ratingParts[0]);
181 | float denom = Integer.valueOf(ratingParts[1]);
182 | rating = (numer / denom) * MOPUB_STAR_RATING_SCALE;
183 | } catch (NumberFormatException e) { /*Ignore and return null*/ }
184 | }
185 | }
186 | return rating;
187 | }
188 |
189 | private boolean isAppInstallAd() {
190 | return nativeAd.getAsset(ASSET_SEC_RATING_IMG) != null || nativeAd.getAsset(ASSET_SEC_HQ_RATING_IMG) != null
191 | || nativeAd.getAsset(ASSET_APP_CATEGORY) != null;
192 | }
193 |
194 | // BaseForwardingNativeAd
195 | @Override
196 | public void prepare(@NonNull final View view) {
197 | super.prepare(view);
198 | nativeAd.setTrackingView(view);
199 | Log.d(kLogTag, "prepare(" + nativeAd.toString() + " " + view.toString() + ")");
200 | }
201 |
202 | @Override
203 | public void clear(@NonNull View view) {
204 | super.clear(view);
205 | nativeAd.removeTrackingView();
206 | Log.d(kLogTag, "clear("+ nativeAd.toString() + ")");
207 | }
208 |
209 | @Override
210 | public void destroy() {
211 | Log.d(kLogTag, "destroy(" +nativeAd.toString() + ") started.");
212 | super.destroy();
213 | nativeAd.destroy();
214 |
215 | // Not needed for Flurry Analytics users
216 | FlurryAgentWrapper.getInstance().onEndSession(mContext);
217 | }
218 |
219 | FlurryAdNativeListener listener = new FlurryAdNativeListener() {
220 | @Override
221 | public void onFetched(FlurryAdNative adNative) {
222 | Log.d(kLogTag, "onFetched(" +adNative.toString() + ") Successful.");
223 | mFlurryStaticNativeAd.onFetched(adNative);
224 | }
225 |
226 | @Override
227 | public void onError(FlurryAdNative adNative, FlurryAdErrorType adErrorType, int errorCode) {
228 | if (adErrorType.equals(FlurryAdErrorType.FETCH)) {
229 | Log.d(kLogTag, "onError(" + adNative.toString() + ", " + adErrorType.toString() +","+ errorCode + ")");
230 | mFlurryStaticNativeAd.onFetchFailed(adNative);
231 | }
232 | }
233 |
234 | @Override
235 | public void onShowFullscreen(FlurryAdNative adNative) {
236 | Log.d(kLogTag, "onShowFullscreen(" + adNative.toString() + ")");
237 | }
238 |
239 | @Override
240 | public void onCloseFullscreen(FlurryAdNative adNative) {
241 | Log.d(kLogTag, "onCloseFullscreen(" + adNative.toString() + ")");
242 | }
243 |
244 | @Override
245 | public void onClicked(FlurryAdNative adNative) {
246 | Log.d(kLogTag, "onClicked(" +adNative.toString() + ") Successful.");
247 | notifyAdClicked();
248 | }
249 |
250 | @Override
251 | public void onImpressionLogged(FlurryAdNative flurryAdNative) {
252 | Log.d(kLogTag, "onImpressionLogged(" +flurryAdNative.toString() + ") Successful.");
253 | notifyAdImpressed();
254 | }
255 |
256 | @Override
257 | public void onAppExit(FlurryAdNative adNative) {
258 | Log.d(kLogTag, "onAppExit(" + adNative.toString() + ")");
259 | }
260 |
261 | @Override
262 | public void onCollapsed(FlurryAdNative adNative) {
263 | Log.d(kLogTag, "onCollapsed(" + adNative.toString() + ")");
264 | }
265 |
266 | @Override
267 | public void onExpanded(FlurryAdNative adNative) {
268 | Log.d(kLogTag, "onExpanded(" + adNative.toString() + ")");
269 | }
270 | };
271 | }
--------------------------------------------------------------------------------
/mopub/src/main/res/layout/activity_banner_ads.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
15 |
16 |
21 |
--------------------------------------------------------------------------------
/mopub/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
11 |
12 |
16 |
17 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/mopub/src/main/res/layout/activity_native_ads.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/mopub/src/main/res/layout/list_item_native_ads.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
21 |
22 |
30 |
31 |
42 |
43 |
51 |
52 |
59 |
--------------------------------------------------------------------------------
/mopub/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/mopub/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flurry/android-AdIntegrationSamples/7a374376efea6fd03be73a3094f68961b8b4146f/mopub/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/mopub/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/mopub/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #D9000000
4 | #4CAF50
5 |
--------------------------------------------------------------------------------
/mopub/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 |
--------------------------------------------------------------------------------
/mopub/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Flurry Mopub Sample
3 |
4 | Settings
5 | "Lorem ipsum dolor sit amet."
6 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent varius justo nunc, consectetur imperdiet metus mollis non. Nam cursus semper mi sed suscipit. Phasellus lectus mauris, pellentesque ac nisi eu, imperdiet congue est."
7 | SPONSORED
8 |
9 |
--------------------------------------------------------------------------------
/mopub/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/native/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/native/README.md:
--------------------------------------------------------------------------------
1 | Flurry Native Ad Integration
2 | ============================
3 |
4 | This module shows how to integrate native ads into a stream or list in your app using Flurry.
5 |
6 | For this sample, a test API key and ad space are already configured. Do not forget to change the ad
7 | space name and API key if copying code from here.
8 |
9 | The provided ad space supports both static and native video ads.
--------------------------------------------------------------------------------
/native/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 23
5 | buildToolsVersion "23.0.2"
6 |
7 | defaultConfig {
8 | applicationId "com.flurry.sample.gemini"
9 | minSdkVersion 16
10 | targetSdkVersion 23
11 | versionCode 1
12 | versionName "1.0"
13 | }
14 | buildTypes {
15 | release {
16 | minifyEnabled false
17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
18 | }
19 | }
20 | }
21 |
22 | dependencies {
23 | compile 'com.android.support:appcompat-v7:23.1.1'
24 | compile 'com.android.support:support-v4:23.1.1'
25 | compile 'com.google.android.gms:play-services-basement:8.4.0'
26 | compile 'com.android.support:recyclerview-v7:23.1.1'
27 | compile 'com.flurry.android:ads:6.2.0'
28 | compile project(':streamads-lib')
29 | }
30 |
--------------------------------------------------------------------------------
/native/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add any project specific keep options here:
2 |
3 | # If your project uses WebView with JS, uncomment the following
4 | # and specify the fully qualified class name to the JavaScript interface
5 | # class:
6 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
7 | # public *;
8 | #}
9 |
--------------------------------------------------------------------------------
/native/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/BaseAdFragment.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.support.v4.app.Fragment;
4 | import android.util.Log;
5 |
6 | import com.flurry.android.ads.FlurryAdErrorType;
7 | import com.flurry.android.ads.FlurryAdNative;
8 | import com.flurry.android.ads.FlurryAdNativeListener;
9 |
10 | public abstract class BaseAdFragment extends Fragment {
11 |
12 | static final String TAG = BaseAdFragment.class.getSimpleName();
13 |
14 | /*
15 | One ad space can fetch either static or video native ads if enabled on Flurry dashboard.
16 |
17 | NOTE: Use your own Flurry ad space. This is left here to make sample review easier
18 | */
19 | protected static final String AD_SPACE_NAME = "StaticVideoNativeTest";
20 |
21 | protected class NativeAdListener implements FlurryAdNativeListener {
22 |
23 | @Override
24 | public void onFetched(FlurryAdNative flurryAdNative) {
25 | Log.i(TAG, "onFetched callback called with Native ad object: " + flurryAdNative);
26 | }
27 |
28 | @Override
29 | public void onShowFullscreen(FlurryAdNative flurryAdNative) {
30 | Log.i(TAG, "onShowFullscreen callback called");
31 | }
32 |
33 | @Override
34 | public void onCloseFullscreen(FlurryAdNative flurryAdNative) {
35 | Log.i(TAG, "onCloseFullscreen callback called");
36 | }
37 |
38 | @Override
39 | public void onAppExit(FlurryAdNative flurryAdNative) {
40 | Log.i(TAG, "onAppExit callback called");
41 |
42 | }
43 |
44 | @Override
45 | public void onImpressionLogged(FlurryAdNative adNative) {
46 | Log.i(TAG, "onImpressionLogged callback called");
47 | }
48 |
49 | @Override
50 | public void onClicked(FlurryAdNative flurryAdNative) {
51 | Log.i(TAG, "onClicked callback called");
52 | }
53 |
54 | @Override
55 | public void onError(FlurryAdNative flurryAdNative, FlurryAdErrorType flurryAdErrorType,
56 | int errorCode) {
57 | Log.e(TAG, String.format("onError called. Error type: %s. Error code: %d",
58 | flurryAdErrorType, errorCode));
59 | }
60 |
61 | @Override
62 | public void onCollapsed(FlurryAdNative flurryAdNative) {
63 | Log.i(TAG, "onCollapsed callback called");
64 | }
65 |
66 | @Override
67 | public void onExpanded(FlurryAdNative flurryAdNative) {
68 | Log.i(TAG, "onExpanded callback called");
69 | }
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.net.http.HttpResponseCache;
4 | import android.os.Bundle;
5 | import android.support.v4.app.FragmentManager;
6 | import android.support.v4.app.FragmentTransaction;
7 | import android.support.v7.app.AppCompatActivity;
8 | import android.support.v7.widget.Toolbar;
9 | import android.util.Log;
10 |
11 | import java.io.File;
12 | import java.io.IOException;
13 |
14 | public class MainActivity extends AppCompatActivity implements
15 | FragmentManager.OnBackStackChangedListener, NativeAdChooserFragment.Callback {
16 |
17 | @Override
18 | protected void onCreate(Bundle savedInstanceState) {
19 | super.onCreate(savedInstanceState);
20 | setContentView(R.layout.activity_single_pane);
21 |
22 | Toolbar toolbar = (Toolbar) findViewById(R.id.app_toolbar);
23 | setSupportActionBar(toolbar);
24 | if (getSupportActionBar() != null) {
25 | getSupportActionBar().setDisplayShowHomeEnabled(true);
26 | getSupportActionBar().setHomeButtonEnabled(true);
27 | }
28 | displayHomeAsUpIfNeeded();
29 |
30 | if (savedInstanceState == null) {
31 | FragmentManager.enableDebugLogging(true);
32 | getSupportFragmentManager().addOnBackStackChangedListener(this);
33 | getSupportFragmentManager().beginTransaction()
34 | .add(R.id.container, NativeAdChooserFragment.newInstance(), NativeAdChooserFragment.TAG)
35 | .commit();
36 | }
37 |
38 | // http response cache
39 | File httpCacheDir = new File(getCacheDir(), "http");
40 | long httpCacheSize = 100 * 1024 * 1024; // 100 MiB
41 |
42 | try {
43 | HttpResponseCache.install(httpCacheDir, httpCacheSize);
44 | } catch (IOException e) {
45 | Log.i(MainActivity.class.getSimpleName(), "HTTP response cache installation failed:" + e);
46 | }
47 | }
48 |
49 | @Override
50 | public void onBackStackChanged() {
51 | displayHomeAsUpIfNeeded();
52 | }
53 |
54 | @Override
55 | public boolean onSupportNavigateUp() {
56 | getSupportFragmentManager().popBackStack();
57 | return true;
58 | }
59 |
60 | @Override
61 | public void onAdDisplaySelected(int index) {
62 | boolean expandableAdsMode = true;
63 |
64 | switch (index) {
65 | case 0:
66 | getSupportFragmentManager().beginTransaction()
67 | .replace(R.id.container, SingleAdFragment.newInstance(), SingleAdFragment.TAG)
68 | .addToBackStack(SingleAdFragment.TAG)
69 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
70 | .commit();
71 | break;
72 | case 1:
73 | expandableAdsMode = false;
74 | // FALL THROUGH
75 | case 2:
76 | getSupportFragmentManager().beginTransaction()
77 | .replace(R.id.container, StreamListViewFragment.newInstance(expandableAdsMode),
78 | StreamListViewFragment.TAG)
79 | .addToBackStack(StreamListViewFragment.TAG)
80 | .setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
81 | .commit();
82 | break;
83 | }
84 | }
85 |
86 | private void displayHomeAsUpIfNeeded() {
87 | boolean canGoUp = getSupportFragmentManager().getBackStackEntryCount() > 0;
88 | if (getSupportActionBar() != null) {
89 | getSupportActionBar().setDisplayHomeAsUpEnabled(canGoUp);
90 | }
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/NativeAdChooserFragment.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.support.v4.app.ListFragment;
7 | import android.view.View;
8 | import android.widget.ArrayAdapter;
9 | import android.widget.ListView;
10 |
11 | public class NativeAdChooserFragment extends ListFragment {
12 |
13 | private Callback mCallbackListener;
14 |
15 | public static final String TAG = NativeAdChooserFragment.class.getSimpleName();
16 |
17 | public static final NativeAdChooserFragment newInstance() {
18 | return new NativeAdChooserFragment();
19 | }
20 |
21 | @Override
22 | public void onActivityCreated(Bundle savedInstanceState) {
23 | super.onActivityCreated(savedInstanceState);
24 |
25 | String[] adTypes = getActivity().getResources().getStringArray(R.array.native_ad_types);
26 | ArrayAdapter adTypeListAdapter = new ArrayAdapter(getActivity(),
27 | android.R.layout.simple_list_item_1, android.R.id.text1, adTypes);
28 | setListAdapter(adTypeListAdapter);
29 | }
30 |
31 | @Override
32 | public void onAttach(Context context) {
33 | super.onAttach(context);
34 |
35 | if (context instanceof Activity) {
36 | try {
37 | mCallbackListener = (Callback) context;
38 | } catch (ClassCastException e) {
39 | throw new ClassCastException(context.toString() +
40 | " must implement NativeAdChooserFragment.Callback");
41 | }
42 | }
43 | }
44 |
45 | @Override
46 | public void onDetach() {
47 | super.onDetach();
48 | mCallbackListener = null;
49 | }
50 |
51 | @Override
52 | public void onListItemClick(ListView l, View v, int position, long id) {
53 | if (mCallbackListener != null) {
54 | mCallbackListener.onAdDisplaySelected(position);
55 | }
56 | }
57 |
58 | interface Callback {
59 | void onAdDisplaySelected(int index);
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/SingleAdFragment.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.os.Bundle;
4 | import android.support.annotation.Nullable;
5 | import android.view.LayoutInflater;
6 | import android.view.View;
7 | import android.view.ViewGroup;
8 | import android.widget.Button;
9 | import android.widget.ImageView;
10 | import android.widget.TextView;
11 |
12 | import com.flurry.android.ads.FlurryAdErrorType;
13 | import com.flurry.android.ads.FlurryAdNative;
14 |
15 | public class SingleAdFragment extends BaseAdFragment {
16 |
17 | private FlurryAdNative mFlurryAdNative;
18 | // Assets documented here: https://developer.yahoo.com/flurry/docs/publisher/code/android/
19 | private static final String AD_ASSET_SUMMARY = "summary";
20 | private static final String AD_ASSET_HEADLINE = "headline";
21 | private static final String AD_ASSET_SOURCE = "source";
22 | private static final String AD_ASSET_SEC_HQ_BRANDING_LOGO = "secHqBrandingLogo";
23 | private static final String AD_ASSET_SEC_HQ_RATING_IMAGE = "secHqRatingImg";
24 | private static final String AD_ASSET_SHOW_RATING = "showRating";
25 | private static final String AD_ASSET_SEC_HQ_IMAGE = "secHqImage";
26 | private static final String AD_ASSET_SEC_IMAGE = "secImage";
27 | private static final String AD_ASSET_VIDEO_URL = "videoUrl";
28 |
29 | static final String TAG = SingleAdFragment.class.getSimpleName();
30 |
31 | public static final SingleAdFragment newInstance() {
32 | return new SingleAdFragment();
33 | }
34 |
35 | @Nullable
36 | @Override
37 | public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
38 | View rootView = inflater.inflate(R.layout.fragment_single_ad, container, false);
39 |
40 | final View adLayout = rootView.findViewById(R.id.ad_layout);
41 |
42 | final TextView adSourceTxt = (TextView)rootView.findViewById(R.id.ad_source);
43 | final TextView adHeadlineTxt = (TextView)rootView.findViewById(R.id.ad_headline);
44 | final TextView adDescription = (TextView)rootView.findViewById(R.id.ad_description);
45 | final ViewGroup adVideo = (ViewGroup)rootView.findViewById(R.id.ad_video);
46 | final ImageView adImage = (ImageView)rootView.findViewById(R.id.ad_image);
47 | final ImageView adSponsorImg = (ImageView)rootView.findViewById(R.id.sponsored_image);
48 | final ImageView adAppRatingImg = (ImageView)rootView.findViewById(R.id.app_rating_image);
49 |
50 | final Button renderAdBtn = (Button)rootView.findViewById(R.id.render_ad_btn);
51 | final NativeAdListener nativeAdListener = new NativeAdListener() {
52 | @Override
53 | public void onFetched(FlurryAdNative flurryAdNative) {
54 | super.onFetched(flurryAdNative);
55 |
56 | renderAdBtn.setEnabled(true);
57 | }
58 |
59 | @Override
60 | public void onError(FlurryAdNative flurryAdNative,
61 | FlurryAdErrorType flurryAdErrorType, int errorCode) {
62 | super.onError(flurryAdNative, flurryAdErrorType, errorCode);
63 |
64 | renderAdBtn.setEnabled(false);
65 | }
66 | };
67 |
68 | rootView.findViewById(R.id.fetch_ad_btn).setOnClickListener(new View.OnClickListener() {
69 | @Override
70 | public void onClick(View v) {
71 | if (mFlurryAdNative != null) { mFlurryAdNative.destroy(); }
72 |
73 | mFlurryAdNative = new FlurryAdNative(getActivity(), AD_SPACE_NAME);
74 | mFlurryAdNative.setListener(nativeAdListener);
75 | mFlurryAdNative.fetchAd();
76 | }
77 | });
78 | renderAdBtn.setOnClickListener(new View.OnClickListener() {
79 | @Override
80 | public void onClick(View v) {
81 | mFlurryAdNative.getAsset(AD_ASSET_SOURCE).loadAssetIntoView(adSourceTxt);
82 | mFlurryAdNative.getAsset(AD_ASSET_HEADLINE).loadAssetIntoView(adHeadlineTxt);
83 | mFlurryAdNative.getAsset(AD_ASSET_SUMMARY).loadAssetIntoView(adDescription);
84 | if (mFlurryAdNative.isVideoAd()) {
85 | mFlurryAdNative.getAsset(AD_ASSET_VIDEO_URL).loadAssetIntoView(adVideo);
86 | }
87 | if (mFlurryAdNative.getAsset(AD_ASSET_SEC_HQ_IMAGE) != null) {
88 | mFlurryAdNative.getAsset(AD_ASSET_SEC_HQ_IMAGE).loadAssetIntoView(adImage);
89 | } else if (mFlurryAdNative.getAsset(AD_ASSET_SEC_IMAGE) != null) {
90 | mFlurryAdNative.getAsset(AD_ASSET_SEC_IMAGE).loadAssetIntoView(adImage);
91 | }
92 | mFlurryAdNative.getAsset(AD_ASSET_SEC_HQ_BRANDING_LOGO).loadAssetIntoView(adSponsorImg);
93 | if (mFlurryAdNative.getAsset(AD_ASSET_SHOW_RATING) != null &&
94 | mFlurryAdNative.getAsset(AD_ASSET_SHOW_RATING).equals("true")) {
95 | mFlurryAdNative.getAsset(AD_ASSET_SEC_HQ_RATING_IMAGE).loadAssetIntoView(adAppRatingImg);
96 | }
97 |
98 | mFlurryAdNative.setTrackingView(adLayout);
99 |
100 | renderAdBtn.setEnabled(false);
101 | }
102 | });
103 |
104 | return rootView;
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/StreamApplication.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.app.Application;
4 |
5 | import com.flurry.android.FlurryAgent;
6 |
7 | public class StreamApplication extends Application {
8 |
9 | // NOTE: Use your own Flurry API key. This is left here to make sample review easier
10 | private static final String FLURRY_APIKEY = "JQVT87W7TGN5W7SWY2FH";
11 |
12 | @Override
13 | public void onCreate() {
14 | super.onCreate();
15 |
16 | FlurryAgent.setLogEnabled(true);
17 | FlurryAgent.init(this, FLURRY_APIKEY);
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/StreamListViewFragment.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.support.annotation.Nullable;
6 | import android.support.v4.app.Fragment;
7 | import android.util.Log;
8 | import android.view.LayoutInflater;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 | import android.widget.ArrayAdapter;
12 | import android.widget.BaseAdapter;
13 | import android.widget.ImageView;
14 | import android.widget.ListView;
15 | import android.widget.TextView;
16 |
17 | import com.flurry.android.ads.FlurryAdErrorType;
18 | import com.flurry.android.ads.FlurryAdNative;
19 | import com.flurry.android.ads.FlurryAdNativeListener;
20 | import com.flurry.android.ads.FlurryAdTargeting;
21 | import com.flurry.sample.gemini.entities.NewsArticle;
22 | import com.yahoo.mobile.library.streamads.FlurryAdListAdapter;
23 | import com.yahoo.mobile.library.streamads.NativeAdAdapter;
24 | import com.yahoo.mobile.library.streamads.NativeAdViewBinder;
25 | import com.yahoo.mobile.library.streamads.positioning.LinearIntervalAdPositioner;
26 |
27 | import java.util.ArrayList;
28 | import java.util.List;
29 | import java.util.Random;
30 |
31 | /**
32 | * This sample uses the library at https://github.com/flurry/StreamAds-Android
33 | * for integrating ads interspersed with other content in a stream adapter.
34 | *
35 | * For best practices in using ads in a stream, please review the code from the library.
36 | */
37 | public class StreamListViewFragment extends BaseAdFragment {
38 | static final String TAG = StreamListViewFragment.class.getSimpleName();
39 |
40 | private ListView mListView;
41 | private List mArticles;
42 | private boolean mExpandableAdsMode;
43 | private final static int ARTICLES_TO_LOAD = 20;
44 |
45 | protected NativeAdListener mNativeAdListener = new NativeAdListener();
46 |
47 | public static final StreamListViewFragment newInstance(boolean expandableAdsMode) {
48 | StreamListViewFragment newInstance = new StreamListViewFragment();
49 | newInstance.mExpandableAdsMode = expandableAdsMode;
50 | return newInstance;
51 | }
52 |
53 | @Override
54 | public View onCreateView(LayoutInflater inflater, ViewGroup container,
55 | Bundle savedInstanceState) {
56 | View rootView = inflater.inflate(R.layout.fragment_main_stream, container, false);
57 |
58 | mListView = (ListView)rootView.findViewById(android.R.id.list);
59 |
60 | return rootView;
61 | }
62 |
63 | @Override
64 | public void onActivityCreated(@Nullable Bundle savedInstanceState) {
65 | super.onActivityCreated(savedInstanceState);
66 |
67 | mArticles = new ArrayList<>(ARTICLES_TO_LOAD);
68 |
69 | loadArticles();
70 |
71 | BaseAdapter dataAdapter = new ArticleAdapter(getActivity(), R.layout.list_item_article, mArticles);
72 |
73 | NativeAdViewBinder.ViewBinderBuilder viewBinderBuilder = new NativeAdViewBinder.ViewBinderBuilder();
74 |
75 | viewBinderBuilder = viewBinderBuilder.setAdLayoutId(R.layout.list_item_ad)
76 | .setHeadlineTextId(R.id.ad_headline)
77 | .setDescriptionTextId(R.id.ad_description)
78 | .setSourceTextId(R.id.ad_source)
79 | .setBrandingLogoImageId(R.id.sponsored_image)
80 | .setAppStarRatingImageId(R.id.app_rating_image)
81 | .setAdImageId(R.id.ad_image);
82 |
83 | if (mExpandableAdsMode) {
84 | viewBinderBuilder = viewBinderBuilder
85 | .setCallToActionViewId(R.id.ad_cta_btn)
86 | .setAdCollapseViewId(R.id.ad_collapse_btn);
87 | }
88 |
89 | NativeAdViewBinder viewBinder = viewBinderBuilder.build();
90 |
91 | FlurryAdListAdapter.Builder flurryAdAdapterBuilder = FlurryAdListAdapter
92 | .from(getActivity(), dataAdapter, viewBinder, AD_SPACE_NAME)
93 | .setAdPositioner(new LinearIntervalAdPositioner(3, 4))
94 | .setFlurryAdNativeListener(mNativeAdListener)
95 | .setAutoDestroy(true);
96 |
97 | if (mExpandableAdsMode) {
98 | flurryAdAdapterBuilder = flurryAdAdapterBuilder
99 | .setExpandableAdMode(NativeAdAdapter.EXPANDABLE_AD_MODE_COLLAPSED);
100 | }
101 |
102 | FlurryAdListAdapter adListAdapter = flurryAdAdapterBuilder.build();
103 |
104 | mListView.setAdapter(adListAdapter);
105 |
106 | adListAdapter.refreshAds();
107 | }
108 |
109 | private void loadArticles() {
110 | String[] titles = getResources().getStringArray(R.array.article_titles);
111 | String content = getResources().getString(R.string.sample_long_text);
112 | String[] authors = getResources().getStringArray(R.array.article_authors);
113 |
114 | Random random = new Random();
115 |
116 | for (int i = 0; i < ARTICLES_TO_LOAD; i++) {
117 | NewsArticle article = new NewsArticle();
118 | article.setArticleTitle(titles[random.nextInt(15)]);
119 | article.setArticleContent(content);
120 | article.setArticleImageResourceId(R.color.placeholder_image_background);
121 | article.setArticleCreator(authors[random.nextInt(15)]);
122 |
123 | mArticles.add(article);
124 | }
125 | }
126 |
127 | private static class ArticleAdapter extends ArrayAdapter {
128 |
129 | public ArticleAdapter(Context context, int resource, List objects) {
130 | super(context, resource, objects);
131 | }
132 |
133 | @Override
134 | public View getView(int position, View convertView, ViewGroup parent) {
135 | ViewHolder viewHolder;
136 |
137 | if (convertView == null) {
138 | convertView = LayoutInflater.from(getContext())
139 | .inflate(R.layout.list_item_article, parent, false);
140 |
141 | viewHolder = new ViewHolder();
142 | viewHolder.articleTitleTextView = (TextView)convertView.findViewById(
143 | R.id.article_title);
144 | viewHolder.articleContentTextView = (TextView)convertView.findViewById(
145 | R.id.article_content);
146 | viewHolder.articleAuthorTextView = (TextView)convertView.findViewById(
147 | R.id.article_author);
148 | viewHolder.articleImageView = (ImageView)convertView.findViewById(
149 | R.id.article_image);
150 |
151 | convertView.setTag(viewHolder);
152 | } else {
153 | viewHolder = (ViewHolder)convertView.getTag();
154 | }
155 |
156 | // Show an article
157 | viewHolder.articleTitleTextView.setText(
158 | getItem(position).getArticleTitle());
159 | viewHolder.articleContentTextView.setText(
160 | getItem(position).getArticleContent());
161 | viewHolder.articleAuthorTextView.setText(
162 | getItem(position).getArticleCreator());
163 | viewHolder.articleImageView.setImageResource(
164 | getItem(position).getArticleImageResourceId());
165 |
166 | return convertView;
167 | }
168 | }
169 |
170 | private static class ViewHolder {
171 | public ImageView articleImageView;
172 | public TextView articleTitleTextView;
173 | public TextView articleContentTextView;
174 | public TextView articleAuthorTextView;
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/native/src/main/java/com/flurry/sample/gemini/entities/NewsArticle.java:
--------------------------------------------------------------------------------
1 | package com.flurry.sample.gemini.entities;
2 |
3 | public class NewsArticle {
4 | private String mArticleTitle;
5 | private String mArticleContent;
6 | private String mArticleCreator;
7 | private int mArticleImageResourceId;
8 |
9 | public String getArticleTitle() {
10 | return mArticleTitle;
11 | }
12 |
13 | public void setArticleTitle(String articleTitle) {
14 | mArticleTitle = articleTitle;
15 | }
16 |
17 | public String getArticleContent() {
18 | return mArticleContent;
19 | }
20 |
21 | public void setArticleContent(String articleContent) {
22 | mArticleContent = articleContent;
23 | }
24 |
25 | public int getArticleImageResourceId() {
26 | return mArticleImageResourceId;
27 | }
28 |
29 | public void setArticleImageResourceId(int articleImageResourceId) {
30 | mArticleImageResourceId = articleImageResourceId;
31 | }
32 |
33 | public String getArticleCreator() {
34 | return mArticleCreator;
35 | }
36 |
37 | public void setArticleCreator(String articleCreator) {
38 | mArticleCreator = articleCreator;
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/native/src/main/res/drawable/scrim_gradient_bottom_dark.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
9 |
10 |
--------------------------------------------------------------------------------
/native/src/main/res/layout/activity_single_pane.xml:
--------------------------------------------------------------------------------
1 |
9 |
10 |
18 |
19 |
22 |
23 |
24 |
--------------------------------------------------------------------------------
/native/src/main/res/layout/fragment_main_stream.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
--------------------------------------------------------------------------------
/native/src/main/res/layout/fragment_single_ad.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
13 |
18 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/native/src/main/res/layout/list_item_ad.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
22 |
23 |
30 |
31 |
43 |
44 |
53 |
59 |
60 |
64 |
65 |
66 |
67 |
79 |
80 |
90 |
91 |
102 |
103 |
111 |
112 |
122 |
123 |
124 |
--------------------------------------------------------------------------------
/native/src/main/res/layout/list_item_article.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
21 |
22 |
34 |
35 |
46 |
47 |
59 |
60 |
71 |
72 |
--------------------------------------------------------------------------------
/native/src/main/res/menu/menu_main.xml:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------
/native/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/flurry/android-AdIntegrationSamples/7a374376efea6fd03be73a3094f68961b8b4146f/native/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/native/src/main/res/values-w820dp/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 64dp
6 |
7 |
--------------------------------------------------------------------------------
/native/src/main/res/values/arrays.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | - Does the noble pulse against a strip biography?
5 | - The leader surfaces against the virtual rot.
6 | - The leadership tolls the wife in the descending plate.
7 | - The wreck chooses after an industrial model.
8 | - Can a restricting opponent reason after a greed?
9 | - Past the jelly rants the miserable giant.
10 | - The mum accident crashes.
11 | - A moderate rocks?
12 | - The surplus censors an individual brass.
13 | - Another protein runs into the teenage.
14 | - The chemical billfold rolls after the sphere.
15 | - The lowering moral swallows on top of the estimated complaint.
16 | - A concatenate waste peers over the review bathroom.
17 | - An excellent enlightened brakes the aligning guidance.
18 | - A seal sweeps within the song!
19 |
20 |
21 |
22 |
23 | - Gabrielius Enitan
24 | - Yehu\' Cassianus
25 | - Line Kornelia
26 | - Bea Filipa
27 | - Perrine Delmar
28 | - Alden Redmund
29 | - Talia Marisa
30 | - Teodor Diana
31 | - Ulla Antón
32 | - Glorinda Syeda
33 | - Lysimachus Wattana
34 | - Secundinus Yvonne
35 | - Hachiro Jürgen
36 | - Brigitte Richard
37 | - Zdislav Alyce
38 |
39 |
40 |
41 | - Single native ad
42 | - Native ads in a list
43 | - Expandable Native ads
44 |
45 |
46 |
--------------------------------------------------------------------------------
/native/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #ffffff
4 | #8333
5 | #555
6 | #5A00C8
7 |
8 | #4CAF50
9 |
--------------------------------------------------------------------------------
/native/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 16dp
4 | 16dp
5 |
6 | 16dp
7 |
8 | 12sp
9 | 14sp
10 | 18sp
11 | 20sp
12 | 26sp
13 |
14 |
--------------------------------------------------------------------------------
/native/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Flurry Native Sample
3 |
4 | Settings
5 | "Lorem ipsum dolor sit amet."
6 | "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent varius justo nunc, consectetur imperdiet metus mollis non. Nam cursus semper mi sed suscipit. Phasellus lectus mauris, pellentesque ac nisi eu, imperdiet congue est."
7 | SPONSORED
8 |
9 | Fetch ad
10 | Render ad
11 |
12 | Learn more
13 | Collapse ▲
14 |
15 |
--------------------------------------------------------------------------------
/native/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
14 |
15 |
20 |
21 |
28 |
29 |
34 |
35 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':banner', ':interstitial', ':mopub', ':native', ':streamads-lib'
2 | project(':streamads-lib').projectDir = new File('StreamAds-Android/lib-adapter')
3 |
--------------------------------------------------------------------------------