Lately, many people have wondered why some iOS apps were so huge. I asked myself this question and analyzed the Facebook application for iOS v. 66.0 in 2016 and v. 87.0 in 2017.

In this article, I dissect the Nest app (5.30.5) for iOS released on 29.11.2018. There has been quite some speculations about this app in a thread started by John Gruber on Twitter:

This post will answer some simple questions about this specific app:

  • Which technologies are used?
  • Why is the app so big?
  • Would it be possible to reduce the app size?
Want to support this blog? Please check out

MarkChart

Note that this analysis is done purely on the technical level. I don’t own a Nest product, and haven’t played much with the app.

App overview

When downloading the app on an iPad Air 2, the App Store indicates a size of 206MB. On the device itself, the uncompressed application weights around 202MB which is consistent. Please note that in this article, the sizes mentioned are indicative and have been rounded in some cases. They could also vary depending on the type of iOS device.

While the application appears with the name Nest on the device, it is actually called Jasper as we can see in the Info.plist:

<key>CFBundleName</key>
<string>Nest</string>
<key>CFBundleExecutable</key>
<string>Jasper</string>
<key>CFBundleIdentifier</key>
<string>com.nestlabs.jasper.release</string>
<key>CFBundleVersion</key>
<string>5.30.5.8</string>

Let start by looking at an overhaul overview using GrandPerspective:

The structure is well-defined and we can identify 6 parts composing the app:

  • main binary Jasper
  • Watch app
  • third-party Frameworks and Swift libraries
  • localizations
  • assets from the asset catalog
  • some extra assets, mostly composed of mp4 and wav files

We will check each of these components in the reversed order.

Extra assets (mp4, wav)

Let’s start with the extra assets, mostly composed of mp4 and wav files. The application contains 46 mp4 movies to help the user set up devices. These animations probably improve the initial user experience and it makes sense to have them in the app. Here is a screenshot of one of the animation:

Assets

The compiled Asset Catalog contains 1787 assets for 31MB. Uncompressed, these assets weight 56MB. If you are interested by the .car file format, you can read my article Reverse engineering the .car file format (compiled Asset Catalogs). It is important to note that App Slicing works as expected: the compiled Assets.car on an iPad Air 2 only contains images with the @2x resolution. The images with the @1x and @3x resolutions are not present. This explains why you will see a 206MB download for an iPad Air 2 while the download on an iPhone Xs with @3x resolution is 245MB.

It is easy to extract and look at the images using my QLCARFiles QuickLook plugin:

There are quite a lot of assets but this is not unusal. However we can see that there are some big images, each taking several hundred of kilobytes:

Here is a screenshot showing the 5 biggest images, some looking like stock photos:

Localizations

The app contains 9 localizations:

  • de
  • en-GB
  • en
  • es-MX
  • es
  • fr-CA
  • fr
  • it
  • nl

Interestingly the localizations take 33MB which is quite a lot. The French localization contains the following files:

Each Localizable.strings file weights only around 1MB. But each localization contains localized images. Below is one example to exhibit the differences between English and French:

While this technic is perfectly valid to improve the user experience, there are some improvements that could be done. First there are several duplicated images across the localizations. As we have seen in the example above, some images are only localized to display a temperature in Fahrenheit (US) or Celsius (all other localizations). Since Fahrenheit is only used for the en localization, each of these images is duplicated 8 times, for each localization other than en:

pairing_onyx_scene.jpg
pairing_onyx_scene@2x.jpg
pairing_onyx_scene@3x.jpg
setting_add_device_onyx_find_key_diagram_1_phone.png
setting_add_device_onyx_find_key_diagram_1_phone@2x.png
setting_add_device_onyx_find_key_diagram_1_phone@3x.png

An attentive reader might have spotted a second optimization: since the images are not stored in the Asset Catalog, App Slicing doesn’t take effect. You will note that the images are available in the @1x, @2x and @3x resolutions although my device will only load the @2x resolutions. In order to get App Slicing working, the localized images should be stored in the asset catalog. This could be done for example by adding a suffix to the filenames and loading the images programmatically:

setting_add_device_onyx_find_key_diagram_1_phone_de.png
setting_add_device_onyx_find_key_diagram_1_phone_de@2x.png
setting_add_device_onyx_find_key_diagram_1_phone_de@3x.png
setting_add_device_onyx_find_key_diagram_1_phone_en.png
setting_add_device_onyx_find_key_diagram_1_phone_en@2x.png
setting_add_device_onyx_find_key_diagram_1_phone_en@3x.png
setting_add_device_onyx_find_key_diagram_1_phone_fr.png
setting_add_device_onyx_find_key_diagram_1_phone_fr@2x.png
setting_add_device_onyx_find_key_diagram_1_phone_fr@3x.png
...

If I remove all the duplicated images and the unneeded resolutions, the localizations would take 14MB instead of 33MB on an iPad Air 2. So we could save around 19MB here, maybe a bit more since the images would be compressed in the Assets.car.

Frameworks

The application contains 67MB of Frameworks. Let’s look at them.

First there are the Swift libraries required due to the lack of ABI stability in Swift. The app is indeed written in Objective-C and Swift. The Swift libraries represent 12MB:

libswiftAVFoundation.dylib
libswiftCore.dylib
libswiftCoreAudio.dylib
libswiftCoreData.dylib
libswiftCoreFoundation.dylib
libswiftCoreGraphics.dylib
libswiftCoreImage.dylib
libswiftCoreLocation.dylib
libswiftCoreMedia.dylib
libswiftDarwin.dylib
libswiftDispatch.dylib
libswiftFoundation.dylib
libswiftMapKit.dylib
libswiftMetal.dylib
libswiftObjectiveC.dylib
libswiftos.dylib
libswiftPhotos.dylib
libswiftQuartzCore.dylib
libswiftsimd.dylib
libswiftUIKit.dylib

Then there are a bunch of other frameworks, some developed by Nest Labs, some by third-party developers. This seems to indicate that the application is well-structured. Here is the list of the Frameworks and their utility:

FrameworkSizeURLDescription
Broker100 kBNest LabsJSON, CoreData?
CocoaAsyncSocket500 kBhttps://github.com/robbiehanson/CocoaAsyncSocketAsynchronous socket networking library
CocoaLumberjack300 kBhttps://github.com/CocoaLumberjack/CocoaLumberjackLogging framework
Courier100 kBhttps://github.com/Drewsmits/CourieriOS Network Layer
DCAPIService1 MBNest LabsBluetooth device communication?
DCKit400 kBhttps://github.com/agordeev/DCKitSet of iOS controls
GoogleToolboxForMac100 kBhttps://github.com/google/google-toolbox-for-macGoogle Toolbox for Mac
grpc2 MBhttps://github.com/grpc/grpcRPC library
GRPCClient500 kBhttps://github.com/grpc/grpc/tree/master/src/objective-c/GRPCClientGeneric gRPC client
GTMSessionFetcher400 kBhttps://github.com/google/gtm-session-fetcherGoogle Toolbox for Mac - Session Fetcher
libPhoneNumber_iOS400 kBhttps://github.com/iziz/libPhoneNumber-iOSPhone number handling library
Lottie600 kBhttps://github.com/airbnb/lottie-iosiOS library to natively render After Effects vector animations
Mantle200 kBhttps://github.com/Mantle/MantleModel framework
nanopb100 kBhttps://github.com/nanopb/nanopbProtocol Buffers with small code size
NestClientProtos100 kBNest LabsProtobuf subclasses
NexusVideoPlayer1 MBNest LabsVideo player
NHNetworkTime100 kBhttps://github.com/huynguyencong/NHNetworkTimeA network time protocol (NTP) client
NLAnalytics1 MBNest LabsCrashlytics, Google Analytics
NLCommonLogging100 kBNest LabsLogging utilities
NLContentComposer700 kBNest LabsUI controls and gestures in Swift
NLLego1 MBNest LabsUI controls
NLLocale200 kBNest LabsAddress, postal code, country
NLMagma100 kBNest LabsSeems to only export a no-op nlmagma_noop() function
NLModelCore8 MBNest LabsCore Data model
NLNetwork100 kBNest LabsNSURLSession utilities
NLStore100 kBNest LabsUse Broker, StoreMad and CoreData
NLUI3 MBNest LabsUI controls and UIKit categories
NLUtils700 kBNest LabsMostly Foundation Categories
NLWeather5 MBNest LabsWeather model and UI
NLWWNCatalog100 kBNest LabsWork With Nest products?
openssl/BoringSSL?2 MBhttps://www.openssl.orgCryptography library
Opus-ios400 kBhttps://github.com/chrisballinger/Opus-iOSAudio codec
PhoenixCommonProtobuf200 kBhttps://developers.google.com/protocol-buffers/Protobuf related
PhoenixCore200 kBNest LabsProtobuf related
PhoenixModels9 MBNest LabsProtobuf related
PhoenixModelsProtobuf2 MBNest LabsProtobuf related
PhoenixServices400 kBNest LabsProtobuf related
PhoenixServicesProtobuf400 kBNest LabsProtobuf related
Protobuf1 MBhttps://github.com/protocolbuffers/protobufProtocol Buffers - Google’s data interchange format
ProtoRPC100 kBhttps://github.com/grpc/grpc/tree/master/src/objective-c/ProtoRPCRPC library for Protocol Buffers
Reachability100 kBhttps://github.com/tonymillion/ReachabilityDrop in replacement for Apple Reachability
RxLibrary100 kBhttps://github.com/grpc/grpc/tree/master/src/objective-c/RxLibraryReactive Extensions
SDWebImage400 kBhttps://github.com/SDWebImage/SDWebImageAsynchronous image downloader with cache support as a UIImageView category
ServiceChat1 MBhttps://github.com/forcedotcom/ServiceSDK-iOSSalesforce SDK (real-time chat with agents)
ServiceCore3 MBhttps://github.com/forcedotcom/ServiceSDK-iOSSalesforce SDK
ServiceKnowledge2 MBhttps://github.com/forcedotcom/ServiceSDK-iOSSalesforce SDK (display Knowledge articles)
speex300 kBhttps://www.speex.orgAudio compression format designed for speech
StoreMad100 kBhttps://github.com/Drewsmits/StoreMadCore Data Utilities
StructureViewModel200 kBNest LabsDevices status
ThermostatViewModel300 kBNest LabsThermostat model and UI
ThumbnailEngine300 kBNest LabsCamera video frame decoder
Weave4 MBNest LabsDevice Manager and Bluetooth communication
youtube_ios_player_helper100 kBhttps://github.com/youtube/youtube-ios-player-helperYouTube video playback

That’s quite a lot of frameworks. I don’t know if they are all needed but some seem to overlap:

  • Speex has been obsoleted by Opus
  • There are 3 networking libraries: CocoaAsyncSocket, Courier, NLNetwork
  • There are multiple Protocol Buffers related frameworks

Watch app

The Watch app takes around 23 MB. Let’s zoom into it:

Swift libraries

The Watch app contains Swift code and as such the Swift libraries are copied:

libswiftCore
libswiftCoreFoundation
libswiftCoreGraphics
libswiftDarwin
libswiftDispatch
libswiftFoundation
libswiftObjectiveC
libswiftUIKit

Note that for such a small app, the Swift libraries take 30% of the size!

Other Frameworks

The frameworks used by the Watch app are with no surprise a subset of the frameworks used in the iOS app:

Broker
CocoaLumberjack
Courier
Mantle
NLAnalytics
NLCommonLogging
NLMagma
NLModelCore
NLNetwork
NLStore
NLUI
NLUtils
StoreMad
StructureViewModel
ThermostatViewModel

Localizations

The Watch app contains 10 localizations:

  • de
  • en-GB
  • en
  • es-MX
  • es
  • fr-CA
  • fr
  • it
  • nl
  • vi

I wondered why the Watch app would contain one extra language, especially Vietnamese… Opening and reading the localization gave the answer:

If you pay attention, you will note that the text is written in English with special characters. So this is most likely a fake localization used for testing which ended up in the release app by accident. Removing this localization would save around 1.3 MB.

Jasper binary

The main binary Jasper is 22MB. The entropy graph generated by Hopper indicates that most of the content is likely code (higher entropy and visible as red):

There is no surprise when listing the libraries loaded by the binary:

@rpath/Broker.framework/Broker
@rpath/CocoaAsyncSocket.framework/CocoaAsyncSocket
@rpath/CocoaLumberjack.framework/CocoaLumberjack
@rpath/Courier.framework/Courier
@rpath/DCAPIService.framework/DCAPIService
@rpath/DCKit.framework/DCKit
@rpath/GoogleToolboxForMac.framework/GoogleToolboxForMac
@rpath/grpc.framework/grpc
@rpath/GRPCClient.framework/GRPCClient
@rpath/GTMSessionFetcher.framework/GTMSessionFetcher
@rpath/libPhoneNumber_iOS.framework/libPhoneNumber_iOS
@rpath/libswiftAVFoundation.dylib
@rpath/libswiftCore.dylib
@rpath/libswiftCoreAudio.dylib
@rpath/libswiftCoreData.dylib
@rpath/libswiftCoreFoundation.dylib
@rpath/libswiftCoreGraphics.dylib
@rpath/libswiftCoreImage.dylib
@rpath/libswiftCoreLocation.dylib
@rpath/libswiftCoreMedia.dylib
@rpath/libswiftDarwin.dylib
@rpath/libswiftDispatch.dylib
@rpath/libswiftFoundation.dylib
@rpath/libswiftMapKit.dylib
@rpath/libswiftMetal.dylib
@rpath/libswiftObjectiveC.dylib
@rpath/libswiftos.dylib
@rpath/libswiftPhotos.dylib
@rpath/libswiftQuartzCore.dylib
@rpath/libswiftsimd.dylib
@rpath/libswiftUIKit.dylib
@rpath/Lottie.framework/Lottie
@rpath/Mantle.framework/Mantle
@rpath/nanopb.framework/nanopb
@rpath/NestClientProtos.framework/NestClientProtos
@rpath/NexusVideoPlayer.framework/NexusVideoPlayer
@rpath/NHNetworkTime.framework/NHNetworkTime
@rpath/NLAnalytics.framework/NLAnalytics
@rpath/NLCommonLogging.framework/NLCommonLogging
@rpath/NLContentComposer.framework/NLContentComposer
@rpath/NLLego.framework/NLLego
@rpath/NLLocale.framework/NLLocale
@rpath/NLMagma.framework/NLMagma
@rpath/NLModelCore.framework/NLModelCore
@rpath/NLNetwork.framework/NLNetwork
@rpath/NLStore.framework/NLStore
@rpath/NLUI.framework/NLUI
@rpath/NLUtils.framework/NLUtils
@rpath/NLWeather.framework/NLWeather
@rpath/NLWWNCatalog.framework/NLWWNCatalog
@rpath/openssl.framework/openssl
@rpath/Opus-ios.framework/Opus-ios
@rpath/PhoenixCommonProtobuf.framework/PhoenixCommonProtobuf
@rpath/PhoenixCore.framework/PhoenixCore
@rpath/PhoenixModels.framework/PhoenixModels
@rpath/PhoenixModelsProtobuf.framework/PhoenixModelsProtobuf
@rpath/PhoenixServices.framework/PhoenixServices
@rpath/PhoenixServicesProtobuf.framework/PhoenixServicesProtobuf
@rpath/Protobuf.framework/Protobuf
@rpath/ProtoRPC.framework/ProtoRPC
@rpath/Reachability.framework/Reachability
@rpath/RxLibrary.framework/RxLibrary
@rpath/SDWebImage.framework/SDWebImage
@rpath/ServiceChat.framework/ServiceChat
@rpath/ServiceCore.framework/ServiceCore
@rpath/ServiceKnowledge.framework/ServiceKnowledge
@rpath/speex.framework/speex
@rpath/StoreMad.framework/StoreMad
@rpath/StructureViewModel.framework/StructureViewModel
@rpath/ThermostatViewModel.framework/ThermostatViewModel
@rpath/ThumbnailEngine.framework/ThumbnailEngine
@rpath/Weave.framework/Weave
@rpath/youtube_ios_player_helper.framework/youtube_ios_player_helper
/System/Library/Frameworks/Accelerate.framework/Accelerate
/System/Library/Frameworks/AddressBookUI.framework/AddressBookUI
/System/Library/Frameworks/AdSupport.framework/AdSupport
/System/Library/Frameworks/AssetsLibrary.framework/AssetsLibrary
/System/Library/Frameworks/AudioToolbox.framework/AudioToolbox
/System/Library/Frameworks/AVFoundation.framework/AVFoundation
/System/Library/Frameworks/AVKit.framework/AVKit
/System/Library/Frameworks/CFNetwork.framework/CFNetwork
/System/Library/Frameworks/Contacts.framework/Contacts
/System/Library/Frameworks/ContactsUI.framework/ContactsUI
/System/Library/Frameworks/CoreBluetooth.framework/CoreBluetooth
/System/Library/Frameworks/CoreData.framework/CoreData
/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
/System/Library/Frameworks/CoreGraphics.framework/CoreGraphics
/System/Library/Frameworks/CoreLocation.framework/CoreLocation
/System/Library/Frameworks/CoreMedia.framework/CoreMedia
/System/Library/Frameworks/CoreTelephony.framework/CoreTelephony
/System/Library/Frameworks/CoreText.framework/CoreText
/System/Library/Frameworks/CoreVideo.framework/CoreVideo
/System/Library/Frameworks/Foundation.framework/Foundation
/System/Library/Frameworks/ImageIO.framework/ImageIO
/System/Library/Frameworks/MapKit.framework/MapKit
/System/Library/Frameworks/MessageUI.framework/MessageUI
/System/Library/Frameworks/OpenGLES.framework/OpenGLES
/System/Library/Frameworks/Photos.framework/Photos
/System/Library/Frameworks/QuartzCore.framework/QuartzCore
/System/Library/Frameworks/SafariServices.framework/SafariServices
/System/Library/Frameworks/Security.framework/Security
/System/Library/Frameworks/StoreKit.framework/StoreKit
/System/Library/Frameworks/SystemConfiguration.framework/SystemConfiguration
/System/Library/Frameworks/UIKit.framework/UIKit
/System/Library/Frameworks/UserNotifications.framework/UserNotifications
/System/Library/Frameworks/WatchConnectivity.framework/WatchConnectivity
/System/Library/Frameworks/WebKit.framework/WebKit
/usr/lib/libc++.1.dylib
/usr/lib/libc++abi.dylib
/usr/lib/libobjc.A.dylib
/usr/lib/libresolv.9.dylib
/usr/lib/libsqlite3.dylib
/usr/lib/libSystem.B.dylib
/usr/lib/libz.1.dylib

More interesting is that the binary has not been stripped and contains a lot of build artifacts. I extracted the paths with grep with the following regular expression:

grep -aor '/Users/[-\+A-Za-z0-9_/\. ]*' Jasper

And obtained 360 lines like:

/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Alarm/Mute/Hush/NLAlarmCardSafetyHusher.m
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Alarm/Mute/NLAlarmCardMuteViewModel.m
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Alarm/Mute/View/NLAlarmCardMuteViewController.m
[...]
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/CameraVideo/NLVideoPlayerView.m
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Camerazilla/Analytics/CamerazillaAnalyticsReporter.m
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Camerazilla/CamerazillaActivityThumbnailViewModel.m
[...]
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/CheckMarkView.swift
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Devices/Agate/Pairing/AgateConfigWorkflowSource.swift
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Devices/Agate/Pairing/AgateHeatLinkIntroWorkFlowSource.swift
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Devices/Agate/Pairing/AgateIntroWorkflowSource.swift
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Devices/Agate/Pairing/AgateLocaleSettingViewController.swift
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/Classes/Devices/Agate/Pairing/PairingFlow+Agate.swift
[...]
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/v4Classes/ViewControllers/StructureHomeAwayAssistViewController.m
/Users/admin/bamboo-agents/bamboo-agent-1/xml-data/build-dir/JSP-PDB823-NESTMOBILE/Jasper/v4Classes/ViewControllers/StructureHomeAwaySummaryViewController+Tahiti.m
/Users/crashlytics/buildAgent/work/7e5c596e59839c6e/apple/AnswersKit/AnswersKit/ANSBackoffTimer.m

We see that Nest uses Bamboo to build the application and we have the confirmation that the app uses Swift and Objective-C code. We can also estimate that ~45% of the files are written in Swift.

This information can also be used to rebuild the file hierarchy:

While we have a lot of details about the internal files, that does not seem to explain why the binary is 22MB. Performing a class-dump of the code will give answers to this question. The class-dump indicates that there are almost 3000 Swift and Objective-C classes.

By looking at the classes, we can identify several statically linked libraries:

FrameworkURLDescription
Answershttps://fabric.io/kits/ios/answersAnalytics
Crashlyticscrashlytics.comCrash reporting
FABOperationhttps://github.com/google-fabric/FABOperationExtend Apple’s NSOperation API
Firebase iOS SDKhttps://firebase.google.comAnalytics, databases, messaging and crash reporting
Google Analytics Services SDKhttps://developers.google.com/analytics/devguides/collection/ios/v3/Analytics
GoogleUtilitieshttp://cocoadocs.org/docsets/GoogleUtilities/Shared utility methods
WEPopoverhttps://github.com/werner77/WEPopoverPopover implementation

The Google Analytics Services SDK can be downloaded as a static library which weights 36 MB for 5 architectures. So most likely this SDK counts for around 7MB in the binary.

The Firebase iOS SDK seems to be quite huge too but I did not manage to estimate its size. It is also interesting to note that there are multiple (overlapping?) frameworks to track users:

  • Answers
  • Firebase iOS SDK
  • Google Analytics Services SDK which is according to the documentation superseeded by the Firebase iOS SDK
  • NLAnalytics (which might just be a wrapper?)

Miscellaneous

While analyzing the app, I discovered several points worth mentionning:

  • HillviewToMiranda.gpx

The unused small HillviewToMiranda.gpx file contains GPS information representing a route between Nest and Nest Labs Miranda. The route can be visualized using http://www.gpsvisualizer.com:

  • thief.jpg

The app contains the small thief.jpg image which appears to be unused:

  • SnapshotMap.json

This file contains information about Jira bugs.

  • Devices code name

As we can see from the NLDeckItemModel subclasses, Nest seems to like rock names for product code names:

NLDeckItemAgate
NLDeckItemDiamond
NLDeckItemFlintstone
NLDeckItemHeatLink
NLDeckItemHotWater
NLDeckItemKryptonite
NLDeckItemOnyx
NLDeckItemPinna
NLDeckItemQuartz
NLDeckItemTopazes
LockzillaDeckItem
Want to support this blog? Please check out

DotChart

Conclusion

We discovered that the app is written in Objective-C and Swift, with a non-negligeable part in Swift. The source code seems to be well-structured with reusable code in frameworks.

The frameworks are representing an important part of the app size. First the Swift libraries in the app and in the Watch app are counting for approximatively 10% of the total size. There are also a lot of other frameworks. Some could possibly overlap like the analytics frameworks: Answers, Firebase iOS SDK, Google Analytics Services SDK.

The application contains a lot of assets including mp4 animations to help the users set up their devices. These assets obviously increase the size of the app.

We also found some simple ways to reduce the app size by around 10%: use App Slicing for the localized images, remove duplicated localized images, remove fake vietnamese localization, remove unused assets (HillviewToMiranda.gpx, thief.jpg, SnapshotMap.json, …).