{"id":538,"date":"2025-11-23T22:02:18","date_gmt":"2025-11-23T21:02:18","guid":{"rendered":"https:\/\/www.sarbyn.com\/blog\/?p=538"},"modified":"2025-11-23T22:06:15","modified_gmt":"2025-11-23T21:06:15","slug":"fighting-against-kmp-and-firebase-analytics","status":"publish","type":"post","link":"https:\/\/www.sarbyn.com\/blog\/2025\/11\/23\/fighting-against-kmp-and-firebase-analytics\/","title":{"rendered":"Fighting against KMP and Firebase Analytics"},"content":{"rendered":"<p>A small guide that I hope can be useful for understanding how to integrate <strong>Firebase Analytics<\/strong> into a <strong>Kotlin Multiplatform (KMP)<\/strong> project, without using <strong>Cocoapods<\/strong> on the iOS side.<\/p>\n<p>This is a standard approach that can be used for any need where you have to use <strong>native iOS libraries<\/strong>.<\/p>\n<p>First of all, <strong>avoid using Cocoapods<\/strong> in every way, both in the KMP project and in the iOS project.<\/p>\n<h3>Practical Example<\/h3>\n<ul>\n<li><strong>Initial Setup:<\/strong> The Firebase Analytics library is imported as a <strong>Gradle dependency<\/strong> on the <strong>Android<\/strong> side, and as an <strong>SPM (Swift Package Manager)<\/strong> dependency on the <strong>iOS<\/strong> side.<\/li>\n<li>Create an <strong><code>expect<\/code> interface<\/strong>, for example:\n<pre><code class=\"language-kotlin\">expect interface AnalyticsService {\n    fun logEvent(name: String, params: Map&lt;String, Any&gt;?)\n}<\/code><\/pre>\n<\/li>\n<li>Create the two <strong><code>actual<\/code> interfaces<\/strong>, one for Android and one for iOS, defined in Kotlin (in their respective source sets):\n<pre><code class=\"language-kotlin\">\/\/ in androidMain\nactual interface AnalyticsService { \n    actual fun logEvent(name: String, params: Map&lt;String, Any&gt;?) \n}\n\n\/\/ in iosMain\nactual interface AnalyticsService { \n    actual fun logEvent(name: String, params: Map&lt;String, Any&gt;?) \n}<\/code><\/pre>\n<\/li>\n<li>Create a <strong>Kotlin implementation for Android<\/strong> of the Android <code>actual<\/code> interface, which uses the Gradle dependency.<\/li>\n<li>Create a <strong>Swift implementation for iOS<\/strong> of the iOS <code>actual<\/code> interface, which uses the SPM dependency. Here&#8217;s a very simplified example of how to expose Swift logic to the KMP module:\n<pre><code class=\"language-swift\">import FirebaseAnalytics \/\/ The SPM dependency\n\n@main\nclass iOSAnalyticsService: AnalyticsService { \/\/ The class exposed to Kotlin\n    func logEvent(name: String, params: [String : Any]?) {\n        Analytics.logEvent(name, parameters: params)\n    }\n}<\/code><\/pre>\n<\/li>\n<\/ul>\n<p>That&#8217;s all it takes.<\/p>\n<p>WTF&#8230;so simple&#8230;I banged my head against the wall for weeks&#8230;.<\/p>\n<p>Can it perhaps be optimized? Certainly, but as a first step, this works perfectly fine. If I find improvements, I&#8217;ll write another couple of lines here.<\/p>\n<hr>\n<h3>Lessons Learned<\/h3>\n<ul>\n<li><strong>Cocoapods<\/strong> is awful<\/li>\n<li>Asking these things to <strong>AIs<\/strong> like ChatGPT or Gemini is a waste of time; they just guess like a kid. Embarrassing.<\/li>\n<li>Getting into the <strong>KMP mindset<\/strong> is truly complicated.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>A small guide that I hope can be useful for understanding how to integrate Firebase Analytics into a Kotlin Multiplatform (KMP) project, without using Cocoapods on the iOS side. This is a standard approach that can be used for any need where you have to use native iOS libraries. First of all, avoid using Cocoapods <a class=\"read-more\" href=\"https:\/\/www.sarbyn.com\/blog\/2025\/11\/23\/fighting-against-kmp-and-firebase-analytics\/\">&hellip;&nbsp;<span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[5,100],"tags":[75,99],"class_list":["post-538","post","type-post","status-publish","format-standard","hentry","category-android","category-kmp","tag-android","tag-kmp"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p3JApm-8G","jetpack_likes_enabled":true,"jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/posts\/538"}],"collection":[{"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/comments?post=538"}],"version-history":[{"count":9,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/posts\/538\/revisions"}],"predecessor-version":[{"id":547,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/posts\/538\/revisions\/547"}],"wp:attachment":[{"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/media?parent=538"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/categories?post=538"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sarbyn.com\/blog\/wp-json\/wp\/v2\/tags?post=538"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}