Android 我在哪里?- 获取国家

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3659809/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-20 11:12:49  来源:igfitidea点击:

Where am I? - Get country

androidgeolocation

提问by DonGru

An android mobile actually does know quite well where it is - but is there a way of retrieving the country by something like a country code?

安卓手机实际上很清楚它在哪里——但是有没有办法通过国家代码之类的东西来检索国家?

No need of knowing the exact GPS position - the countryis sufficient

无需知道确切的 GPS 位置 -国家就足够了

I first thought of using the time zone, but actually I need more information than that since it makes a difference if the location is New York or Lima.

我首先想到使用时区,但实际上我需要比这更多的信息,因为位置是纽约或利马会有所不同。

The background of the question:I have an application that uses temperature values, and I'd like to set the default unit either to Celsius or Fahrenheit, depending on whether the location is US or outside

问题的背景:我有一个使用温度值的应用程序,我想将默认单位设置为摄氏度或华氏度,具体取决于位置是美国还是国外

采纳答案by stealthcopter

This will get the country codeset for the phone (phones language, NOT user location):

这将获得为电话设置的国家/地区代码(电话语言,而不是用户位置):

 String locale = context.getResources().getConfiguration().locale.getCountry(); 

can also replace getCountry() with getISO3Country()to get a 3 letter ISO code for the country. This will get the country name:

也可以用getISO3Country()替换 getCountry()以获得该国家/地区的 3 个字母 ISO 代码。这将获得国家名称

 String locale = context.getResources().getConfiguration().locale.getDisplayCountry();

This seems easier than the other methods and rely upon the localisation settings on the phone, so if a US user is abroad they probably still want Fahrenheit and this will work :)

这似乎比其他方法更容易,并且依赖于手机上的本地化设置,所以如果美国用户在国外,他们可能仍然需要华氏度,这会起作用:)

Editors note: This solution has nothing to do with the location of the phone. It is constant. When you travel to Germany locale will NOT change. In short: locale != location.

编者注:此解决方案与手机的位置无关。它是恒定的。当您前往德国时,语言环境不会改变。简而言之:语言环境!= 位置。

回答by caw

/**
 * Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
 * @param context Context reference to get the TelephonyManager instance from
 * @return country code or null
 */
public static String getUserCountry(Context context) {
    try {
        final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        final String simCountry = tm.getSimCountryIso();
        if (simCountry != null && simCountry.length() == 2) { // SIM country code is available
            return simCountry.toLowerCase(Locale.US);
        }
        else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable)
            String networkCountry = tm.getNetworkCountryIso();
            if (networkCountry != null && networkCountry.length() == 2) { // network country code is available
                return networkCountry.toLowerCase(Locale.US);
            }
        }
    }
    catch (Exception e) { }
    return null;
}

回答by shine_joseph

Use this link http://ip-api.com/json,this will provide all the information as json. From this json you can get the country easily. This site works using your current IP,it automatically detects the IP and sendback details.

使用此链接http://ip-api.com/json,这将提供 json 形式的所有信息。从这个 json 你可以很容易地得到这个国家。该站点使用您当前的 IP 工作,它会自动检测 IP 和发回详细信息。

Docs http://ip-api.com/docs/api:jsonHope it helps.

文档http://ip-api.com/docs/api:json希望它有所帮助。

Example json

示例 json

{
  "status": "success",
  "country": "United States",
  "countryCode": "US",
  "region": "CA",
  "regionName": "California",
  "city": "San Francisco",
  "zip": "94105",
  "lat": "37.7898",
  "lon": "-122.3942",
  "timezone": "America/Los_Angeles",
  "isp": "Wikimedia Foundation",
  "org": "Wikimedia Foundation",
  "as": "AS14907 Wikimedia US network",
  "query": "208.80.152.201"
}

note: As this is a 3rd party solution, only use if others didn't work.

注意:由于这是第 3 方解决方案,只有在其他解决方案不起作用时才使用。

回答by DonGru

Actually I just found out that there is even one more way of getting a country code, using the getSimCountryIso() method of TelephoneManager:

实际上,我刚刚发现还有一种获取国家/地区代码的方法,使用以下的 getSimCountryIso() 方法TelephoneManager

TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String countryCode = tm.getSimCountryIso();

Since it is the sim code it also should not change when traveling to other countries.

由于它是 sim 代码,因此在前往其他国家/地区时也不应更改。

回答by EboMike

First, get the LocationManager. Then, call LocationManager.getLastKnownPosition. Then create a GeoCoder and call GeoCoder.getFromLocation. Do this is in a separate thread!! This will give you a list of Addressobjects. Call Address.getCountryNameand you got it.

首先,获取 LocationManager。然后,调用LocationManager.getLastKnownPosition。然后创建一个 GeoCoder 并调用GeoCoder.getFromLocation. 在单独的线程中执行此操作!!这将为您提供一个Address对象列表。打电话Address.getCountryName,你就明白了。

Keep in mind that the last known position can be a bit stale, so if the user just crossed the border, you may not know about it for a while.

请记住,最后一个已知位置可能有点陈旧,因此如果用户刚刚越过边界,您可能暂时不知道它。

回答by Dave Webb

You could use getNetworkCountryIso()from TelephonyManagerto get the country the phone is currently in (although apparently this is unreliable on CDMA networks).

您可以使用getNetworkCountryIso()fromTelephonyManager获取手机当前所在的国家/地区(尽管这在 CDMA 网络上显然不可靠)。

回答by Nativ

Here is a complete solution based on the LocationManager and as fallbacks the TelephonyManager and the Network Provider's locations. I used the above answer from @Marco W. for the fallback part(great answer as itself!).

这是一个基于 LocationManager 的完整解决方案,作为后备,TelephonyManager 和网络提供商的位置。我使用@Marco W. 的上述答案作为后备部分(本身就是很好的答案!)。

Note: the code contains PreferencesManager, this is a helper class that saves and loads data from SharedPrefrences. I'm using it to save the country to S"P, I'm only getting the country if it is empty. For my product I don't really care for all the edge cases(user travels abroad and so on).

注意:代码中包含 PreferencesManager,这是一个辅助类,用于从 SharedPrefences 中保存和加载数据。我用它来将国家保存到 S"P,如果国家是空的,我只会得到国家。对于我的产品,我并不真正关心所有的边缘情况(用户出国旅行等)。

public static String getCountry(Context context) {
    String country = PreferencesManager.getInstance(context).getString(COUNTRY);
    if (country != null) {
        return country;
    }

    LocationManager locationManager = (LocationManager) PiplApp.getInstance().getSystemService(Context.LOCATION_SERVICE);
    if (locationManager != null) {
        Location location = locationManager
                .getLastKnownLocation(LocationManager.GPS_PROVIDER);
        if (location == null) {
            location = locationManager
                    .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }
        if (location == null) {
            log.w("Couldn't get location from network and gps providers")
            return
        }
        Geocoder gcd = new Geocoder(context, Locale.getDefault());
        List<Address> addresses;
        try {
            addresses = gcd.getFromLocation(location.getLatitude(),
                    location.getLongitude(), 1);

            if (addresses != null && !addresses.isEmpty()) {
                country = addresses.get(0).getCountryName();
                if (country != null) {
                    PreferencesManager.getInstance(context).putString(COUNTRY, country);
                    return country;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    country = getCountryBasedOnSimCardOrNetwork(context);
    if (country != null) {
        PreferencesManager.getInstance(context).putString(COUNTRY, country);
        return country;
    }
    return null;
}


/**
 * Get ISO 3166-1 alpha-2 country code for this device (or null if not available)
 *
 * @param context Context reference to get the TelephonyManager instance from
 * @return country code or null
 */
private static String getCountryBasedOnSimCardOrNetwork(Context context) {
    try {
        final TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        final String simCountry = tm.getSimCountryIso();
        if (simCountry != null && simCountry.length() == 2) { // SIM country code is available
            return simCountry.toLowerCase(Locale.US);
        } else if (tm.getPhoneType() != TelephonyManager.PHONE_TYPE_CDMA) { // device is not 3G (would be unreliable)
            String networkCountry = tm.getNetworkCountryIso();
            if (networkCountry != null && networkCountry.length() == 2) { // network country code is available
                return networkCountry.toLowerCase(Locale.US);
            }
        }
    } catch (Exception e) {
    }
    return null;
}

回答by 4gus71n

String locale = context.getResources().getConfiguration().locale.getCountry(); 

Is deprecated. Use this instead:

已弃用。改用这个:

Locale locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
    locale = context.getResources().getConfiguration().getLocales().get(0);
} else {
    locale = context.getResources().getConfiguration().locale;
}

回答by MarGin

For some devices, if the default language is set different (an indian can set English (US)) then

对于某些设备,如果默认语言设置不同(印度人可以设置英语(美国)),则

context.getResources().getConfiguration().locale.getDisplayCountry();

will give wrong value .So this method is non reliable

会给出错误的值。所以这种方法是不可靠的

Also, getNetworkCountryIso() method of TelephonyManager will not work on devices which don't have SIM card (WIFI tablets).

此外,TelephonyManager 的 getNetworkCountryIso() 方法不适用于没有 SIM 卡的设备(WIFI 平板电脑)。

If a device doesn't have SIM then we can use Time Zone to get the country. For countries like India, this method will work

如果设备没有 SIM 卡,那么我们可以使用时区来获取国家/地区。对于像印度这样的国家,这种方法会奏效

sample code used to check the country is India or not (Time zone id : asia/calcutta)

用于检查国家是否为印度的示例代码(时区 ID:asia/calcutta)

private void checkCountry() {


    TelephonyManager telMgr = (TelephonyManager) getSystemService(Context.TELEPHONY_SERVICE);
    if (telMgr == null)
        return;

    int simState = telMgr.getSimState();

    switch (simState) {
        //if sim is not available then country is find out using timezone id
        case TelephonyManager.SIM_STATE_ABSENT:
            TimeZone tz = TimeZone.getDefault();
            String timeZoneId = tz.getID();
            if (timeZoneId.equalsIgnoreCase(Constants.INDIA_TIME_ZONE_ID)) {
               //do something
            } else {
               //do something
            }
            break;

            //if sim is available then telephony manager network country info is used
        case TelephonyManager.SIM_STATE_READY:

           TelephonyManager tm = (TelephonyManager) this.getSystemService(Context.TELEPHONY_SERVICE);
            if (tm != null) {
                String countryCodeValue = tm.getNetworkCountryIso();
                //check if the network country code is "in"
                if (countryCodeValue.equalsIgnoreCase(Constants.NETWORK_INDIA_CODE)) {
                   //do something
                }

                else {
                   //do something
                }

            }
            break;

    }
}

回答by Steve

Using GPS with latitude and longitude, we can get the Country code.

使用带有经纬度的 GPS,我们可以获得国家代码。

If we use telephony, it won't work if we are not using sim card and in locale, based on language, it show the country code in wrong way.

如果我们使用电话,如果我们不使用 SIM 卡并且在语言环境中,根据语言,它会以错误的方式显示国家/地区代码,则它将无法工作。

MainActivity.java:

主活动.java:

    GPSTracker gpsTrack;
    public static double latitude = 0;
    public static double longitude = 0;

    gpsTrack = new GPSTracker(TabHomeActivity.this);

        if (gpsTrack.canGetLocation()) {
            latitude = gpsParty.getLatitude();
            longitude = gpsParty.getLongitude();

            Log.e("GPSLat", "" + latitude);
            Log.e("GPSLong", "" + longitude);

        } else {
            gpsTrack.showSettingsAlert();

            Log.e("ShowAlert", "ShowAlert");

        }

        countryCode = getAddress(TabHomeActivity.this, latitude, longitude);

        Log.e("countryCode", ""+countryCode);

   public String getAddress(Context ctx, double latitude, double longitude) {
    String region_code = null;
    try {
        Geocoder geocoder = new Geocoder(ctx, Locale.getDefault());
        List<Address> addresses = geocoder.getFromLocation(latitude, longitude, 1);
        if (addresses.size() > 0) {
            Address address = addresses.get(0);


            region_code = address.getCountryCode();


        }
    } catch (IOException e) {
        Log.e("tag", e.getMessage());
    }

    return region_code;
}

GPSTracker.java:

GPSTracker.java:

import android.app.AlertDialog;
import android.app.Service;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.provider.Settings;
import android.util.Log;

public class GPSTracker extends Service implements LocationListener {

    private final Context mContext;

    // flag for GPS status
    boolean isGPSEnabled = false;

    // flag for network status
    boolean isNetworkEnabled = false;

    // flag for GPS status
    boolean canGetLocation = false;

    Location location; // location
    double latitude; // latitude
    double longitude; // longitude

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters

    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = 1000 * 60 * 1; // 1 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    public GPSTracker(Context context) {
        this.mContext = context;
        getLocation();
    }

    public Location getLocation() {
        try {
            locationManager = (LocationManager) mContext
                    .getSystemService(LOCATION_SERVICE);

            // getting GPS status
            isGPSEnabled = locationManager
                    .isProviderEnabled(LocationManager.GPS_PROVIDER);

            // getting network status
            isNetworkEnabled = locationManager
                    .isProviderEnabled(LocationManager.NETWORK_PROVIDER);

            if (!isGPSEnabled && !isNetworkEnabled) {
                // no network provider is enabled
            } else {
                this.canGetLocation = true;
                // First get location from Network Provider
                if (isNetworkEnabled) {
                    locationManager.requestLocationUpdates(
                            LocationManager.NETWORK_PROVIDER,
                            MIN_TIME_BW_UPDATES,
                            MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                    Log.d("Network", "Network");
                    if (locationManager != null) {
                        location = locationManager
                                .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
                        if (location != null) {
                            latitude = location.getLatitude();
                            longitude = location.getLongitude();
                        }
                    }
                }
                // if GPS Enabled get lat/long using GPS Services
                if (isGPSEnabled) {
                    if (location == null) {
                        locationManager.requestLocationUpdates(
                                LocationManager.GPS_PROVIDER,
                                MIN_TIME_BW_UPDATES,
                                MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                        Log.d("GPS Enabled", "GPS Enabled");
                        if (locationManager != null) {
                            location = locationManager
                                    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
                            if (location != null) {
                                latitude = location.getLatitude();
                                longitude = location.getLongitude();
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        return location;
    }

    /**
     * Stop using GPS listener
     * Calling this function will stop using GPS in your app
     * */
    public void stopUsingGPS(){
        if(locationManager != null){
            locationManager.removeUpdates(GPSTracker.this);
        }
    }

    /**
     * Function to get latitude
     * */
    public double getLatitude(){
        if(location != null){
            latitude = location.getLatitude();
        }

        // return latitude
        return latitude;
    }

    /**
     * Function to get longitude
     * */
    public double getLongitude(){
        if(location != null){
            longitude = location.getLongitude();
        }

        // return longitude
        return longitude;
    }

    /**
     * Function to check GPS/wifi enabled
     * @return boolean
     * */
    public boolean canGetLocation() {
        return this.canGetLocation;
    }



    public void showSettingsAlert() {
        final AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
        builder.setMessage("Your GPS seems to be disabled, do you want to enable it?")
                .setCancelable(false)
                .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                    public void onClick(@SuppressWarnings("unused") final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        mContext.startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
                    }
                })
                .setNegativeButton("No", new DialogInterface.OnClickListener() {
                    public void onClick(final DialogInterface dialog, @SuppressWarnings("unused") final int id) {
                        dialog.cancel();
                    }
                });
        final AlertDialog alert = builder.create();
        alert.show();
    }

    @Override
    public void onLocationChanged(Location location) {
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
    }

    @Override
    public IBinder onBind(Intent arg0) {
        return null;
    }

}

Log:

日志:

E/countryCode:IN

E/国家代码:IN

Edit:Use Fused Location Providerto get latitude and longitude update for better result.

编辑:使用Fused Location Provider获取经纬度更新以获得更好的结果。