Flutter local network privacy permissions for debugging: the smart way

I’ve recently been working on a Flutter app for my work at Cino.

When I tried to run my app on my iPhone, I noticed the debugging features (such as hot-reloading, a real game-changer by the way) did not work and the following error was logged:

On iOS 14+, local network broadcast in apps need to be declared in the app’s Info.plist. Debug and profile Flutter apps and modules host VM services on the local network to support debugging features such as hot reload and DevTools. To make your Flutter app or module attachable and debuggable, add a ‘_dartobservatory._tcp’ value to the ‘NSBonjourServices’ key in your Info.plist for the Debug/Profile configurations. For more information, see https://flutter.dev/docs/development/add-to-app/ios/project-setup#local-network-privacy-permissions

The documentation linked describes a way to solve this on iOS. Basically it entails adding a property to your Info.plist file. However, since this property should not be included in release builds, the guide suggests to create multiple copies of your Info.plist file, i.e. one called Info-Debug.plist and one called Info-Release.plist. The former file would then include this property and the latter would not.

Although this approach works, it violates the well-known DRY principle. It is now very easy to forget that any other property change needs to be propagated to multiple files, easily leading to errors.

Because I really did not like this approach, I’ve come up with a better solution by utilizing user defined variables in Xcode:

  1. Open your Info.plist file and add a NSBonjourServices property of type array, containing a single string element {DART_DEBUG_BONJOUR_SERVICE}. Verify that your plist source now contains this:
<key>NSBonjourServices</key>
<array>
    <string>${DART_DEBUG_BONJOUR_SERVICE}</string>
</array>
  1. Open your Project, select your target, go to the Build Settings tab, and click the + sign in the top left corner and click Add User-Defined Setting. Example image
  2. Rename the added setting to DART_DEBUG_BONJOUR_SERVICE
  3. Click on the arrow next to the setting name to expand the setting. I then entered the value _dartobservatory._tcp for the debug and profile builds, and left it empty for the release build.
  4. ????
  5. Profit!

Because we set the value of DART_DEBUG_BONJOUR_SERVICE in step 4 conditionally based on the active build mode, this makes sure that for release builds it will never be enabled. At the same time, you still have a single plist file you need to maintain, so it’s much more convenient than Firebase’s solution.

Why make life hard when you can make it simple?