iOS是否可以在未经许可的情况下获取用户的大概位置?

问题描述 投票:0回答:2

您建议如何在未经用户许可的情况下获取用户所在国家/地区? 是否可以使用手机信号塔三角测量或 WiFi 定位来获得大概位置? 您建议使用什么其他方法来猜测用户所在的国家/地区?

ios objective-c swift location
2个回答
7
投票

来自苹果的文档

重要提示:除了不可用的硬件外,用户还拥有 拒绝应用程序访问位置服务的选项 数据。在应用程序初次使用期间,核心位置 框架提示用户确认使用定位服务 是可以接受的。如果用户拒绝请求,CLLocationManager 对象在将来向其委托报告适当的错误 要求。您还可以检查应用程序的显式授权 使用authorizationStatus方法获取状态。

所以即使存在一些巧妙的方法来避免许可,你也会在审核阶段被拒绝。


您建议还有什么其他方法来猜测用户是哪个国家/地区 位于?

您可以使用IP地址获取此信息。


Swift 4 - 获取设备的IP地址:

在桥接标头中添加

#include<ifaddrs.h>

这是获取IP地址所需的框架。

class func getIPAddress() -> String? {
        var address: String?
        var ifaddr: UnsafeMutablePointer<ifaddrs>? = nil
        if getifaddrs(&ifaddr) == 0 {
            var ptr = ifaddr
            while ptr != nil {
                defer { ptr = ptr?.pointee.ifa_next }

                let interface = ptr?.pointee
                let addrFamily = interface?.ifa_addr.pointee.sa_family
                if addrFamily == UInt8(AF_INET) || addrFamily == UInt8(AF_INET6) {

                    if let name: String = String(cString: (interface?.ifa_name)!), name == "en0" {
                        var hostname = [CChar](repeating: 0, count: Int(NI_MAXHOST))
                        getnameinfo(interface?.ifa_addr, socklen_t((interface?.ifa_addr.pointee.sa_len)!), &hostname, socklen_t(hostname.count), nil, socklen_t(0), NI_NUMERICHOST)
                        address = String(cString: hostname)
                    }
                }
            }
            freeifaddrs(ifaddr)
        }
        return address
}

使用IP地址获取国家/地区

您可以首先尝试

http://ip-api.com/json
,它会返回一个 JSON,如其 API 页面上所解释的那样。

然后您可以将此 JSON 字符串转换为字典并访问数据。

func getIpLocation(completion: @escaping(NSDictionary?, Error?) -> Void) { let url = URL(string: "http://ip-api.com/json")! var request = URLRequest(url: url) request.httpMethod = "GET" URLSession.shared.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) in DispatchQueue.main.async { if let content = data { do { if let object = try JSONSerialization.jsonObject(with: content, options: .allowFragments) as? NSDictionary { completion(object, error) } else { // TODO: Create custom error. completion(nil, nil) } } catch { // TODO: Create custom error. completion(nil, nil) } } else { completion(nil, error) } } }).resume() }

此函数返回字典或错误(在解决 TODO 之后)。假设您将使用结果来更新 UI,则在主线程上调用

completion

。如果没有,您可以删除 
DispatchQueue.main.async { }


4
投票
我使用以下方法成功获得了该国家/地区,而无需请求位置权限:

import MapKit class CountryDectectorViewController: UIViewController { var didDetectCountryCode: ((String?) -> Void)? override func viewDidLoad() { super.viewDidLoad() // Map view setup let mapView = MKMapView() view.addSubview(mapView) mapView.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ mapView.topAnchor.constraint(equalTo: view.topAnchor), mapView.bottomAnchor.constraint(equalTo: view.bottomAnchor), mapView.leadingAnchor.constraint(equalTo: view.leadingAnchor), mapView.trailingAnchor.constraint(equalTo: view.trailingAnchor) ]) mapView.layoutIfNeeded() // Reverse geocoding map region center let location = CLLocation( latitude: mapView.region.center.latitude, longitude: mapView.region.center.longitude ) CLGeocoder().reverseGeocodeLocation(location) { placemarks, _ in self.didDetectCountryCode?(placemarks?.first?.isoCountryCode) } } }
ISO 国家代码可以通过以下方式获取:

let controller = CountryDectectorViewController() controller.didDetectCountryCode = { countryCode in print(countryCode) } controller.loadViewIfNeeded()

一些背景

我意识到 MapKit 已经有了这些信息,因为每次显示

MKMapView

 时,该区域都会自动设置为适合当前用户所在的国家/地区。使用这个假设,我需要找到一个解决方案来加载地图而不显示它,然后对中心坐标进行反向地理编码以识别国家/地区。

我实施此解决方案时考虑到了我发现的以下限制:

    最好不要请求用户权限
  • 设备区域设置不被认为是可靠的替代方案
  • 检测 sim 运营商实际上返回原始运营商国家/地区,而不是当前连接的运营商(通过漫游)
  • 通过 IP 检索国家可以使用最近变得更流行的 VPN 轻松伪造
© www.soinside.com 2019 - 2024. All rights reserved.