Androidモバイルは実際にはどこにあるかをよく知っていますが、国コードのようなもので国を取得する方法はありますか?
GPSの正確な位置を知る必要はありません- 国で十分です
最初はタイムゾーンを使用することを考えましたが、実際には場所がニューヨークかリマかによって違いが生じるため、それよりも多くの情報が必要です。
質問の背景:温度値を使用するアプリケーションがあり、デフォルトの単位を摂氏または華氏に設定したい(場所が米国か外かによって異なる)。
Androidモバイルは実際にはどこにあるかをよく知っていますが、国コードのようなもので国を取得する方法はありますか?
GPSの正確な位置を知る必要はありません- 国で十分です
最初はタイムゾーンを使用することを考えましたが、実際には場所がニューヨークかリマかによって違いが生じるため、それよりも多くの情報が必要です。
質問の背景:温度値を使用するアプリケーションがあり、デフォルトの単位を摂氏または華氏に設定したい(場所が米国か外かによって異なる)。
回答:
これにより、電話に設定された国コードが取得されます(電話の言語、ユーザーの場所ではありません)。
String locale = context.getResources().getConfiguration().locale.getCountry();
getCountry()をgetISO3Country()に置き換えて、国の3文字のISOコードを取得することもできます。これは国名を取得します:
String locale = context.getResources().getConfiguration().locale.getDisplayCountry();
これは他の方法よりも簡単で、電話のローカリゼーション設定に依存しているため、米国のユーザーが海外にいる場合でも華氏を望んでおり、これは機能します:)
編集者注:このソリューションは、電話の場所とは関係ありません。一定です。ドイツに旅行するとき、ロケールは変更されません。つまり、ロケール!=の場所です。
/**
* 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;
}
getSimCountryIso
ように発言us
しgetNetworkCountryIso
ますfr
toLowerCase()
呼び出しを変更することができtoUpperCase()
ます。
このリンクhttp://ip-api.com/jsonを使用してください。これ により、すべての情報がjsonとして提供されます。このjsonから簡単に国を取得できます。このサイトは現在のIPを使用して動作し、IPとセンドバックの詳細を自動的に検出します。
ドキュメントhttp://ip-api.com/docs/api: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"
}
注:これはサードパーティのソリューションであるため、他のユーザーが機能しない場合にのみ使用してください。
実際、私はgetSimCountryIso()メソッドを使用して国コードを取得する方法が1つ以上あることを知りましたTelephoneManager
。
TelephonyManager tm = (TelephonyManager)getSystemService(Context.TELEPHONY_SERVICE);
String countryCode = tm.getSimCountryIso();
これはsimコードなので、他の国に旅行するときにも変更してはなりません。
まず、LocationManagerを取得します。次に、を呼び出しますLocationManager.getLastKnownPosition
。次に、GeoCoderを作成してを呼び出しますGeoCoder.getFromLocation
。これは別のスレッドで行います!! これにより、Address
オブジェクトのリストが表示されます。電話Address.getCountryName
してください。
最後の既知の位置は少し古くなっている可能性があるので、ユーザーが国境を越えただけではしばらくの間、その位置を知らない可能性があることに注意してください。
これは、LocationManagerに基づく完全なソリューションであり、フォールバックとしてTelephonyManagerとネットワークプロバイダーの場所を示します。私は上記の@Marco W.からの回答をフォールバック部分に使用しました(それ自体として素晴らしい回答です!)。
注:コードにはPreferencesManagerが含まれています。これはSharedPrefrencesからデータを保存およびロードするヘルパークラスです。国を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;
}
country = addresses.get(0).getCountryName();
あなたのコードには、国の完全な名前を変数に入れるコードがありますcountry
。同時に、メソッドgetCountryBasedOnSimCardOrNetwork(Context context)
では国のISOコードを返します。私はあなたが書きたかったと信じていますcountry = addresses.get(0).getCountryCode();
:-)
getNetworkCountryIso()
fromTelephonyManager
を使用して、電話が現在ある国を取得できます(明らかに、これはCDMAネットワークでは信頼できません)。
String locale = context.getResources().getConfiguration().locale.getCountry();
非推奨です。代わりにこれを使用してください:
Locale locale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
locale = context.getResources().getConfiguration().getLocales().get(0);
} else {
locale = context.getResources().getConfiguration().locale;
}
一部のデバイスでは、デフォルトの言語が異なるように設定されている場合(インド人は英語(米国)を設定できます)
context.getResources().getConfiguration().locale.getDisplayCountry();
間違った値を与えるので、この方法は信頼できません
また、テレフォニーマネージャーのgetNetworkCountryIso()メソッドは、SIMカードを持たないデバイス(WIFIタブレット)では機能しません。
デバイスにSIMがない場合は、タイムゾーンを使用して国を取得できます。インドのような国では、この方法が機能します
国のチェックに使用されるサンプルコードはインドかどうか(タイムゾーン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;
}
}
緯度と経度でGPSを使用して、国コードを取得できます。
電話を使用する場合、SIMカードを使用しておらず、言語に基づいたロケールでは、国コードが誤った方法で表示されると機能しません。
MainActivity.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:
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;
}
}
ログ:
E / countryCode: IN
編集:融合位置プロバイダーを使用して緯度と経度の更新を取得し、より良い結果を得ます。
GEOIP dbを使用して関数を作成しました。このリンクを直接利用できます http://jamhubsoftware.com/geoip/getcountry.php
{"country":["India"],"isoCode":["IN"],"names":[{"de":"Indien","en":"India","es":"India","fr":"Inde","ja":"\u30a4\u30f3\u30c9","pt-BR":"\u00cdndia","ru":"\u0418\u043d\u0434\u0438\u044f","zh-CN":"\u5370\u5ea6"}]}
autoload.phpおよび.mmdbファイルは、https: //dev.maxmind.com/geoip/geoip2/geolite2/からダウンロードできます。
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$ip_address = $_SERVER['REMOTE_ADDR'];
//$ip_address = '3.255.255.255';
require_once 'vendor/autoload.php';
use GeoIp2\Database\Reader;
// This creates the Reader object, which should be reused across
// lookups.
$reader = new Reader('/var/www/html/geoip/GeoLite2-City.mmdb');
// Replace "city" with the appropriate method for your database, e.g.,
// "country".
$record = $reader->city($ip_address);
//print($record->country->isoCode . "\n"); // 'US'
//print($record->country->name . "\n"); // 'United States'
$rows['country'][] = $record->country->name;
$rows['isoCode'][] = $record->country->isoCode;
$rows['names'][] = $record->country->names;
print json_encode($rows);
//print($record->country->names['zh-CN'] . "\n"); // '美国'
//
//print($record->mostSpecificSubdivision->name . "\n"); // 'Minnesota'
//print($record->mostSpecificSubdivision->isoCode . "\n"); // 'MN'
//
//print($record->city->name . "\n"); // 'Minneapolis'
//
//print($record->postal->code . "\n"); // '55455'
//
//print($record->location->latitude . "\n"); // 44.9733
//print($record->location->longitude . "\n"); // -93.2323
?>