Search Unity

Question [iOS 14] Properly dealing with NSLocalNetworkUsageDescription

Discussion in 'iOS and tvOS' started by Denchi_, Sep 17, 2020.

  1. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    Hi,

    apparently in iOS 14, access to the local network has to be explicitly requested. This happens automatically when my app tries to access the network for the first time, showing a message "<AppName> would like to find and connect devices on your local network", see also:

    https://developer.apple.com/videos/play/wwdc2020/10110/

    I have UDP-based local server discovery functionality in my app and starting this discovery (UDP listen) does not seem to trigger the network permission request. Instead, it will just fail transparently. Once I use a different functionality of my app (directly connect to a local server by IP using TCP), the message is triggered and I can give the permission. After that's done, the server discovery also works.

    Is there a good way to manually request (and re-request if not given) this permission, for example when the app starts or when a button is pressed? I've tried adding NSLocalNetworkUsageDescription to my .plist file, but that only allowed me to set a custom message.

    Also, what's a good way to check if the network permission was given by the user?

    Thanks
    Denchi
     
  2. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    Hey,

    I've just started hearing from customers that my app cannot connect to its UDP server after upgrading to iOS 14.
    Seems that I'm in the same boat as you. Thanks for the links at least I have an idea of whats going on.
    Have you made any progress?

    Does your app appear in this network permission list as described here?
    https://support.plex.tv/articles/ios-system-permissions/

    Looks like Apple has dropped us in it with this one!
     
  3. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    The user is asked if they want to grant network access the first time your app accesses the local network. Before that happens, the permission isn't shown in the list.

    For some reason, listening to UDP packets doesn't seem to trigger the network access permission request dialog. The dialog only seems to trigger if I try to open a TCP socket to another device (I use Telepathy for that in my app).

    As a hack/workaround, I just try to open a TCP socket to 255.255.255.255 when the app starts. This of course fails but it triggers the dialog at startup and once the user has allowed network access, I then also receive UDP packets properly when listening for them. I'm sure there's a proper way to do this, but this seems to work for me for now at least.

    I've asked Apple support about this, will update if/when I get a response. Please also let me know if you find a better way to handle this.

    As for how to check if the permission was given, I still have no idea. I just remind the users in my app to check the app permissions if the server scan doesn't work.
     
  4. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    I literally just read here that if you only listen for data the dialog wont show:
    https://developer.apple.com/forums/thread/660260

    In my app some connection modes will only listen for data.
    I am at least able to get my users to attempt a different connection mode that will try to send a packet to bring up the permission dialog so they can allow it.

    In this thread it seems the accepted hack is to ping yourself every second or so. The ping will cause the dialog to show and will continue to fail if they deny the permission or success if they accept.
    https://developer.apple.com/forums/thread/650648
     
  5. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    Interesting. Maybe I'm doing something wrong, but just trying to ping 127.0.0.1 doesn't seem to trigger the dialog.
    If you have some working code, would you mind sharing it?
     
  6. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    I got an answer from Apple. Basically, they asked me for more info/feedback but also added:

    So basically what I've been doing already. Kind of odd that they wouldn't have anything to manually trigger permission requests like on Android.
     
  7. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    No I don't have any working code myself.
    The mode I've asked the user to switch to uses lidgren for networking. I don't know what part of its connection attempt triggers the dialog.
    Do you mind sharing your current method using TCP and the broadcast address?
    I don't have an iOS 14 device myself so cannot test unfortunately.
     
    Last edited: Sep 21, 2020
  8. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    Sure. This is what I have right now. Seems to reliably trigger the dialog.

    Note that when the user clicks NO on the dialog, it won't appear again. The user will have to go into the app settings and manually set the permission in that case.

    Edit: Should also note that my app made it through review just now, so looks like this is okay to use for now.

    Code (CSharp):
    1. using UnityEngine;
    2. using Telepathy;
    3.  
    4. /// <summary>
    5. /// Only needed on iOS. Triggers network access request message.
    6. /// </summary>
    7. public class NetworkAccessDialogTrigger : MonoBehaviour
    8. {
    9.     /// <summary>
    10.     /// Whether or not to ask user for network access at startup.
    11.     /// </summary>
    12.     public bool AskAtStartup;
    13.  
    14.     /// <summary>
    15.     /// Network client.
    16.     /// </summary>
    17.     private Client client;
    18.  
    19.     /// <summary>
    20.     /// Whether or not the "client" is currently active.
    21.     /// </summary>
    22.     private bool active = false;
    23.  
    24.     void Start()
    25.     {
    26.         if (AskAtStartup)
    27.         {
    28.             TriggerNetworkPermissionRequest();
    29.         }
    30.     }
    31.  
    32.     /// <summary>
    33.     /// Workaround to trigger the iOS local network access
    34.     /// permission dialog by connecting to 255.255.255.255
    35.     /// </summary>
    36.     public void TriggerNetworkPermissionRequest()
    37.     {
    38.         if (!PlatformHelper.IsIphone || active)
    39.             return;
    40.  
    41.         Debug.Log("Requesting network access permission.");
    42.  
    43.         active = true;
    44.    
    45.         // Trigger dialog.
    46.         client = new Client();
    47.         client.Connect("255.255.255.255", 8052);
    48.  
    49.         // Abort connection shortly after.
    50.         Invoke(nameof(Disconnect), 2);
    51.     }
    52.  
    53.     /// <summary>
    54.     /// Abort connection.
    55.     /// </summary>
    56.     private void Disconnect()
    57.     {
    58.         if (client.Connected || client.Connecting)
    59.         {
    60.             client.Disconnect();
    61.         }
    62.  
    63.         active = false;
    64.     }
    65. }
    66.  
     
    Last edited: Sep 21, 2020
    Berno likes this.
  9. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    Thanks a lot.
    I need to update my xcode so I can use the ios 14 simulator.
    If I come up with any alternative solution will share it here.
     
  10. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    Do you know if you can get the permissions prompt to show running on the simulator?
    I've tried your code and I've gotten nothing. Do you actually need an iOS 14 device to test this?
     
  11. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    No idea. My app uses ARKit/ARCore so I could never got it to work on the simulator. It does work on an actual iOS 14 device though.
     
  12. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    Anyone coming across this problem, here is a function to trigger the permissions dialog that doesn't rely on any networking library:


    Code (CSharp):
    1. using System;
    2. using System.Net;
    3. using System.Net.Sockets;
    4. using UnityEngine;
    5.  
    6. public class IOSNetworkPermission
    7. {
    8.     //connect to broadcast address to send data and trigger network permission dialog in iOS 14
    9.     public static void TriggerDialog()
    10.     {
    11.         //Main.Log("Trigger network dialog");
    12.         var client = new TcpClient();
    13.         try
    14.         {
    15.             client.Connect(IPAddress.Parse("255.255.255.255"), 8052);
    16.         }
    17.         catch (Exception e)
    18.         {
    19.             Debug.Log("IOSNetworkPermission exception occured");
    20.             Debug.Log(e.Message);
    21.         }
    22.         client?.Close();
    23.     }
    24. }
    25.  
     
    matronator likes this.
  13. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    hi,
    I am facing an issue with NetworkDiscovery, it was working fine before but after updating to iOS 14 it is not able to find the IP address in the network. Any solutions on this?
     
  14. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    I am not able to get the dialog. Do I have to trigger any function at the beginning?
     
  15. Denchi_

    Denchi_

    Joined:
    Dec 17, 2018
    Posts:
    23
    Just got a mail from Apple support:

    Hi --------,

    That’s great news, glad to hear it! Don’t worry about filing the feedback, we think we’ve found (and fixed) some of the underlying issues, thanks for all the help.

    Best,
    Apple Networking
     
  16. Berno

    Berno

    Joined:
    Oct 29, 2014
    Posts:
    40
    Just copy the code and call TriggerDialog() at some point in your app.

    Does this mean that listening to UDP will trigger the dialog in an iOS 14 patch?
     
    saifshk17 likes this.
  17. saifshk17

    saifshk17

    Joined:
    Dec 4, 2016
    Posts:
    488
    Thanks alot! it worked! :)
     
  18. wesselb

    wesselb

    Joined:
    May 29, 2018
    Posts:
    6
    For some reason this method still doesn't trigger the dialog in my app, weirdly enough. it says 'no route to host'. do others have the same error? or are there maybe different solutions?
     
    Last edited: Dec 16, 2020
  19. wesselb

    wesselb

    Joined:
    May 29, 2018
    Posts:
    6
    for the people who still having issues with this. I finally managed to fix the problem in unity by turning on this thing:

    it's in the player settings in unity.