Apple Local Push Connectivity with error nil?

I'm trying to configure Local Push Connectivity. I already have Local Push Entitlement, and have install a provisioning profile with local push entitlement. It's build fine but when app start, PushProvider didn't active and start and Push Manager show error nil. I have done every instructions that sample code have provided.

This is my project. In my application target, I have a bundle id com.my_team_name.my_app_name and in the app group name group.com.my_team_name.my_app_name

In the .entitlement, I've set the required configuration:

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>com.apple.developer.networking.networkextension</key>
    <array>
        <string>app-push-provider</string>
    </array>
    <key>com.apple.developer.networking.wifi-info</key>
    <true/>
    <key>com.apple.security.application-groups</key>
    <array>
        <string>group.com.my_team_name.my_app_name</string>
    </array>
</dict>
</plist>

Info.plist has noting to change And I have a PushManager Class with this code

class AppPushManager: NSObject, NEAppPushDelegate{
    func appPushManager(_ manager: NEAppPushManager, didReceiveIncomingCallWithUserInfo userInfo: [AnyHashable : Any] = [:]) {
        
    }
    
    static let shared = AppPushManager()
    
    private var pushManager: NEAppPushManager = NEAppPushManager()
    private let pushManagerDescription = "PushDefaultConfiguration"
    private let pushProviderBundleIdentifier = "com.my_team_name.my_app_name.PushProvider"
    
    func initialize() {
        if pushManager.delegate == nil {
            pushManager.delegate = self
        }
        
        pushManager.localizedDescription = pushManagerDescription
        pushManager.providerBundleIdentifier = pushProviderBundleIdentifier
        pushManager.isEnabled = true

        pushManager.providerConfiguration = [
            "host": "my_server.local"
        ]

        pushManager.matchSSIDs = ["my_wifi_ssid"]
        
        pushManager.saveToPreferences(completionHandler: { error in
            print("error? \(String(describing: error))")
            print("is active: \(pushManager.isActive)")
        })
    }
}

In my extension, A PushProvider Target. I have a bundle id com.my_team_name.my_app_name.PushProvider

and in the app group name group.com.my_team_name.my_app_name

In the Info.plist of my extension, I've added the required configuration:

<key>NSExtension</key>
<dict>
    <key>NSExtensionPointIdentifier</key>
    <string>com.apple.networkextension.app-push</string>
    <key>NSExtensionPrincipalClass</key>
    <string>$(PRODUCT_MODULE_NAME).PushProvider</string>
</dict>

the .entitlement file have the same contents as the application. and I have created the extension class "PushProvider.swift" as follow:

class PushProvider: NEAppPushProvider {
    ...
}

When I run the application, I got this printed out

error? nil
is active: false

I think it might be something with providerBundleIdentifier in Push Manager. Have anyone know what I've missing?

Accepted Reply

Seem to working now I'm confuse with 'pushManager.isActive` always show false, but it actually run. Debugging by this method https://developer.apple.com/forums/thread/11241?answerId=32880022#32880022 help me a lot.

  • Always checking that pushManager.matchSSIDs was correct.

  • Right, if the matchSSIDs property loses track of the associated network then the provider will stop or not start at all.

Add a Comment

Replies

I would make sure that you are running this project on a development device with the debugger attached, and the console.app window filtering the logs from your app. That should tell you what is happening here.

From the container app, make sure that you are going through the path of:

  1. loadAllFromPreferences to create the initial NEAppPushManager:
private var pushManager: NEAppPushManager?

...

NEAppPushManager.loadAllFromPreferences { managers, error in
    precondition(Thread.isMainThread)
    if let error = error {
        os_log("Error loading NEAppPushManager: %{public}@", error.localizedDescription)
        return
    }

    var manager: NEAppPushManager
    if let foundManager = managers?.first, NetworkManager.isOurManager(foundManager) {
        manager = foundManager
        os_log("Did find an existing NEAppPushManager, assigning the instance")
    } else {
        manager = NEAppPushManager()
        os_log("Did not find a NEAppPushManager, creating a new instance")
    }
    manager.delegate = self
    self.pushManager = manager
    
    // Setup Push Manager
    self.pushManager?.localizedDescription = ""
    self.pushManager?.providerBundleIdentifier = "com.my_team_name.my_app_name.PushProvider"
    self.pushManager?.isEnabled = true
    self.pushManager?.providerConfiguration = [
        "host": "hostinfo.com"
    ]
    self.pushManager?.matchSSIDs = ["NetworkSSID"]
    
}

  1. Then load and save the NEAppPushManager:
guard let localManager = self.pushManager else {
    // Handle the failed unwrap
    return
}

localManager.loadFromPreferences { error in
    precondition(Thread.isMainThread)
    
    if let error = error {
        os_log("Error loading NEAppPushManager: %{public}@", error.localizedDescription)
        // Handle error
        return
    }
    
    localManager.saveToPreferences { error in
        if let nsError = error as NSError? {
            os_log("did not save configuration, error: %{public}@", nsError.localizedDescription)
            // Handle error
            return
        }
        os_log("Did Save Configuration Successfully")
        // Checkout logs here
    }
}
  1. Configure the NEAppPushProvider with a constructor to see if it is even being reached after the saveToPreferences call.
class PushProvider: NEAppPushProvider {
   
    override init() {
        os_log("AppPushProvider init")
        super.init()
    }
    
    // MARK: - NEAppPushProvider Life Cycle
    

    override func start(completionHandler: @escaping (Error?) -> Void) {
        os_log("AppPushProvider start")
        
        completionHandler(error)
    }
    ...
}

Try this out and see where this gets you.

Matt Eaton
DTS Engineering, CoreOS
meaton3@apple.com
  • Hi, I got this error Optional(Error Domain=NEAppPushErrorDomain Code=3 "(null)

    And I get some error form PushManager

    <NEAppPushManager: 0x281512160>: Failed to save the configuration: Error Domain=NEConfigurationErrorDomain Code=9 "configuration is unchanged" UserInfo={NSLocalizedDescription=configuration is unchanged}

    PushProvider still not active.

  • I'm able to run Simple Push App, so it's mean that I did something wrong. but I have a few question, I can't debug PushProvider. It say Xcode won't pause at this breakpoint because it has not been resolved Resolving it requires that: The line at the breakpoint is compiled. The compiler generates debug information that is not stripped out (check the Build Settings). The library for the breakpoint is loaded.

Add a Comment

After a lot of trying I found that error

<NEAppPushManager: 0x281512160>: Failed to save the configuration: Error Domain=NEConfigurationErrorDomain Code=9 "configuration is unchanged" UserInfo={NSLocalizedDescription=configuration is unchanged}

it is what it means. When I change setting, error disappears. But PushProvider still not active. both function override init()  and 'override func start()' in PushProvider class was not executed at all.

When I change setting, error disappears. But PushProvider still not active. both function override init() and 'override func start()' in PushProvider class was not executed at all.

Right, it does sound like you have a configuration issue here if your can execute saveToPreferences without an error but the provider is not being hit at all.

Are there any other logs that may indicate what is happening in the Console.app? I would recommend deleting the app and network configuration entirely from your test device and then start over again. Then, reproduce the error while your device is recording logs to the console and see if that gives you any more clues as to what is happening.

Seem to working now I'm confuse with 'pushManager.isActive` always show false, but it actually run. Debugging by this method https://developer.apple.com/forums/thread/11241?answerId=32880022#32880022 help me a lot.

  • Always checking that pushManager.matchSSIDs was correct.

  • Right, if the matchSSIDs property loses track of the associated network then the provider will stop or not start at all.

Add a Comment