PermissionsKit icon indicating copy to clipboard operation
PermissionsKit copied to clipboard

Local Network Permission

Open z234009184 opened this issue 3 years ago • 19 comments

Feature Description Describe what functionality you want to see.

Thank you for your development of this library. I have a small demand. When the application is started for the first time, it mistakenly touches that it is not allowed to use the network permission. How can I know that the user does not open the network permission and let the user go to the setting page to open the network permission?

let data = CTCellularData()
        let state = data.restrictedState
        switch state {
          case .notRestricted:
          DispatchQueue.main.async {
              authorizedHandler()
          }
          default:
          DispatchQueue.main.async {
              unAuthorizedHandler()
          }
        }

z234009184 avatar Feb 26 '22 12:02 z234009184

Hi! Which permission do you using for request?

ivanvorobei avatar Feb 27 '22 15:02 ivanvorobei

image

Now SPPermission can not support Network permission Please help

z234009184 avatar Mar 01 '22 08:03 z234009184

So you want to add network permission, right?

ivanvorobei avatar Mar 01 '22 08:03 ivanvorobei

I'd appreciate it if you could

z234009184 avatar Mar 02 '22 01:03 z234009184

I am also very interested in the wireless data permission, I guess that is what you called the network permission right?

yuchenz27 avatar Mar 07 '22 07:03 yuchenz27

Yes,in China, when the application is started for the first time, it will apply to the system for network permission. If the user accidentally prohibits the network permission, the application will not be able to access the network until the user goes to the setting center to open the wireless network permission.

z234009184 avatar Mar 08 '22 14:03 z234009184

image

z234009184 avatar Mar 08 '22 14:03 z234009184

@z234009184 fully right, no way to simple manage this permission. I can to get state of permission and request it once. But sorry, busy with my work now.

ivanvorobei avatar Mar 08 '22 14:03 ivanvorobei

@z234009184 are you still need this permission?

ivanvorobei avatar Apr 17 '22 12:04 ivanvorobei

@z234009184 are you still need this permission?

Yes, I think it is necessary to add network permissions as an extension, so that you can only use the PermissionsKit

z234009184 avatar Apr 17 '22 12:04 z234009184

Ok, doing it

ivanvorobei avatar Apr 17 '22 13:04 ivanvorobei

I did some refresh. Available one way to request permission, but no way to get status correctly. Each time need to do request permission for get state. So apple hide API and its doesn't look like solution. Any ideas?

ivanvorobei avatar Apr 17 '22 16:04 ivanvorobei

Hey I am coming from #280. I think the permission discussed in this issue is Wireless Data Permission not Local Network Permission.

I am looking for solutions for both of these permissions.

yuchenz27 avatar Apr 20 '22 07:04 yuchenz27

@yuchenz27 I think you right, my bad. If you have code share with me, I am ready to integrate it shortly

ivanvorobei avatar Apr 20 '22 07:04 ivanvorobei

@ivanvorobei There is no official access to these permissions. I have done some research on the Internet and found the following candidate solutions.

For Wireless Data Permission, this code works https://stackoverflow.com/questions/25623272/how-to-use-scnetworkreachability-in-swift?noredirect=1&lq=1

import SystemConfiguration

func connectedToNetwork() -> Bool {

    var zeroAddress = sockaddr_in()
    zeroAddress.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
    zeroAddress.sin_family = sa_family_t(AF_INET)

    guard let defaultRouteReachability = withUnsafePointer(to: &zeroAddress, {
        $0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
            SCNetworkReachabilityCreateWithAddress(nil, $0)
        }
    }) else {
        return false
    }

    var flags: SCNetworkReachabilityFlags = []
    if !SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags) {
        return false
    }

    let isReachable = flags.contains(.reachable)
    let needsConnection = flags.contains(.connectionRequired)

    return (isReachable && !needsConnection)
}

For Local Network Permission, this code works https://stackoverflow.com/questions/63940427/ios-14-how-to-trigger-local-network-dialog-and-check-user-answer/65800221#65800221

import Foundation
import Network

@available(iOS 14.0, *)
public class LocalNetworkAuthorization: NSObject {
    private var browser: NWBrowser?
    private var netService: NetService?
    private var completion: ((Bool) -> Void)?
    
    public func requestAuthorization(completion: @escaping (Bool) -> Void) {
        self.completion = completion
        
        // Create parameters, and allow browsing over peer-to-peer link.
        let parameters = NWParameters()
        parameters.includePeerToPeer = true
        
        // Browse for a custom service type.
        let browser = NWBrowser(for: .bonjour(type: "_bonjour._tcp", domain: nil), using: parameters)
        self.browser = browser
        browser.stateUpdateHandler = { newState in
            switch newState {
            case .failed(let error):
                print(error.localizedDescription)
            case .ready, .cancelled:
                break
            case let .waiting(error):
                print("Local network permission has been denied: \(error)")
                self.reset()
                self.completion?(false)
            default:
                break
            }
        }
        
        self.netService = NetService(domain: "local.", type:"_lnp._tcp.", name: "LocalNetworkPrivacy", port: 1100)
        self.netService?.delegate = self
        
        self.browser?.start(queue: .main)
        self.netService?.publish()
    }
    
    private func reset() {
        self.browser?.cancel()
        self.browser = nil
        self.netService?.stop()
        self.netService = nil
    }
}

@available(iOS 14.0, *)
extension LocalNetworkAuthorization : NetServiceDelegate {
    public func netServiceDidPublish(_ sender: NetService) {
        self.reset()
        print("Local network permission has been granted")
        completion?(true)
    }
}

The problem for these two solutions is that they trigger the permission dialog and return the permission status through a single function, so there is no way to just check the permission status without triggering the dialog for the first time (which makes sense because we will trigger the dialog for the first time anyway).

In addition, for the second code snippet, if the user allows the permission, it will take about 0.5s to get the permission status (which is success) every time in the future sessions. On the contrary, if the user denies the permission, it will instantly return the denies status in the future sessions.

yuchenz27 avatar Apr 20 '22 09:04 yuchenz27

@yuchenz27 thanks for your research! I will think how I can integrate it

ivanvorobei avatar Apr 20 '22 09:04 ivanvorobei

@ivanvorobei no problem, your plugin is awesome. I don't think those solutions are perfect, probably there is a better way.

yuchenz27 avatar Apr 20 '22 09:04 yuchenz27

Just a reminder, the code I left for Wireless Data Permission is not actually for the permission. It just checks if there is a valid network connection. So if you grant the permission and close the cellular data on your iPhone, it will still return false.

yuchenz27 avatar Apr 21 '22 03:04 yuchenz27

@yuchenz27 both permissions not true public API, so it make some logic and happen request. Its not clean solution, but best which we can propose to developers.

ivanvorobei avatar Apr 21 '22 08:04 ivanvorobei