如何获取用户的国家/地区位置?

How can I get a user's country location?

由于 GDPR,我需要检查用户的位置 - 用户是否来自欧盟。到目前为止,我已经找到了这些解决方案 -

  1. Get Country using the Phone's language configuration如果用户使用美国英语版本,即使他可能来自其他国家/地区,也会产生误导)。

     String locale = context.getResources().getConfiguration().locale.getCountry();
    
  2. Get Location using the GPS需要 location coarse 权限,我不想添加,特别是因为 Android 6.0+ 运行时权限).

     private void getCountryCode(final Location location) {
         Helper.log(TAG, "getCountryCode");
    
         AsyncTask<Void, Void, String> countryCodeTask = new AsyncTask<Void, Void, String>() {
    
             final float latitude = (float) location.getLatitude();
             final float longitude = (float) location.getLongitude();
             // Helper.log(TAG, "latitude: " + latitude);
             List<Address> addresses = null;
             Geocoder gcd = new Geocoder(mContext);
             String code = null;
    
             @Override
             protected String doInBackground(Void... params) {
                 try {
                     addresses = gcd.getFromLocation(latitude, longitude, 1);
                     code = addresses.get(0).getCountryCode();
                 } 
                 catch (IOException e) {
                     e.printStackTrace();
                 }
                 return code;
             }
    
             @Override
             protected void onPostExecute(String code) {
                 Helper.log(TAG, "onPostExecute");
                 mCountryCodeListener.returnCountryCode(code);
             }
         };
    
         if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.GINGERBREAD_MR1) {
             countryCodeTask.execute();
         }
         else {
             countryCodeTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
         }
     }
    
  3. Get Location using the SIM card or Wi-Fi不能在没有SIM卡或Wi-Fi的桌子上使用,而我的应用程序可以在没有互联网连接或Wi-Fi的设备上使用-Fi).

     TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE);
     String countryCodeValue = tm.getNetworkCountryIso();
    

是否可以查到用户是否来自欧盟地区?

我不需要确切的位置,甚至国家也可以。

是否有其他方法可能也需要位置权限(不是粗略的位置权限也有帮助)?

请注意,这个问题不是任何其他问题的重复,因为我的情况没有被任何其他问题解决。

您已经提到了获得 Country Name 的所有可能选项,但还有一个选项。 如果您的应用程序具有访问互联网的权限,您也可以通过IP地址获取国家名称...

您也可以从 IP 地址中获取国家名称。获得 IP 地址后,将其传递给 ipstack API 以获取国家/地区名称。您可以免费制作10,000 requests/month

获取 IP 地址的方法有很多种(google)。一种方式如下:

public static String getLocalIpAddress() {
    try {
        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements();) {
            NetworkInterface intf = en.nextElement();
            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements();) {
                InetAddress inetAddress = enumIpAddr.nextElement();
                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                    return inetAddress.getHostAddress();
                }
            }
        }
    } catch (SocketException ex) {
        ex.printStackTrace();
    }
    return null;
}

将以下权限添加到 AndroidManifest.xml:

 <uses-permission android:name="android.permission.INTERNET" />
 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

查看此文档以了解如何使用 ipstack API:https://ipstack.com/documentation

用法:

https://api.ipstack.com/YOUR_IP_ADDRESS?access_key=YOUR_ACCESS_KEY

API 以 JSON 格式响应 134.201.250.155 IP 地址(如果需要,您也可以在 XML 中获取):

{
  "ip": "134.201.250.155",
  "hostname": "134.201.250.155",
  "type": "ipv4",
  "continent_code": "NA",
  "continent_name": "North America",
  "country_code": "US",
  "country_name": "United States",
  "region_code": "CA",
  "region_name": "California",
  "city": "Los Angeles",
  "zip": "90013",
  "latitude": 34.0453,
  "longitude": -118.2413,
  "location": {
    "geoname_id": 5368361,
    "capital": "Washington D.C.",
    "languages": [
        {
          "code": "en",
          "name": "English",
          "native": "English"
        }
    ],
    "country_flag": "https://assets.ipstack.com/images/assets/flags_svg/us.svg",
    "country_flag_emoji": "",
    "country_flag_emoji_unicode": "U+1F1FA U+1F1F8",
    "calling_code": "1",
    "is_eu": false
  },
  "time_zone": {
    "id": "America/Los_Angeles",
    "current_time": "2018-03-29T07:35:08-07:00",
    "gmt_offset": -25200,
    "code": "PDT",
    "is_daylight_saving": true
  },
  "currency": {
    "code": "USD",
    "name": "US Dollar",
    "plural": "US dollars",
    "symbol": "$",
    "symbol_native": "$"
  },
  "connection": {
    "asn": 25876,
    "isp": "Los Angeles Department of Water & Power"
  }
  "security": {
    "is_proxy": false,
    "proxy_type": null,
    "is_crawler": false,
    "crawler_name": null,
    "crawler_type": null,
    "is_tor": false,
    "threat_level": "low",
    "threat_types": null
  }
}

您可以获取 MCC/MNC 代码,因为您对国家 MCC(移动国家代码)感兴趣。

如果您的应用程序中没有 GPS 功能,而您只想为此添加和使用它,这会影响用户体验,我建议您应该假设用户已经在该地区做你必须做的事。

只为这种情况获取位置(并耗尽电池)是一种矫枉过正。

您可以通过请求 URL http://adservice.google.com/getconfig/pubvendors 来检查用户是否在欧盟。它会给你这样的答案:

{"is_request_in_eea_or_unknown":true}

我在某处读到过 Android consent SDK 的工作方式。

使用 Google Consent SDK 检查用户是否在欧洲经济区 (EEA)。

build.gradle中添加:

implementation 'com.google.android.ads.consent:consent-library:1.0.6'

ConsentInformation.getInstance(context).requestConsentInfoUpdate( ... )用作described in the documentation

然后使用:

ConsentInformation.getInstance(context).isRequestLocationInEeaOrUnknown()

如果函数 returns true,请将 GDPR 规则应用于您的应用。

另一种方法是跟踪 IP 位置,但如果用户使用 VPN 或代理,这可能不起作用。

这是 IP 定位 api 服务的示例: https://ip-api.com/