Prerequisites
- Flutter 2 or later.
- Xcode 12.5 or later.
- iOS 9 or later.
- Android 4.0 (Ice Cream Sandwich - API Version 14) or later.
- Enable AndroidX in your project. For more information.
- Application Id provided in Admost Mediation Dashboard.
- Zone Id(s) provided in Admost Mediation Dashboard.
For testing you can use following Ids;
IOS Test Ids
Application Id: "15066ddc-9c18-492c-8185-bea7e4c7f88c"
Banner Zone Id: "b4009772-de04-42c4-bbaa-c18da9e4a1ab"
Interstitial Zone Id: "39f74377-5682-436a-9338-9d1c4df410bd"
RewardedVideo Zone Id: "2bdefd44-5269-4cbc-b93a-373b74a2f067"
Android Test Ids
Application Id: "6cc8e89a-b52a-4e9a-bb8c-579f7ec538fe"
Banner Zone Id: "9fb970db-7d96-4ef2-ac8c-d88ec22270ff"
Interstitial Zone Id: "f99e409b-f9ab-4a2e-aa9a-4d143e6809ae"
RewardedVideo Zone Id: "88cfcfd0-2f8c-4aba-9f36-cc0ac99ab140"
Setup
You can install the AMR SDK in your Flutter app by adding the following under
dependencies:
in your pubspec.yaml
file:
admost_flutter_plugin: "^1.2.5"
Then navigate to your project's directory in terminal and run:
flutter pub get
Please refer to following table for required and optional packages for your target.
Status | Name | Download Links |
---|
IOS Setup Notes
Required Files
With your selections you are going to work with following files;
Podfile
Info.plist
Flutter ~ Project view | Info.plist and Podfile location
- android
-
ios
Podfile
~> HERE- Flutter
-
Runner
- AppDelegate.swift
- Assets.xcassets
- Base.lproj
- GeneratedPluginRegistrant.h
- GeneratedPluginRegistrant.m
Info.plist
~> HERE- Runner-Bridging-Header.h
- Runner.xcodeproj
- Runner.xcworkspace
- lib
- pubspec.yaml
-
CocoaPods is a dependency manager for Swift and Objective-C Cocoa projects which automates and simplifies the process of using 3rd-party libraries like AMR in your projects. See getting started guide for more information on installing cocoapods.
Edit Files
At least one mediation adapter is required for AMRSDK to show banners. You can add all adapters (recommended for maximized revenue) or start with a subset of adapters. Consult your AMR agent for further details.
Please select the ad networks you want to install from the list above.
Podfile
will be updated while you are choosing networks.
To integrate AMR SDK and mediation adapters into your Flutter project using CocoaPods,
specify it in
your Podfile:
PLEASE SELECT ONE OR MORE NETWORKS TO CREATE YOUR PODPSPEC DEPENDENCY LIST.
Add following lines to your plist
file.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>admost.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
</dict>
<key>NSCalendarsUsageDescription</key>
<string>Some ad content may access calendar</string>
Important If you are using AdMob you must add
your AdMob App ID
to your plist
file with
GADApplicationIdentifier
key as shown below.
(Replace
ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX
with your own App ID
)
<key>GADApplicationIdentifier</key>
<string>ca-app-pub-XXXXXXXXXXXXXXXX~XXXXXXXXXX</string>
Your App ID
can be found on AdMob dashboard -> Apps -> App settings
-> App info.
Important If you are using AppLovin you must add
AppLovin SDK Key
to your plist
file with
AppLovinSdkKey
key as shown below.
(Replace
XXXXXXXXXXXXXXX
with your own AppLovin SDK Key
)
<key>AppLovinSdkKey</key>
<string>XXXXXXXXXXXXXXX</string>
Your AppLovin SDK Key
can be found on AppLovin Dashboard -> Account
-> Keys.
Important If you are using Appsamurai or YouAppi
you must set Always Embed Swift Libraries
value YES.
Important If you are using Pollfish you must update and add Pollfish Policy to your privacy policy file.
Optional If you are using AdColony you need to
add following code to your plist
file.
<key>LSApplicationQueriesSchemes</key>
<array>
<string>fb</string>
<string>instagram</string>
<string>tumblr</string>
<string>twitter</string>
</array>
SKAdNetwork
With the iOS 14, you need to add SKAdNetwork
ids to your Info.plist
file to support conversion tracking.
Add following code to your Info.plist
file:
PLEASE SELECT ONE OR MORE NETWORKS TO CREATE YOUR SKADNETWORK LIST.
iOS 14
Starting with iOS 14, apps will be required to ask users for permission to access IDFA. In
order to ask for this permission and display the App Tracking Transparency authorization
request for accessing the IDFA, you will need to add
NSUserTrackingUsageDescription
key to Info.plist
file.
<key>NSUserTrackingUsageDescription</key>
<string>Your awesome message to encourage user to give permission to access IDFA</string>
To present the authorization request, call
AdmostATTrackingManager.requestTrackingAuthorization():
import 'package:admost_flutter_plugin/admost_ios_attrackingmanager.dart';
...
if (Platform.isIOS) {
AdmostATTrackingManager.requestTrackingAuthorization().then((status) {
// Tracking authorization completed.
});
}
User is prompted with following popup after requestTrackingAuthorization
call.
Please see
ATTrackingManager.AuthorizationStatus
for possible return values.
Android Setup Notes
Required Files
With your selections you are going to work with following files;
/build.gradle
/app/src/build.gradle
gradle.properties
AndroidManifest.xml
If you are using proguard you have to edit /app/src/proguard-rules.pro
too.
Flutter ~ Project view
-
android
-
app
- src
- debug
-
main
-
AndroidManifest.xml
~> AndroidManifest.xml
-
- profile
build.gradle
~> /app/src/build.gradleproguard-rules.pro
~> /app/src/proguard-rules.pro
- src
- gradle
build.gradle
~> /build.gradlegradle.properties
~> gradle.properties
-
app
- ios
- lib
- pubspec.yaml
Edit Files
Add the following lines inside repositories{} bracelets in
/build.gradle
file
Add the following lines inside android{} bracelets in
/app/src/build.gradle
file
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
Add the following lines inside dependencies{} bracelets in
/app/src/build.gradle
file
It is highly recommended to enable AndroidX in your project. Editing
gradle.properties
file and adding the lines below(if they are
not present) is required for most ad-network sdks.
android.useAndroidX=true
android.enableJetifier=true
Starting with Android 9.0 (API level 28), cleartext support is disabled by default. For applications targetSdkVersion higher than 27 must use the following manifest config for AdMost cleartext support.
<manifest ...>
<uses-permission android:name="android.permission.INTERNET" />
<application
...
android:networkSecurityConfig="@xml/admost_network_security_config"
...>
...
</application>
</manifest>
Important If you are using Admob SDK
(com.google.android.gms:play-services-ads) with version
17.0.0 and higher, you must add your AdMob App ID
to your
Android Manifest
file.
<manifest>
<application>
<!-- Sample AdMob App ID: ca-app-pub-0000000000000000~0000000000 -->
<meta-data
android:name="com.google.android.gms.ads.APPLICATION_ID"
android:value="[ADMOB_APP_ID]"/>
</application>
</manifest>
Your App ID
can be found on AdMob dashboard -> Apps -> App
settings -> App info.
Important If you are using AppLovin you
must add AppLovin SDK Key
to your Android Manifest
file as shown below.
<manifest>
<application>
<meta-data
android:name="applovin.sdk.key"
android:value="YOUR_SDK_KEY_FROM_APPLOVIN"/>
</application>
</manifest>
Your AppLovin SDK Key
can be found on AppLovin Dashboard ->
Account -> Keys.
Proguard
If you are using proguard. Copy & paste following code snippet in to your
/app/src/proguard-rules.pro
file
# ADMOST
-keepattributes Exceptions, InnerClasses
-dontwarn admost.sdk.**
-keep class admost.sdk.** {*;}
-dontwarn com.amr.unity.**
-keep class com.amr.unity.** {*;}
-dontwarn admost.adserver.**
-keep class com.adjust.sdk.** {*;}
-dontwarn com.adjust.sdk.**
-keep class com.appsflyer.** {*;}
-dontwarn com.appsflyer.**
-keep class admost.adserver.** { *; }
-dontwarn com.google.android.exoplayer2.**
-keep class com.google.android.exoplayer2.**{ *;}
-keep class android.support.v4.app.DialogFragment { *; }
-keep class android.support.v4.util.LruCache { *; }
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# ADCOLONY
-dontwarn com.adcolony.**
-keep class com.adcolony.** { *; }
-keepclassmembers class * { @android.webkit.JavascriptInterface <methods>; }
-keepclassmembers class com.adcolony.sdk.ADCNative** { *; }
# ADGEM
-keep class com.adgem.** { *; }
-dontwarn com.adgem.**
# ADMOB / ADX / GOOGLE
-keep class com.android.vending.billing.**
-keep public class com.google.android.gms.ads.** { public *; }
-keep public class com.google.ads.** { public *; }
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { public static final *** NULL; }
-keepnames class * implements android.os.Parcelable
-keepclassmembers class * implements android.os.Parcelable { public static final *** CREATOR; }
-keep @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclasseswithmembers class * { @android.support.annotation.Keep <fields>; }
-keepclasseswithmembers class * { @android.support.annotation.Keep <methods>; }
-keep @interface com.google.android.gms.common.annotation.KeepName
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * { @com.google.android.gms.common.annotation.KeepName *; }
-keep @interface com.google.android.gms.common.util.DynamiteApi
-keep public @com.google.android.gms.common.util.DynamiteApi class * { public <fields>; public <methods>; }
-keep public @com.google.android.gms.common.util.DynamiteApi class * { *; }
-keep class com.google.android.apps.common.proguard.UsedBy*
-keep @com.google.android.apps.common.proguard.UsedBy* class *
-keepclassmembers class * { @com.google.android.apps.common.proguard.UsedBy* *; }
-dontwarn android.security.NetworkSecurityPolicy
-dontwarn android.app.Notification
#ADTIMING
-dontwarn com.aiming.mdt.**.*
-dontoptimize
-dontskipnonpubliclibraryclasses
-keepattributes *Annotation*
#adt
-keep class com.aiming.mdt.**{ *; }
-keepattributes *Annotation*,InnerClasses
-keepnames class * implements android.os.Parcelable {
public static final ** CREATOR;
}
#R
-keepclassmembers class **.R$* {
public static <fields>;
}
#AFA
-dontwarn com.admost.**
-keep class com.admost.** {*;}
# AMAZON
-dontwarn com.amazon.**
-keep class com.amazon.** { *; }
-dontwarn org.apache.http.**
-keepattributes *Annotation*
# APPLOVIN
-dontwarn com.applovin.**
-keep class com.applovin.** { *; }
# APPNEXT
-keep class com.appnext.** { *; }
-dontwarn com.appnext.**
# CHARTBOOST
-dontwarn org.apache.http.**
-dontwarn com.chartboost.sdk.impl.**
-keep class com.chartboost.sdk.** { *; }
-keepattributes *Annotation*
# CRITEO
-dontwarn com.criteo.**
-keep class com.criteo.** { *; }
# DISPLAYIO
-keep class io.display.sdk.** { *; }
-dontwarn io.display.sdk.**
-keep class com.brandio.ads.** { *;}
-dontwarn com.brandio.ads.**
# FACEBOOK
-dontwarn com.facebook.ads.**
-dontnote com.facebook.ads.**
-keep class com.facebook.** { *; }
-keepattributes Signature
-keep class com.google.android.exoplayer2.** {*;}
-dontwarn com.google.android.exoplayer2.**
# FLURRY
-keep class com.flurry.** { *; }
-dontwarn com.flurry.**
-keepattributes *Annotation*,EnclosingMethod,Signature
-keepclasseswithmembers class * { public <init>(android.content.Context, android.util.AttributeSet, int); }
-keep class * extends java.util.ListResourceBundle { protected Object[][] getContents(); }
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { public static final *** NULL; }
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * { @com.google.android.gms.common.annotation.KeepName *; }
-keepnames class * implements android.os.Parcelable { public static final ** CREATOR; }
# FREECORP
-keep class com.fly.** { *; }
-dontwarn com.fly.**
# FYBER
-keep class com.fyber.** { *; }
-dontwarn com.fyber.**
-keep class com.fyber.mediation.MediationConfigProvider { public static *; }
-keep class com.fyber.mediation.MediationAdapterStarter { public static *; }
-keepclassmembers class com.fyber.ads.videos.mediation.** { void setValue(java.lang.String); }
# HUAWEI-ADS
-keep class com.huawei.openalliance.ad.** { *; }
-keep class com.huawei.hms.ads.** { *; }
# INMOBI
-keepattributes SourceFile,LineNumberTable
-keep class com.inmobi.** {*;}
-dontwarn com.inmobi.**
-keep public class com.google.android.gms.**
-dontwarn com.google.android.gms.**
-dontwarn com.squareup.picasso.**
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient{public *;}
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info{public *;}
-keep class com.squareup.picasso.** {*;}
-dontwarn com.squareup.picasso.**
-dontwarn com.squareup.okhttp.**
-keep class com.moat.** {*;}
-dontwarn com.moat.**
-keep class com.integralads.avid.library.* {*;}
# INNERACTIVE
-dontwarn com.fyber.**
-keep class com.fyber.** {*;}
-dontwarn com.inneractive.api.ads.**
-keep class com.inneractive.api.ads.** {*;}
-keepclassmembers class com.inneractive.api.ads.** {*;}
-keepclassmembers class com.inneractive.api.ads.sdk.nativead.** {*;}
-keepattributes Signature
-keepattributes *Annotation*
-keep class sun.misc.Unsafe { *; }
-keep class com.google.gson.stream.** { *; }
-keep class com.google.gson.examples.android.model.** { *; }
-keep class com.google.gson.Gson { *; }
-keep class com.google.gson.GsonBuilder { *; }
-keep class com.google.gson.FieldNamingStrategy { *; }
# IRONSOURCE
-dontwarn com.ironsource.**
-keep class com.ironsource.** { *; }
-keepclassmembers class * implements android.os.Parcelable { public static final android.os.Parcelable$Creator *; }
-keep public class com.google.android.gms.ads.** { public *; }
-keep class com.ironsource.adapters.** { *; }
-dontwarn com.moat.**
-keep class com.moat.** { public protected private *; }
# LOOPME
-dontwarn com.loopme.**
-keep class com.loopme.** { *; }
# MEDIABRIX
-keep class com.mediabrix.** { *; }
-keep class com.moat.** { *; }
-keep class mdos.** { *; }
-dontwarn com.mediabrix.**
-dontwarn com.moat.**
-dontwarn mdos.**
# MILLENNIAL & NEXAGE
-keep class com.millennialmedia.** { *; }
-dontwarn com.millennialmedia.**
# MINTEGRAL
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.mbridge.** {*; }
-keep interface com.mbridge.** {*; }
-keep interface androidx.** { *; }
-keep class androidx.** { *; }
-keep public class * extends androidx.** { *; }
-dontwarn com.mbridge.**
-keep class **.R$* { public static final int mbridge*; }
# MOBFOX
-dontwarn com.mobfox.**
-keep class com.mobfox.** { *; }
-keep class com.mobfox.adapter.** { *; }
-keep class com.mobfox.sdk.** { *; }
# MOPUB
-keepclassmembers class com.mopub.** { public *; }
-dontnote com.mopub.**
-dontwarn com.mopub.**
-keep public class com.mopub.**
-keep class com.mopub.mobileads.** { *; }
-keep class * extends com.mopub.mobileads.CustomEventBanner {}
-keep class * extends com.mopub.mobileads.CustomEventInterstitial {}
-keep class * extends com.mopub.nativeads.CustomEventNative {}
-keep class * extends com.mopub.nativeads.CustomEventRewardedAd {}
-keepclassmembers class ** { @com.mopub.common.util.ReflectionTarget *; }
-keepclassmembers class com.integralads.avid.library.mopub.** { public *; }
-keep public class com.integralads.avid.library.mopub.**
-keepclassmembers class com.moat.analytics.mobile.mpub.** { public *; }
-keep public class com.moat.analytics.mobile.mpub.**
-keep class com.google.android.gms.common.GooglePlayServicesUtil { *; }
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient { *; }
-keep class com.google.android.gms.ads.identifier.AdvertisingIdClient$Info { *; }
-keep class * extends java.util.ListResourceBundle { protected Object[][] getContents(); }
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { public static final *** NULL; }
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * { @com.google.android.gms.common.annotation.KeepName *; }
-keepnames class * implements android.os.Parcelable { public static final ** CREATOR; }
-keep public class android.webkit.JavascriptInterface {}
# MYTARGET
-keep class com.my.target.** {*;}
# NEND
-keep class net.nend.android.** { *; }
-dontwarn net.nend.android.**
# NATIVEX
-dontwarn com.nativex.**
-keep class com.nativex.** { *; }
# OGURY
-dontwarn com.ogury.**
-keep class com.ogury.** { *; }
# OUTBID
-dontwarn outbid.com.outbidsdk.**
-keep class outbid.com.outbidsdk.** { *; }
# QUMPARA
-dontwarn com.qumpara.analytics.**
-keep class com.qumpara.analytics.** { *; }
-dontwarn com.qumpara.offerwall.sdk.**
-keep class com.qumpara.offerwall.sdk.** { *; }
#POLLFISH
-dontwarn com.pollfish.**
-keep class com.pollfish.** { *; }
# PUBNATIVE
-keepattributes Signature
-keep class net.pubnative.** { *; }
-dontwarn net.pubnative.**
-keep class com.squareup.picasso.** { *; }
-dontwarn com.squareup.picasso.**
# REVMOB
-dontwarn rm.com.android.sdk.**
-keep class rm.com.android.sdk.** { public *; }
# RETROFIT
-dontwarn retrofit2.**
-keep class retrofit2.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keepclasseswithmembers class * {
@retrofit2.http.* <methods>;
}
# SMAATO
-dontwarn com.smaato.**
-keep class com.smaato.** { public *; }
-assumenosideeffects class android.util.Log {
public static *** d(...);
public static *** v(...);
public static *** i(...);
}
-keep public class com.smaato.soma.internal.connector.OrmmaBridge { public *; }
-keepattributes *Annotation*
-dontwarn com.smaato.soma.SomaUnityPlugin*
-dontwarn com.millennialmedia**
-dontwarn com.facebook.**
# SMARTAD
-keep class com.smartadserver.** { *; }
-dontwarn com.smartadserver.**
# STARTAPP
-keepattributes Exceptions, InnerClasses, Signature, Deprecated, SourceFile, LineNumberTable, *Annotation*, EnclosingMethod
-dontwarn android.webkit.JavascriptInterface
-keep class com.startapp.** { *; }
-dontwarn com.startapp.**
# TAPJOY
-keep class com.tapjoy.** {*;}
-keep class com.moat.** {*;}
-keepattributes JavascriptInterface
-keepattributes *Annotation*
-keep class * extends java.util.ListResourceBundle {protected Object[][] getContents();}
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable {public static final *** NULL;}
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * {@com.google.android.gms.common.annotation.KeepName *;}
-keepnames class * implements android.os.Parcelable {public static final ** CREATOR;}
-keep class com.google.android.gms.ads.identifier.** {*;}
-dontwarn com.tapjoy.**
# TAPPX
-keepattributes *Annotation*
-keepclassmembers class com.google.**.R$* { public static <fields>; }
-keep public class com.google.ads.** {*;}
-keep public class com.google.android.gms.** {*;}
-keep public class com.tappx.** { *; }
-dontwarn com.tappx.**
#PANGLE
-dontwarn com.bytedance.**
-keep class com.bytedance.** {*;}
# UNITY
-dontwarn com.unity3d.**
-keep class com.unity3d.ads.** { *; }
# Vungle
-dontwarn com.vungle.**
-dontnote com.vungle.**
-keep class com.vungle.** { *; }
-dontwarn com.vungle.warren.error.VungleError$ErrorCode
-keep class com.moat.** { *; }
-dontwarn com.moat.**
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement
-dontwarn okio.**
-dontwarn retrofit2.Platform$Java8
-keepattributes Signature
-keepattributes InnerClasses
-keepattributes *Annotation*
-dontwarn sun.misc.**
-keep class com.google.gson.examples.android.model.** { *; }
-keep class * implements com.google.gson.TypeAdapterFactory
-keep class * implements com.google.gson.JsonSerializer
-keep class * implements com.google.gson.JsonDeserializer
-keep class com.google.android.gms.internal.** { *; }
-dontwarn com.google.android.gms.ads.identifier.**
-keepclassmembers enum com.vungle.warren.** { *; }
-dontwarn kotlin.Unit
-dontwarn retrofit2.-KotlinExtensions
-keepclassmembers,allowshrinking,allowobfuscation interface * {
@retrofit2.http.* <methods>;
}
-dontwarn okhttp3.**
-dontwarn javax.annotation.**
-dontwarn org.conscrypt.**
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
-keepclassmembers class * extends com.vungle.warren.persistence.Memorable {
public <init>(byte[]);
}
#YANDEX
-dontwarn com.yandex.**
-keep class com.yandex.** { *; }
# YOUAPPI
-keep class com.google.gson.**{ *;}
-keep class com.google.android.gms.**{*;}
-keep class com.youappi.sdk.**{*;}
-keep interface com.youappi.sdk.**{*;}
-keep enum com.youappi.sdk.**{*;}
-keepclassmembers class * {
@android.webkit.JavascriptInterface <methods>;
}
# VERIZON
-keepclassmembers class com.verizon.ads** {
public *;
}
-keep class com.verizon.ads**
# ADMOST
-keepattributes Exceptions, InnerClasses
-dontwarn admost.sdk.**
-keep class admost.sdk.** {*;}
-dontwarn com.amr.unity.**
-keep class com.amr.unity.** {*;}
-dontwarn admost.adserver.**
-keep class com.adjust.sdk.** {*;}
-dontwarn com.adjust.sdk.**
-keep class com.appsflyer.** {*;}
-dontwarn com.appsflyer.**
-keep class admost.adserver.** { *; }
-dontwarn com.google.android.exoplayer2.**
-keep class com.google.android.exoplayer2.**{ *;}
-keep class android.support.v4.app.DialogFragment { *; }
-keep class android.support.v4.util.LruCache { *; }
# ADMOB / ADX / GOOGLE
-keep class com.android.vending.billing.**
-keep public class com.google.android.gms.ads.** { public *; }
-keep public class com.google.ads.** { public *; }
-keep class com.google.android.gms.** { *; }
-dontwarn com.google.android.gms.**
-keep public class com.google.android.gms.common.internal.safeparcel.SafeParcelable { public static final *** NULL; }
-keepnames class * implements android.os.Parcelable
-keepclassmembers class * implements android.os.Parcelable { public static final *** CREATOR; }
-keep @interface android.support.annotation.Keep
-keep @android.support.annotation.Keep class *
-keepclasseswithmembers class * { @android.support.annotation.Keep <fields>; }
-keepclasseswithmembers class * { @android.support.annotation.Keep <methods>; }
-keep @interface com.google.android.gms.common.annotation.KeepName
-keepnames @com.google.android.gms.common.annotation.KeepName class *
-keepclassmembernames class * { @com.google.android.gms.common.annotation.KeepName *; }
-keep @interface com.google.android.gms.common.util.DynamiteApi
-keep public @com.google.android.gms.common.util.DynamiteApi class * { public <fields>; public <methods>; }
-keep public @com.google.android.gms.common.util.DynamiteApi class * { *; }
-keep class com.google.android.apps.common.proguard.UsedBy*
-keep @com.google.android.apps.common.proguard.UsedBy* class *
-keepclassmembers class * { @com.google.android.apps.common.proguard.UsedBy* *; }
-dontwarn android.security.NetworkSecurityPolicy
-dontwarn android.app.Notification
# FACEBOOK
-dontwarn com.facebook.ads.**
-dontnote com.facebook.ads.**
-keep class com.facebook.** { *; }
-keepattributes Signature
-keep class com.google.android.exoplayer2.** {*;}
-dontwarn com.google.android.exoplayer2.**
# MINTEGRAL
-keepattributes Signature
-keepattributes *Annotation*
-keep class com.mbridge.** {*; }
-keep interface com.mbridge.** {*; }
-keep interface androidx.** { *; }
-keep class androidx.** { *; }
-keep public class * extends androidx.** { *; }
-dontwarn com.mbridge.**
#PANGLE
-dontwarn com.bytedance.**
-keep class com.bytedance.** {*;}
-keep class **.R$* { public static final int mbridge*; }
Usage
Initialization
To initialize Admost Mediation SDK, import
'package:admost_flutter_plugin/admost.dart';
to your file;
import 'package:admost_flutter_plugin/admost.dart';
and initialize AMRSDK with Admost.initialize()
Admost.initialize(
appId: Platform.isIOS
? "15066ddc-9c18-492c-8185-bea7e4c7f88c"
: "6cc8e89a-b52a-4e9a-bb8c-579f7ec538fe",
userConsent: "<your_userConsent_value>",
subjectToGDPR: "<your_subjectToGDPR_value>",
subjectToCCPA: "<your_subjectToCCPA_value>");
}
For testing you can use following Application Id;
IOS Application Id: "15066ddc-9c18-492c-8185-bea7e4c7f88c"
Android Application Id: "6cc8e89a-b52a-4e9a-bb8c-579f7ec538fe"
GDPR and CCPA
Once you have collected the user’s consent, you can pass it onto the SDK using the init configuration parameters shown above.
userConsent
has a boolean parameter. If you have the user’s consent, set
it YES. If you do not have the user's consent, set it NO.
subjectToGDPR
has a boolean parameter. If you know the user is subject
to GDPR, set it YES. If you know the user is not subject to GDPR, set it NO.
subjectToCCPA
has a boolean parameter. If you know the user is subject
to CCPA, set it YES. If you know the user is not subject to CCPA, set it NO.
If you don’t pass the user’s consent or subjectToGDPR to the SDK, the rules described in GDPR have been applied.
If you don’t pass the user’s consent or subjectToCCPA to the SDK, the rules described in CCPA have been applied.
Banner Ads
Important
Default banner size changed from Fullscreen width to 320x50, 728x90 and
300x250.
If you are using 320x90 banner, please contact with your account manager.
There are 3 types of banner size; 320x50, 728x90 and 300x250 banner.
To create and show a banner ad first import
'package:admost_flutter_plugin/admost_banner.dart';
and
'package:admost_flutter_plugin/admost_banner_size.dart';
to your
file
Also if you want handle ad events, import
'package:admost_flutter_plugin/admost_ad_events.dart';
// main.dart
import 'package:admost_flutter_plugin/admost_banner.dart';
import 'package:admost_flutter_plugin/admost_banner_size.dart';
import 'package:admost_flutter_plugin/admost_ad_events.dart'
Then declare your banner with AdmostBanner
and handle ad events with
listener:
AdmostBanner(
adUnitId: Platform.isIOS
? "b4009772-de04-42c4-bbaa-c18da9e4a1ab"
: '9fb970db-7d96-4ef2-ac8c-d88ec22270ff',
adSize: AdmostBannerSize.LEADERBOARD,
listener: (AdmostAdEvent event, Map args) {
if (event == AdmostAdEvent.loaded) {
// It indicates that the banner ad is loaded.
}
if (event == AdmostAdEvent.clicked) {
// It indicates that the banner ad is clicked.
}
if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the banner ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
},
)
For testing you can use following Banner Zone Id;
IOS Banner Zone Id: "b4009772-de04-42c4-bbaa-c18da9e4a1ab"
Android Banner Zone Id: "9fb970db-7d96-4ef2-ac8c-d88ec22270ff"
Optionally you can set the width of the banner, default value is 320px for 50px banner, 728px for 90px banner, 300px for 250px banner.
AdmostBanner(
.
.
adSize: AdmostBannerSize(width:<width>,height:<height>,name:<"SizeName">),
listener: ..,
)
There are 3 event in AdmostBanner
AdmostBanner(
...
listener: (AdmostAdEvent event, Map args) {
if (event == AdmostAdEvent.loaded) {
// It indicates that the banner ad is loaded.
}
if (event == AdmostAdEvent.clicked) {
// It indicates that the banner ad is clicked.
}
if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the banner ad received no-fill response from all of its placements.
}
},
)
loaded
state is returned when banner received.
if (event == AdmostAdEvent.loaded) {
// It indicates that the Banner ad is loaded.
}
clicked
state is returned when banner clicked.
if (event == AdmostAdEvent.clicked) {
// It indicates that the banner ad is clicked.
}
If failedToLoad
state is returned investigate error to adress the
problem.
if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the banner ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
Customize Native Ad Appearance (Optional)
You can change the appearance of native ads to suit your application's design.
To create and show a native ad you need import
'package:admost_flutter_plugin/admost_native_ad.dart';
to your
file
import 'package:admost_flutter_plugin/admost_native_ad.dart';
IOS Native Ad
To add native ads on IOS , download the CustomXibs.zip file and
extract in <your project>/ios/Runner
path.
You can change the layout and design of following assets;
If you want to use your own layouts you can create a copy and modify one of the custom sized samples (CustomNative150x250.xib, CustomNative200x200.xib or CustomNative300x120.xib) and change their frame to fit your design.
After creating your native xib file on the iOS side, then declare
your banner with AdmostNativeAd
.
You must pass the xibNameForIOS:
parameter.
xibNameForIOS: 'AMRNativeAdBaseView250',
AdmostNativeAd(
adUnitId: Platform.isIOS
? 'c72a4a52-23c5-4c34-9eb1-7bbc4c08c7e4'
: 'f3915393-7f42-4b9d-97c3-e7d4017c7591',
adSize: AdmostBannerSize(width:200,height:200,name:"AMRNativeAdBaseView250"),
xibNameForIOS: 'AMRNativeAdBaseView250',
listener: (AdmostAdEvent event, Map args) {
if (event == AdmostAdEvent.loaded) {
// It indicates that the banner ad is loaded.
}
if (event == AdmostAdEvent.clicked) {
// It indicates that the banner ad is clicked.
}
if (event == AdmostAdEvent.failedToLoad) {
// Ad is not loaded and can not be shown.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
},
)
Android Native Ad
For Android, you can follow the following steps;
- Define a layout file in the android layout folder for your custom native design
- Create a AdMostViewBinder object in the MainActivity and assign this object as the static native binder
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="120dp"
android:background="@android:color/white"
android:orientation="horizontal">
<ImageView
android:id="@+id/admost_flutter_back_image"
android:layout_width="145dp"
android:layout_marginLeft="5dp"
android:adjustViewBounds="true"
android:layout_gravity="left|center"
android:layout_height="wrap_content"
android:scaleType="fitXY"
android:visibility="gone"/>
<ImageView
android:id="@+id/admost_flutter_main_image"
android:layout_width="145dp"
android:layout_marginLeft="5dp"
android:adjustViewBounds="true"
android:layout_gravity="left|center"
android:layout_height="wrap_content"
android:scaleType="fitXY" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="5dp"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_marginTop="0dp">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|left"
android:layout_marginLeft="10dp"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/admost_flutter_icon"
android:layout_width="14dp"
android:layout_height="14dp"
android:layout_marginRight="4dp"
android:layout_marginTop="6dp"
android:background="@null"
android:scaleType="fitXY" />
<TextView
android:id="@+id/admost_flutter_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:layout_marginRight="15dp"
android:maxLines="1"
android:layout_marginTop="5dp"
android:gravity="center_vertical"
android:text="Title"
android:textColor="#ff000000"
android:textSize="14sp" />
</LinearLayout>
<TextView
android:id="@+id/admost_flutter_attribution"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical|right"
android:layout_marginTop="30dp"
android:layout_marginLeft="10dp"
android:text="Ad"
android:textColor="#ffacabab"
android:textSize="12sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="35dp"
android:layout_marginLeft="10dp"
android:orientation="vertical">
<TextView
android:id="@+id/admost_flutter_detail"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="10dp"
android:layout_marginTop="5dp"
android:ellipsize="end"
android:lineSpacingExtra="3dp"
android:maxLines="2"
android:paddingBottom="5dp"
android:paddingTop="8dp"
android:text="Title Lorem ipsom dolor sit amet consaposod elit"
android:textColor="#cc2a2e32"
android:textSize="12sp"/>
<Button
android:id="@+id/admost_flutter_cta"
android:layout_width="match_parent"
android:layout_height="36dp"
android:layout_marginBottom="12dp"
android:layout_marginTop="-10dp"
android:layout_gravity="center"
android:gravity="center"
android:text="Go"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="@android:color/black"/>
</LinearLayout>
<LinearLayout
android:id="@+id/admost_flutter_ad_choices"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:gravity="right"
android:orientation="vertical"/>
</RelativeLayout>
</LinearLayout>
val binder: AdMostViewBinder = admost.sdk.AdMostViewBinder.Builder(R.layout.custom_layout_flutter)
.iconImageId(R.id.cardIcon)
.titleId(R.id.cardTitle)
.callToActionId(R.id.CallToActionTextView)
.textId(R.id.cardDetailText)
.attributionId(R.id.cardAttribution)
.mainImageId(R.id.cardImage)
.backImageId(R.id.cardBack)
.privacyIconId(R.id.ad_choices)
.isRoundedMode(true)
.build()
AdmostFLTNativeAdBinder.getInstance().binder = binder;
Interstitial Ads
To create and show an interstitial ad first import
'package:admost_flutter_plugin/admost_interstitial.dart';
to your
file and declare an AdmostInterstitial
object;
import 'package:admost_flutter_plugin/admost.dart';
import 'package:admost_flutter_plugin/admost_interstitial.dart';
.
.
class _MyHomePageState extends State<MyHomePage> {
String interstitialText = 'Load Interstitial';
AdmostInterstitial interstitialAd;
.
.
.
if (interstitialAd == null) {
interstitialAd = AdmostInterstitial(
zoneId: Platform.isIOS
? '39f74377-5682-436a-9338-9d1c4df410bd'
: 'f99e409b-f9ab-4a2e-aa9a-4d143e6809ae',
listener:...
}
if (await interstitialAd.isLoaded) {
interstitialAd.show();
} else {
interstitialAd.load();
}
.
.
.
}
For testing you can use following Interstitial Zone Id;
IOS Interstitial Zone Id: "39f74377-5682-436a-9338-9d1c4df410bd"
Android Interstitial Zone Id: "f99e409b-f9ab-4a2e-aa9a-4d143e6809ae"
There are 6 state in AdmostInterstitial
.
AdmostInterstitial(
zoneId: Platform.isIOS
? '39f74377-5682-436a-9338-9d1c4df410bd'
: 'f99e409b-f9ab-4a2e-aa9a-4d143e6809ae',
listener: (AdmostAdEvent event, Map args) {
if (event == AdmostAdEvent.loaded) {
// It indicates that the interstitial ad is loaded and ready to show.
print("Interstitial network: ${args['network']}");
print("Interstitial ecpm: ${args['ecpm']}");
}
if (event == AdmostAdEvent.opened) {
// It indicates that the interstitial ad is showed.
}
if (event == AdmostAdEvent.clicked) {
// It indicates that the interstitial ad is clicked.
}
if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the interstitial ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
if (event == AdmostAdEvent.failedToShow) {
// Indicates that the interstitial ad was received but there was a problem while it was showing.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
if (event == AdmostAdEvent.dismissed) {
// It indicates that the interstitial ad is dismissed.
}
},
);
When isLoaded
is true
just call the .show()
method to present interstitial.
if (await interstitialAd.isLoaded) {
interstitialAd.show();
} else {
interstitialAd.load();
}
If failedToLoad
state is returned investigate error
to
adress the problem.
Important Attempting to load a new
interstitial from the
failedToLoad
methods is strongly discouraged.
if (event == AdmostAdEvent.failedToLoad) {
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
failedToShow
event state is returned to inform the application that the
received interstitial failed to be shown.
This delegate expected to be returned very rarely but if it is returned you should
either load another interstitial or resume tasks.
if (event == AdmostAdEvent.failedToShow) {
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
opened
state is returned to inform the application that the received
interstital is shown.
if (event == AdmostAdEvent.opened) {
// It indicates that the interstitial ad is showed.
}
clicked
state is returned when interstital clicked.
if (event == AdmostAdEvent.clicked) {
// Interstitial Ad clicked.
print("Network: ${args['network']}");
}
dismissed
state is returned to inform the application that the
interstitial is closed by clicking cross button/back button. You can use this
callback to resume paused tasks during
interstitial presentation.
You can use dismissed
callback and reload a interstitial ad.
if (event == AdmostAdEvent.dismissed) {
// Interstitial Ad dismissed.
}
Rewarded Video Ads
Rewarded video ads integration is pretty similar to Interstitial ads with 2
additional event. To create and show a rewarded video ad
first import
'package:admost_flutter_plugin/admost_rewarded.dart'
to your file and
declare an AdmostRewarded
property;
import 'package:admost_flutter_plugin/admost.dart';
import 'package:admost_flutter_plugin/admost_rewarded.dart';
.
.
class _MyHomePageState extends State<MyHomePage> {
String rewardedText = 'Load Rewarded';
AdmostRewarded rewardAd;
.
.
.
if (rewardAd == null) {
rewardAd = AdmostRewarded(
zoneId: Platform.isIOS
? '2bdefd44-5269-4cbc-b93a-373b74a2f067'
: '88cfcfd0-2f8c-4aba-9f36-cc0ac99ab140',
listener: (AdmostAdEvent event, Map<String, dynamic>args) {
if (event == AdmostAdEvent.loaded) {
rewardedText = 'Show Rewarded';
setState(() {
rewardedText;
});
} else if (event == AdmostAdEvent.dismissed) {
rewardedText = 'Load Rewarded';
setState(() {
rewardedText;
});
} else if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the interstitial ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
} else if (event == AdmostAdEvent.completed) {
// It indicates that the user deserves to receive a reward. You may need to store this information in a variable and give a reward
}
},
);
}
if (await rewardAd.isLoaded) {
rewardAd.show();
} else {
rewardAd.load();
}
.
.
.
}
For testing you can use following RewardedVideo Zone Id;
IOS RewardedVideo Zone Id: "2bdefd44-5269-4cbc-b93a-373b74a2f067"
Android RewardedVideo Zone Id: "88cfcfd0-2f8c-4aba-9f36-cc0ac99ab140"
There are 7 event methods in AdmostRewarded
.
AdmostRewarded(
zoneId: Platform.isIOS
? '2bdefd44-5269-4cbc-b93a-373b74a2f067'
: '88cfcfd0-2f8c-4aba-9f36-cc0ac99ab140',
listener: (AdmostAdEvent event, Map args) {
if (event == AdmostAdEvent.loaded) {
print("Rewarded network: ${args['network']}");
print("Rewarded ecpm: ${args['ecpm']}");
} else if (event == AdmostAdEvent.dismissed) {
// It indicates that the rewarded ad is dismissed.
} else if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the rewarded ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
} else if (event == AdmostAdEvent.failedToShow) {
// Indicates that the rewarded ad was received but there was a problem while it was showing.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
} else if (event == AdmostAdEvent.clicked) {
// It indicates that the rewarded ad clicked.
} else if (event == AdmostAdEvent.opened) {
// It indicates that the rewarded ad is showed.
} else if (event == AdmostAdEvent.completed) {
// It indicates that the user deserves to receive a reward. You may need to store this information in a variable and give a reward
}
},
);
When isLoaded
is true
just call the .show()
method to present rewarded video.
if (await rewardAd.isLoaded) {
rewardAd.show();
} else {
rewardAd.load();
}
If failedToLoad
state is returned investigate error
to
adress the problem.
Important Attempting to load a new rewarded
video from the
failedToLoad
methods is strongly discouraged.
if (event == AdmostAdEvent.failedToLoad) {
// It indicates that the rewarded ad received no-fill response from all of its placements.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
opened
state is returned to inform the application that the received
rewarded video is shown.
if (event == AdmostAdEvent.opened) {
// It indicates that the rewarded ad is showed.
}
failedToShow
event state is returned to inform the application that the
received rewarded video failed to be shown.
This delegate expected to be returned very rarely but if it is returned you should
either load another reward video or resume tasks.
if (event == AdmostAdEvent.failedToShow) {
// Indicates that the rewarded ad was received but there was a problem while it was showing.
print("Error code: ${args['errorCode']}");
print("Error message: ${args['errorMessage']}");
}
clicked
state is returned when rewarded video clicked.
if (event == AdmostAdEvent.clicked) {
// It indicates that the rewarded ad clicked.
print("Network: ${args['network']}");
}
completed
state is returned to inform the application that the user
completed watching the video to a certain point to get the reward. The
video may have finished or keep playing after completed
is returned.
Use this state to reward the user.
Important Attempting to load a new rewarded
video from the
completed
states is strongly discouraged.
if (event == AdmostAdEvent.completed) {
// It indicates that the user deserves to receive a reward. You may need to store this information in a variable and give a reward
player.reward();
}
dismissed
state is returned to inform the application that the
rewarded video is closed by clicking cross button/back button. You can use this
state to resume paused tasks during
rewarded video presentation.
You can use dismissed
state and reload a new rewarded video ad.
if (event == AdmostAdEvent.dismissed) {
animation.resume();
}
Extras
Test Suite
You can use Test Suite to test your ad networks with your zone ids.
You must be a Tester to show Test Suite on devices.
To use Test Suite in your application, you can use one of the following codes;
Admost.startTestSuite(Platform.isIOS
? "15066ddc-9c18-492c-8185-bea7e4c7f88c"
: "6cc8e89a-b52a-4e9a-bb8c-579f7ec538fe");
In App Purchase Tracking
IAP IOS
The following method is used to track purchases with receipt validation in ios:
Admost.trackIAPForIOS(transactionId, currency, amount, ['tag1', 'tag2']);
Explanation of Parameters:
- transactionId – Transaction identifier of SKPaymentTransaction.
- currencyCode – Currency code of transaction.
- amount – Amount of transaction.
- tags – You can use to analyze and differentiate the purchases.
IAP Android
The following method is used to track purchases with receipt validation in android:
Admost.trackIAPForAndroid(originalJSON, signature, currency, amount, ['tag1', 'tag2'])
Explanation and code samples of parameters:
- originalJSON – a String in JSON format that contains details about the purchase order. It is returned by the operating system after you make the purchase call.
- signature – String containing the signature of the purchase data that the developer signed with their private key. It is returned by the operating system after you make the purchase call.
- currency – Currency code of transaction.
- amount – Amount of transaction.
- tags – You can use the purchases to be analyzed and differentiated.
Setting Application User Id
You can use the following method to set application specific user id in Admost Analytics for enhanced tracking of your users. You should to call this method before initialization.
Admost.setUserId("applicationUserId");
Adjust Integration
Follow the official ADJUST documents to integrate AdjustSDK in to your app.
AppsFlyer Integration
Follow the official APPSFLYER documents to integrate AppsFlyerSDK in to your app.
Privacy Consent Required
You can optionally use isPrivacyConsentRequired property to obtain the user is in a GDPR or CCPA required country.
var privacyConsentStatus = await Admost.isPrivacyConsentRequired;
Apple App Privacy (IOS Only)
Starting December 8, 2020, Apple has announced a privacy disclosure for the App Store, You must define which data are collected by your apps and any SDKs you have integrated. To improve the performance of AdMost, the AMRSDK may collect following information from your apps:
- User ID – If you are using
setUserId
method to identify users with your custom app user ID, you will need to select 'User ID' - Purchases – If you are using in app purchase trackings methods, you will need to select 'Purchases'
- Coarse Location – To estimate the general location of a device
- Product Interaction – Analytics purposes
- Advertising Data – Analytics purposes