Publisher Android

Managing the size of the Flurry SDK on Android

When building large Android apps, there are two different aspects of an Android libraries size that might be of a concern.

The first, and least common, is the disk space/memory the library would occupy, measured in bytes.

The second, and more common, is the number of methods the library contains.

With regards to the Flurry SDK, the first issue is not a problem because the entire Flurry ads and analytics SDK only adds about 300 KB to an app, which is minuscule given the high availability of disk space and memory on devices today. The second issue is a more common developer complaint when they have an already large app that is relying on multiple libraries to function. With an app already using multiple libraries, adding any more library functionality could get difficult on Android.

On Android, the platform’s build architecture creates .dex files from an application that the platform’s runtime can execute. These .dex files have a limit on the number of methods that it can contain. By default, each app will have one .dex file and each .dex file can only contain about 65K methods. However, when a developer’s app starts depending on a lot of libraries, it can be very easy to go beyond that 65K method limit, resulting in an error like the following when the app is built:

Conversion to Dalvik format failed: Unable to execute dex: method ID not in [0, 0xffff]: 65536

...or on newer platforms:

trouble writing output: Too many field references: 131000; max is 65536. You may try using –multi-dex option.

Consider that the Flurry SDK alone adds 5K methods for the ads API and ~2K methods for the analytics and Tumblr API as of version 6.0.0. This means that including the Flurry SDK will take ~10% of a developer’s allowed method count. Including other libraries and the application’s own code, it is possible to see how a developer can easily approach the 65K method limit, especially when they include the entire Google Play Services library, which currently has over 20K methods.

There are several ways to overcome this limit. Each of the ways listed below are also available when using the Flurry SDK.

Remove unused code or selectively compile Google Play Services

Many large applications easily suffer from having leftover legacy code. This legacy code could add to the method count of apps and removing them would reduce not just the app’s method count, but also its build time.

Legacy code is not the only code that could be unused in an app, however. Sometimes, developers may include library dependencies that their app does not really need. This could be as a result of oversight or using a boilerplate template to build the apps. One large culprit of an unused library dependency is Google Play Services (GPS). As mentioned above, GPS can easily add over 20K methods to your app.

On Android Studio, developers now have the option of only including the parts of GPS that they need, instead of including the entire 20K methods. To do that, they can modify their build.gradle file.

Assuming they had the following build.gradle snippet:

dependencies {
compile ‘com.google.android.gms:play-services:7.5.0’

}

This would include the entire GPS library. Instead, they can break down the snippet to include only parts that they need:

dependencies {
compile ‘com.google.android.gms:play-services-analytics:7.5.0’ compile ‘com.google.android.gms:play-services-ads:7.5.0’ compile ‘com.google.android.gms:play-services-maps:7.5.0’

}

The methods described above are not a fireproof solution. There are two drawbacks:

You need to be using Gradle or Android Studio to be able to selectively compile GPS. Apps built with Eclipse without Gradle cannot do this. This method assumes that it is the unused code that is taking the app over the DEX method limit. It is possible to have only code that is used, but still go over the method limit.

Using ProGuard

ProGuard allows you minimize your application by removing unused or unreferenced code during the build process. In this case, ProGuard is doing the same thing described in the previous method, but automatically. When building Android apps, ProGuard is not enabled by default, so enabling ProGuard, the app developer may be able to go below the method limit.

There are some drawbacks to ProGuard:

ProGuard will only reduce the method count based on the amount of code used in the app. It only attempts to remove unused code. If the app does use a lot of code and dependencies it has, ProGuard may not be able to go below the DEX limit. ProGuard may sometimes remove code that is used. In this case, the developer will need to configure ProGuard to specify what parts of code is used.

Multidexing

As mentioned earlier, each Android app contains one executable .dex file by default. Multidexing allows you split an app to contain multiple .dex files, with each file having its own method limit.

This method is the only guaranteed way to go below the limit and should be the default recommendation to Flurry app developers. Configuration for multidexing is easy on Maven or Gradle build supported systems like Android Studio.

However, multidexing will not work for every app. Here are some drawbacks:

Only works for IDEs or build systems that use Maven or Gradle, like Android Studio or IntelliJ. Eclipse is not supported. Applications that target Android APIs lower than version 14 will need to specifically test their apps with API 14 or less as multidexing could cause the app to not start or crash during startup on those levels. Using multiple .dex files may slow down an application’s startup time. Not all libraries may allow multidexing. The Flurry SDK allows multidexing, but other included libraries that use native code or invocation may not easily allow for multidexing. This case is rare, but may arise in some cases where the developer is using Java libraries not built for Android.

Dynamic Class Loading or using DexClassLoader

This is the most complicated of all the listed methods and it requires that the developer have a separate .dex file for different libraries that do not add to their own app’s .dex file. The library .dex files can then be loaded dynamically, while the app is running. Because the libraries are not included at build time, the app will then need to use reflection to access the libraries’ APIs.

Due to the complexity and brittleness of this method, this method is discouraged for Flurry app developers, but it is allowed by the Flurry SDK.

The disadvantages of this method are:

Complexity in setting up. Because the app will need to use reflection at runtime to access library APIs, the app would be very brittle. If there is an update to a library, there is no way to know how any API changes will affect the app when building the app. The developer will have to go through the app documentation and change their reflection implementation to fit with the new APIs.

Overall, the size of the Flurry SDK should not be a problem to most modern apps as there are several easy solutions to overcome the DEX method limit. The recommendation to Flurry app developers should be to start by using ProGuard and removing unused code and dependencies. If that doesn’t put the app under the limit, Multidexing will work for most setups. Dynamic class loading should only be used in rare cases.

ssl support

As of Flurry Android SDK 5.3, the ssl is the default transport mechanism and setSecureTransportEnabled method has been removed as no longer necessary.

Does Flurry support Android Advertising Id?

With the release of 4.0.0 version Flurry Advertising uses the Android Advertising ID provided by Google Play Services. The SDK will check for and respect the user’s ad tracking preference.

The google-play-services_lib needs to be a referenced library when building a project with FlurryAds_5.x.x.jar. For more information on Android Advertising ID please follow this link

No Ads served: I have followed your integration instructions, but see no ads in my app.

A couple of quick pointers on how to troubleshoot the lack of ads:

  • Verify the ad space name in your code is the same capitalization as the ad space configured on the dev.flurry.com

  • Check the ad space placement is defined to be either Stream, Full Screen, Banner Top or Banner Bottom. If you originally created your ad space from the app, the placement would not be declared - it would say Undetermined Placement. On the flurry dev portal go to Publishers tab, on the left hand navigation bar select Inventory / Ad Spaces, and select the ad space in question. In the section Basic Setup select the placement that represents your ad space the best.

  • Check the ad space configured to serve ads. On the flurry dev portal go to Publishers tab, on the left hand navigation bar select Inventory / Ad Spaces, and select the ad space in question. In the section Advanced Options / Ad Source Settings make sure that Gemini Video Backfill, Flurry Marketplace Fill, or both is set to On to assure Flurry is sending you ads. The above settings are relevant for the Banner and Full Screen placements. The Stream placements do not require any additional configuration, they are On by default.

  • Turn the flurry logging on in you app and observe the logcat for the FlurryAgent statements.

    When integrating banners, interstittials or native ad spaces, look at the callbacks that FlurryAdBannerListener, FlurryAdInterstitialListener or FlurryAdNativeListner respectively, return upon calling fetchAd on the ad object. Each of the three delegates returns the adequately named version of the onError callback. Namely:

Each error callback provides the FlurryAdErrorType and the errorCode that you can look into to understand the cause for the failure to receive the ad object.

The external error codes that can be returned to your app are as follows:

Error code Error summary Error description
1 No network connectivity There is no internet connection
2 Missing ad controller Occurs when ad has not been prepared
3 No context A valid context is missing
4 Invalid ad unit The ad unit that is used is invalid.
17 Ad not ready Triggered when you call displayAd() on an ad object that is not ready
18 Wrong orientation Device is in wrong orientation for banner or interstitial ads
19 No view group Banner ad wasn’t placed in a ViewGroup
20 Ad was unfilled Ad was unfilled by server. Could be due to incorrect ad request, incorrect ad space configuration or no fill at request location at the moment
21 Incorrect class for ad space Ad request made with incorrect class for corresponding ad space
22 Device locked Device is locked during ad request

Similarly each delegate fires a callback in case the ad object is received:

  • If you are working with FlurryAdBanner object, and the onFetched callback is received, but the ad is not displayed, check your layout to see if the vievGroup paramter as provided when creating the FlurryAdBanner(Context context, ViewGroup viewGroup, String adSpace) object is incorporated into the layout.

FlurryAds: No ads available from server for this space.

There are few reasons for this error, some are temporary some are reflection on geographical availability of Flurry ads. You can (temporarily) set your ad space into the test mode to see if the ads appear. The test mode is available for Gemini ads only. The ads served from the RTB marketplace are not available in the test mode.

Please do remember to turn the test mode off prior to submitting your app to the Play Store.

Can I place a banner in a custom placement instead of top or bottom of the screen?

Yes. The banner’s position on the screen is by default on the top or bottom of the screen. The the vievGroup paramter as provided when creating the FlurryAdBanner(Context context, ViewGroup viewGroup, String adSpace) object is incorporated into the layout of the activity determines its actual location.

Alternatively consider integrating native ad objects instead of the banner ones for the ability to place them anywhere in the layout and for the ability to have a custom look that reflects the look of your application.

How does my app know if an ad is available ?

For each fetchAd called on an object, its respective listener (FlurryAdBannerListener, FlurryAdInterstitialListener or FlurryAdNativeListner ) returns either onFetched or onError callback. In case onFetched is returned, the ad object is the parameter of this callback.

We recommend calling isReady() on the ad object to verify if the ad is ready prior to displaying it.

onVideoCompleted delegate is not called

void onVideoCompleted(FlurryAdInterstitial adInterstitial) listener callback method will be called when a video finishes playing to inform the app that a video associated with an ad has finished playing.

This method is invoked for Rewarded full screen takeover ad spaces only (this includes the following ad mix options: Rewarded, Let Flurry Decide and Client­-side Rewarded). The ad space configured as Standard ad mix will not invoke this delegate. The ad space mix configuration is done on the server side, see further instructions: to integrate rewards into your app or to tie Flurry Rewards into your.

Can I control what ads show in an Ad Space?

You can filter out the ads from showing in your Ad Space by setting filters under the Filter Options. Filters are available for app store id, advertiser name and app name.

You can set up filters for a specific Ad Space and copy those settings to another ad space. Under Filter Options>Copy Filters, you will see a drop down on the right to select the Ad Space that you’d like to copy the filters from.

Ad Space Test mode

Setting an ad space into the test mode is meant to help you validate the integration. The test mode removes any content or geo filtering and delivers the ads into the ad space.

The test mode configuration can be done in two ways: in your application code or on the dev portal by a Flurry administrator.

The advantage of doing so in your application code is the immediate validation. However you need to **make sure to turn the test mode off (by removing the code or by explicitly setting the test mode to false / NO) before launching your app.

The advantage of setting the ad space into the test mode on the Flurry’s dev portal is that it can be turned on / off at any time (even when the application is live in production), however it has to be done by a Flurry administrator and it takes ~20 minutes for the configuration to take effect. To do so, please email support@flurry.com with your API key and the ad space name.

My game is in Unity, can I integrate Flurry ads into my game?

that are wraped around our latest SDKs to provide easy integration of Flurry features into a Unity game. app When using the Prime31 plugin, you still acquire API key from Flurry’s dev portal and refer back to it for all server side configuration of ad spaces and ad serving campaigns when applicable .

Reminders

Turn-off the test mode for all the ad spaces in you app prior to releasing it.