iOS 14 How to Trigger Local Network Dialog and Check User Answer

iOS 14 How to trigger Local Network dialog and check user answer?

I did open DTS request and had conversion with Apple support team. Here is some important parts which I included below.

How to check is access granted or not

From support team:

For know, there is no such an API to check user permission.

From support team:

If the user declines, the connection fails. Exactly how it fails
depends on the network API you’re using and how you use that API.

  • By default the connection will fail with NSURLErrorNotConnectedToInternet.
  • If you set waitsForConnectivity on the session configuration, the request will wait for things to improve. In that case you’ll receive
    the -URLSession:taskIsWaitingForConnectivity: delegate callback to
    tell you about this. If the user changes their mind and enables local
    network access, the connection will then go through.

Unfortunately there’s no direct way to determine if this behaviour is
the result of a local network privacy restriction or some other
networking failure.



How to trigger this popup

From support team:

the problem here is that the local network permission alert is
triggered by outgoing traffic and you do not generate any outgoing
traffic. The only way around this is to generate some dummy outgoing
traffic in order to trigger this alert.

I’ve seen other developers in this situation and the absence of a
direct API to trigger the local network permission alert is quite
annoying. I encourage you to file a bug about this.

I’ve been discussing this issue with the local network privacy team
and our current advice for apps in your situation — that is, apps that
want to receive broadcasts but don’t send any local network traffic —
is as follows:

  • The system should do a better job of handling this. We’re tracking that as a bug rdar://problem/67975514. This isn’t fixed in the
    current iOS 14.2b1 release but you should continue to test with iOS
    beta seeds as they are released.

  • In the meantime you can force the local network privacy alert to show by sending a message. We specifically recommend that you send a
    message that’s roughly equivalent to the message you’re trying to
    receive, so in your case that means sending an IPv4 UDP broadcast.

UPDATE

For iOS 14.2 - prompt is received for inbound traffic FIXED. Because of this you don't need below example for simulating traffic to triggering prompt.


Here is class for dummy outgoing traffic simulation:
example

That traffic will never leave the iOS device and thus, even if the
interface is asleep, it won’t wake it up. And even if it did wake up
the interface, the cost of that is trivial because you’re not doing it
over and over again, just once in order to trigger the local network
privacy alert.

Objective C: iOS 14 How to do Network privacy permission check

This is my original answer that is written in Swift - iOS 14 How to trigger Local Network dialog and check user answer? and you can use it from objc as well without any effort.

But if you have a pure ObjC project and don't want to add swift files this is the similar approach that works the same:

// LocalNetworkPrivacy.h

@interface LocalNetworkPrivacy : NSObject

- (void)checkAccessState:(void (^)(BOOL))completion;

@end

// LocalNetworkPrivacy.m

#import <UIKit/UIKit.h>
#import "LocalNetworkPrivacy.h"

@interface LocalNetworkPrivacy () <NSNetServiceDelegate>

@property (nonatomic) NSNetService *service;
@property (nonatomic) void (^completion)(BOOL);
@property (nonatomic) NSTimer *timer;
@property (nonatomic) BOOL publishing;

@end

@implementation LocalNetworkPrivacy

- (instancetype)init {
if (self = [super init]) {
self.service = [[NSNetService alloc] initWithDomain:@"local." type:@"_lnp._tcp." name:@"LocalNetworkPrivacy" port:1100];
}
return self;
}

- (void)dealloc {
[self.service stop];
}

- (void)checkAccessState:(void (^)(BOOL))completion {
self.completion = completion;

self.timer = [NSTimer scheduledTimerWithTimeInterval:2 repeats:YES block:^(NSTimer * _Nonnull timer) {
if (UIApplication.sharedApplication.applicationState != UIApplicationStateActive) {
return;
}

if (self.publishing) {
[self.timer invalidate];
self.completion(NO);
}
else {
self.publishing = YES;
self.service.delegate = self;
[self.service publish];
}
}];
}

#pragma mark - NSNetServiceDelegate

- (void)netServiceDidPublish:(NSNetService *)sender {
[self.timer invalidate];
self.completion(YES);
}

@end

How to use:

LocalNetworkPrivacy* localNetworkPrivacy = [LocalNetworkPrivacy new];
[localNetworkPrivacy checkAccessState:^(BOOL granted) {
NSLog(@"Granted: %@", granted ? @"YES" : @"NO");
}];

NOTE: You must set NSLocalNetworkUsageDescription and add "_lnp._tcp." to NSBonjourServices into your Info.plist.

What triggers the would like to find and connect to devices on your local network permission notification on iOS 14?

Apple (Eskimo on the Dev Forums) released a FAQ providing more details around this alert:
https://developer.apple.com/forums/thread/663858

Particularly, providing more info as to what triggers this alert is FAQ-2:
https://developer.apple.com/forums/thread/663874

What operations require local network access?

The general rule is that outgoing traffic to a local network address
requires that the user grant your app local network access. Common
scenarios include:

  • Making an outgoing TCP connection — yes
  • Listening for and accepting incoming TCP connections — no
  • Sending a UDP unicast — yes
  • Sending a UDP multicast — yes
  • Sending a UDP broadcast — yes
  • Receiving an incoming UDP unicast — no
  • Receiving an incoming UDP multicast — yes
  • Receiving an incoming UDP broadcast — yes

These TCP and UDP checks are done at the lowest levels of the system
and thus apply to all networking APIs. This includes Network
framework, BSD Sockets, NSStream, NSURLSession and WKWebView, and any
other protocols that you layer on top of those.

IMPORTANT Receiving an incoming UDP multicast or broadcast does not
currently require local network access but, because we hope to change
that in a future update, our advice right now is that you write your
code as if did (r. 69792887, 70017649).

Resolving link-local DNS names (those ending with local, per RFC 6762)
requires local network access. Again, this check applies to a wide
variety of APIs including <dns_sd.h>, <net_db.h>, Network framework,
NSStream, and NSURLSession.

Finally, all Bonjour operations require local network access:

  • Registering a service with Bonjour — yes
  • Browsing for Bonjour services — yes
  • Resolving a Bonjour service — yes

Again, these checks apply to all APIs that use Bonjour, including
<dns_sd.h>, Network framework, NSNetService, and Multipeer
Connectivity.

Note You must declare the Bonjour service types you use in your
Info.plist. See How do I map my Multipeer Connectivity service type to
an entry in the Bonjour services property? for details.

Bonjour-based services where you don’t see any details of the network
do not require local network access. These include:

  • AirPlay — no
  • Printing via UIKit — no

Local Network Permission dialog NOT showing up

It looks like the reason was that there was a router in the local network that does NOT support UPnP => Therefore, this dialog will NOT even be triggered.



Related Topics



Leave a reply



Submit