Solar2D: AdMob, Notification and FirebaseAnalytics plugin on iOS

created 13.10.2020


Introduction

If you have published a mobile game using Solar2D, you have almost sure used native plugins. They are essentially reusable modules that do use native code and libraries. Since those plugins are built, maintained and created by different people and organizations they may use the same native libraries but different versions. That may cause problems and this article is about how I did solve these problems in case of plugins that use Googles Firebase, namely plugin.notifications.v2, plugin.firebaseAnalytics and plugin.admob.

My app, Trashman Underwater has used a long time plugin.firebaseAnalytics and plugin.notifications.v2. So far the usage has happened more or less without problems but then I decided to update plugin.firebaseAnalytics and started to get compile time errors:

Undefined symbols for architecture armv7: "_OBJC_CLASS_$_GULKeychainStorage", referenced from: objc-class-ref in FirebaseInstallations(FIRInstallationsIDController.o)

I also planned to start to use plugin.admob. Therefore I decided to figure out what is going on.

AdMob plugin, FirebaseAnalytics plugin … and Notifications plugin

On forum, there has been discussion about the version incompatibility. I did also submit a bug report to scotth.tech once about incompatibility between plugin.admob and scotth.tech Firebase Analytics plugin. But I guess version conflicts are inevitable and t herefore I wanted to try to solve this in such a way that I can build my app with the dependencies I do want to use.

It is clear that without a bit of luck this is not possible since if native API has changed, plugin code cannot use it. In this article I have managed to build the game by just replacing native libraries and updating metadata.lua of the plugins

Sometimes that is not enough. And since I did not find good instructions I will probably will write another article how to build admob plugin from coronalabs github.

Back to the topic. I wanted to figure out the reason for those errors. Aargh. Just to make sure you get it: aargh.

I spent more than a day trying to figure out why I do get all the time those Undefined symbols errors. And finally realized that plugin.notifications.v2 uses Firebase as well. After that things started to progress smoothly. And in the end I had a working game with Firebase Analytics, AdMob and local notifications. I do not use at the moment push notifications so I do not know do they work or not.

Version Information

Below you will find all the steps I did. You need Mac computer to try them out and also you have to use terminal to complete them. But first some version information:

Development Computer: Mac OS X
Solar2D build: 2020.3620
plugin.notifications: downloaded 9.10.2020, data.tgz size 2026472 bytes
plugin.firebaseAnalytics: downloaded 9.10.2020 from scott.tech marketplace using url: https://solar2dmarketplace.com/marketplacePlugins?ID=MARKET_PLAC_ID&plugin=FirebaseAnalytics_tech-scotth&type=iOS, data.tgz size 16685007 bytes

Why? Because it is at the moment very difficult to figure what version of the plugin is in use. They, at least to my knowledge, do not have version information that user of the plugin would know. That is ok often but in case of problems makes it more difficult to figure out what is going on.

How can I know when the plugin was downloaded – doesn’t the simualtor cache these? Yes, but I simply removed the relevant directories from the cache under:

~/Solar2DPlugins/Caches/Solar2Directory/solar2d/com.solar2d

Why firebaseAnalytics is downloaded from url? At least my simulator downloaded a version with very different (smaller size). I hoped that the version I downloaded from the url would be newer. My guess is that this version downloaded from url uses version 6.32.0 of the Firebase libraries.

Documenting the sizes of the plugins gives me opportunity to at least know if the version is different compared to earlier version I have used.

Anyway. To step 1.

Step 1. Build an app with firebaseAnalytics and notifications plugins

So, I did replace data.tgz in ~/Solar2Directory/solar2d/tech.scotth/plugin.firebaseAnalytics/iphone with the new version downloaded from url.

And built for device using iOS 14.0 sdk. Boom. ”There was a problem linking the app.”:

Undefined symbols for architecture armv7: "_OBJC_CLASS_$_GULKeychainStorage", referenced from: objc-class-ref in FirebaseInstallations(FIRInstallationsIDController.o) "_OBJC_CLASS_$_GULKeychainUtils", referenced from: objc-class-ref in FirebaseInstallations(FIRInstallationsIIDTokenStore.o) ld: symbol(s) not found for architecture armv7

And then a lot of trying out different things before finally realising that the notifications plugin also uses Firebase.

Step 2. ”Fix” notifications plugin dependencies

I do write ”fix” since we actually do not want to add all the dependencies but just the dependencies that are needed and not alread included in the firebaseAnalytics plugin.

cd /Users/mfranssi/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.notifications.v2/iphone
open data.tgz
cd data
rm -rf resources/Frameworks/*

Let’s stop here. We just deleted three libraries from notifications framework. Surely it is not going to work!? Well, it will since those frameworks are already included in the firebaseAnalytics plugin. But yes – if you stop using that framework this solution is not for you.

What, I hear you asking again. The deleted frameworks were called FBLPromises.framework, GoogleUtilities.framework, protobuf.framework. Only GoogleUtilities.framework of those is in the firebaseAnalytics plugin. You are right.

Ok, let’s continue.

rm -rf FirebaseCore.framework FirebaseInstallations.framework

Two more frameworks gone.

nano metadata.lua

Let’s remove those frameworks also from metadata using our favorite!? editor nano. Use any editor you want to to accomplish this task. But remove the frameworks mentioned. If you are using nano, use ctrl+o to save and then ctrl+x to exit.

tar -czf ~/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.notifications.v2/iphone/data.tgz .

And then let’s build again.

Voila! We did get more errors. But they are different errors at least. As we can guess, the newer libraries are not compatible with the old ones. But luckily we are not completely out of luck :).

As mentioned above my guess was that firebaseAnalytics is using version 6.32.0. Let’s download it from:

https://github.com/firebase/firebase-ios-sdk/releases/tag/CocoaPods-6.32.0

Based on the file size and dates etc. we can figure out that it is almost for sure 6.32.0 that is used by firebaseAnalytics. If we are really lucky, replacing the remaining two frameworks in plugin.notifications with the newer ones would solve the issue. I did rename the zip to Firebase6.32.0 and double-clicked the downloaded zip to open the zip and then (still in ~/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.notifications.v2/iphone/data)

rm -rf FirebaseInstanceID.framework FirebaseMessaging.framework cp -r ~/Downloads/Firebase6.32.0/FirebaseMessaging/FirebaseInstanceID.xcframework/ios-armv7_arm64/FirebaseInstanceID.framework . cp -r ~/Downloads/Firebase6.32.0/FirebaseMessaging/FirebaseMessaging.xcframework/ios-armv7_arm64/FirebaseMessaging.framework . cp -r ~/Downloads/Firebase6.32.0/FirebaseMessaging/Protobuf.xcframework/ios-armv7_arm64/Protobuf.framework .

As you noticed we did actually copy protobuf back to a different location. So let’s add id back to metadata.lua as well. And the again:

tar -czf ~/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.notifications.v2/iphone/data.tgz .

And let’s compile.

And voila! No errors and the application runs on the device as well.

To verify that the application works you have to check the local notifications by waiting to get one. In case of receiving data from Firebase analytics you can open Firebase console and open StreamView. If you have given your application a newer version that in the production is it easy to find your events. Just select App Version and if you receive events you will see your app version in the list.

Just to clarify, here is how the final metadata.lua looks like:

local metadata =
{
        plugin =
        {
                format = "staticLibrary",
                staticLibs = { 'NotificationsV2Plugin',   }, 
                frameworks = { 'FirebaseInstanceID', 'FirebaseMessaging', 'Protobuf' },
                frameworksOptional = { "UserNotifications", "UserNotificationsUI" },
                delegates = { "CoronaNotificationsDelegate" }
        }
}

return metadata

3. AdMob plugin

Finally, let’s add plugin.admob and plugin.att. Add them into your build.settings as instructed and build for device. And init admob like it should be done. And start the application. Not good. At least in my case the app freezes with a blank screen.

So, let’s use the same tactics as with plugin.notifications.

cd ~/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.admob/iphone/  
open data.tgz
cd data
rm -rf resources/Frameworks
rm -rf GoogleAppMeasurement.framework GoogleMobileAds.framework

cp -r ~/Downloads/Firebase6.32.0/Google-Mobile-Ads-SDK/GoogleMobileAds.framework .
cp -r ~/Downloads/Firebase6.32.0/Google-Mobile-Ads-SDK/UserMessagingPlatform.framework .
nano metadata.lua
tar -czf ~/Solar2DPlugins/Caches/Solar2Directory/coronalabs/com.coronalabs/plugin.admob/iphone/data.tgz .

metadata.lua in this case looks like this:

local metadata =
{
        plugin =
        {
                format = 'staticLibrary',
                staticLibs = { 'plugin_admob', },
                frameworks = { 'GoogleMobileAds', 'UserMessagingPlatform' },
                frameworksOptional = {},
        },
}

return metadata

And build and run. And the plugin seems to work ok.

Except in case of banners the log starts to report all the time:

[Device] 0x10cdcf270 - [PID=11611, throttler=0x1094a1ed8] ProcessThrottler::Activity::Activity: Starting foreground activity / 'WebPageProxy::runJavaScriptInFrameInScriptWorld'
[Device] 0x10cdcf270 - [PID=11611, throttler=0x1094a1ed8] ProcessThrottler::Activity::invalidate: Ending foreground activity / 'WebPageProxy::runJavaScriptInFrameInScriptWorld'
[Device] 0x10cdcf2a0 - [PID=11611, throttler=0x1094a1ed8] ProcessThrottler::Activity::Activity: Starting foreground activity / 'WebPageProxy::runJavaScriptInFrameInScriptWorld'
[Device] 0x10cdcf2a0 - [PID=11611, throttler=0x1094a1ed8] ProcessThrottler::Activity::invalidate: Ending foreground activity / 'WebPageProxy::runJavaScriptInFrameInScriptWorld'

Not good in my opinion. Luckily we can do more. Vlad kindly did insert admob plugin source code into github: https://github.com/coronalabs/com.coronalabs-plugin.admob

So we can ensure that we have the latest version and do modifications. I did create a fork of the repository and did the changes mentioned above. And did build. No change.

So, I guess I can live with this.

Hopefully this helps. I have tried to document all the relevant details but I know that often more explanation might be helpful. If you have some detailed questions, send me an email.

Note also that simulator updates the plugins. So one day your modified plugin might be built and installed on the device, on the other day not anymore. In that case jsut copy the modified plugin again to the relevan directory.

Contact information

Sorry, I do not have a blogging platform in use. If you have any questions, you can send me an email. I will try to answer here.

mikko.franssila@docommit.com

Follow us

Try out the game

Datasheet

Trashman Underwater

  • A mobile game where the aim of the player is to clean the seas by collecting trash out of oceans. Suitable for kids. More than 30 levels, nice and calm pace.
  • Author and publisher: Docommit oy
  • Rating: 4.9 based on 25 ratings, updated 7.9.2020)
  • Play Mode: Single Player
  • Platforms: iOS, Android
  • Price: Free to Play
  • In app Purchases: Yes
  • Ads: Yes
  • For Human Beings Between Age: 4-110
  • More Screenshots: Screenshots