语言环境对 Android 地理编码器的影响
Effect of Locale on Android Geocoder
我正在尝试为客户远程排除应用程序故障。该应用创建其地理编码器并查找如下地址:
Geocoder gc = new Geocoder(context, Locale.getDefault());
List<Address> addresses = gc.getFromLocationName(nextWaypoint, 5);
航路点是加拿大的街道地址。客户端报告该应用程序可以在某些设备上对地址进行地理编码,但无法在其他设备上对相同地址进行地理编码。它失败的设备是来自以色列的 Android 4.0.3 设备。
我的直觉是,以色列的设备需要一个他们在以色列使用的任何格式的地址,甚至不会将加拿大地址识别为地址。这看起来有可能,甚至可能吗?
编辑: 我写了一个测试应用程序,表明我最初的想法是错误的。客户给了我一个示例地址(这个地址在美国),我编写了一个测试应用程序,它创建了两个具有显式语言环境的地理编码器:一个使用 Locale.US
,另一个使用 new Locale("iw", "IL")
。两者都能够在我的 4.4 设备上对示例地址进行地理编码。
根据客户端看到的代码和错误消息,getFromLocationName(...)
必须在以色列 4.0.3 设备上返回零结果。它 returns 在其他设备上产生相同地址。
Geocoder
是否已知在 4.0.3 中不稳定?
编辑 2: 可能与 issue 38009 有关。但是客户报告说他们看到了一个祝酒词,他们只会看到 getFromLocationName(...)
是否返回了一个空列表,如果抛出异常则不会。
很遗憾,我没有很好的答案,但据我所知,这是我认为你应该做的。
- 我会仔细检查您是否在您的用户设备上看到地理编码 api 引发的崩溃或异常。
- 如果情况仍然是您只得到零结果,我会制作一个 google 错误票 Android Bug Tracker 看看他们怎么说。我看到有人说在发生冲突的地区他们不会提供服务,但我没有直接从 google 看到任何东西,所以我想弄清楚这一点。
老实说,我认为这真的是您唯一的两个选择,就好像没有崩溃,而且 API 没有明确告诉我们为什么它们会给我们零结果。如果您创建了一个工单,请在此处分享,我很想看看 Google 的回应是什么。
我不确定这是否与您遇到的问题相同,但我会告诉您我的(以及我的部分解决方案)...
我正在 Google 地图上搜索自定义地点,第一次激活地图 activity 时,附近的位置自动显示在地图上(完美),但我注意到当我搜索完全相同的位置(使用 EditText 输入),自定义位置未显示在地图上。
我发现当我转换 THE PLACE ADDRESS(来自 EditText 输入)和来自 GeoCode 的自定义地点地址(来自我的数据库输入)时,Geocode 结果并不相同。
原因是 Geocode 实例(Geocode(context) 甚至 Geocode(context, locale))返回了搜索国家 Locale 中的一些结果 [Geocode(context, locale) 实例似乎没有正在工作]。
例子:
(我的默认设备语言环境是 PT-BR)
1 - 如果我正在搜索米兰(意大利),来自 EditText 输入(米兰)的地理编码结果在 PT-BR(米兰)中,而来自位于米兰的 CUSTOMIZED 对象的地理编码结果在 IT(米兰)中。
2 - 如果我正在搜索伦敦(英国),EditText 的地理编码结果是 PT-BR (Londres - Reino Unido) [即使我输入的是英语] 和 CUSTOMIZED 的地理编码结果位于米兰的对象将进入 EN(伦敦 - 英国)。
这样我无法匹配结果(我相信地理编码 returns 应该是 Locale.Default 语言)。
我的解决方案是:
从默认 Geocoder 获取结果地址,将其语言与默认语言 [result.getCountryCode] 进行比较。如果不同,使用第一个结果语言 [new Geocoder(context, Locale.forLanguageTag(result.getCountryCode())] 设置一个新的 Geocoder 实例,并保留这个新结果。
[ 我正在使用相同的 Geocoder(context, locale) 实例从我想要的地方(从 EditText)获取结果并从我的自定义位置(从数据库)获取结果,这样,无论我在 EditText 上插入什么语言,我总是得到正确的结果]
Geocoder geocoder = new Geocoder(parentContext);
Address placeResult = null;
try {
List<Address> addresses = geocoder.getFromLocationName(address, 1);
if (addresses.size() > 0) {
placeResult = addresses.get(0);
Log.d(TAG, String.format(">>> CONVERTED PLACE COUNTRY >>> %s <<<", placeResult.getCountryCode()));
if(!placeResult.getCountryCode().equalsIgnoreCase(Locale.getDefault().getCountry())) {
Log.d(TAG, String.format(">>> CHANGING CONVERTED PLACE COUNTRY >>> From: %s To: %s <<<", Locale.getDefault().getCountry(), placeResult.getCountryCode()));
geocoder = new Geocoder(parentContext, Locale.forLanguageTag(placeResult.getCountryCode()));
addresses = geocoder.getFromLocationName(address, 1);
}
placeResult = addresses.get(0);
} catch (IOException e) {
e.printStackTrace();
return;
}
寻找我的自定义地点:
try {
studioGeoAddress = geocoder.getFromLocation(studioLatitude, studioLongitude, 1).get(0);
Log.d(TAG, String.format(">>> CONVERTED STUDIO GEO ADDRESS >>> %s <<<", studioGeoAddress.toString()));
Log.d(TAG, String.format(">>> CONVERTED STUDIO LOCALE >>> %s <<<", studioGeoAddress.getLocale()));
Log.d(TAG, String.format(">>> STUDIO PROFILE >>> %s <<<", studioProfile.getDisplayName()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS COUNTRY >>> %s | %s <<<", studioGeoAddress.getCountryName(), placeResult.getCountryName()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS ADMIN >>> %s | %s <<<", studioGeoAddress.getAdminArea(), placeResult.getAdminArea()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS SUB-ADMIN >>> %s | %s <<<", studioGeoAddress.getSubAdminArea(), placeResult.getSubAdminArea()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS LOCALITY >>> %s | %s <<<", studioGeoAddress.getLocality(), placeResult.getLocality()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS SUB-LOCALITY >>> %s | %s <<<", studioGeoAddress.getSubLocality(), placeResult.getSubLocality()));
if (placeResult.getSubAdminArea() != null) {
if (studioGeoAddress.getSubAdminArea() != null) {
Log.d(TAG, String.format(">>> STUDIO SUB-ADMIN >>> %s | %s <<<", studioGeoAddress.getSubAdminArea(), placeResult.getSubAdminArea()));
if(studioGeoAddress.getSubAdminArea().equalsIgnoreCase(placeResult.getSubAdminArea())) {
Log.d(TAG, String.format(">>> STUDIO ADDED TO LIST >>> %s [MATCH] <<<", studioProfile.getDisplayName()));
STUDIOS_LIST.add(studioProfile);
}
}
} catch (IOException e) {
e.printStackTrace();
}
那是我的解决方案,也许还有更简单或更简单的方法,但目前有效。
Ps。对不起我的英语..
我正在尝试为客户远程排除应用程序故障。该应用创建其地理编码器并查找如下地址:
Geocoder gc = new Geocoder(context, Locale.getDefault());
List<Address> addresses = gc.getFromLocationName(nextWaypoint, 5);
航路点是加拿大的街道地址。客户端报告该应用程序可以在某些设备上对地址进行地理编码,但无法在其他设备上对相同地址进行地理编码。它失败的设备是来自以色列的 Android 4.0.3 设备。
我的直觉是,以色列的设备需要一个他们在以色列使用的任何格式的地址,甚至不会将加拿大地址识别为地址。这看起来有可能,甚至可能吗?
编辑: 我写了一个测试应用程序,表明我最初的想法是错误的。客户给了我一个示例地址(这个地址在美国),我编写了一个测试应用程序,它创建了两个具有显式语言环境的地理编码器:一个使用 Locale.US
,另一个使用 new Locale("iw", "IL")
。两者都能够在我的 4.4 设备上对示例地址进行地理编码。
根据客户端看到的代码和错误消息,getFromLocationName(...)
必须在以色列 4.0.3 设备上返回零结果。它 returns 在其他设备上产生相同地址。
Geocoder
是否已知在 4.0.3 中不稳定?
编辑 2: 可能与 issue 38009 有关。但是客户报告说他们看到了一个祝酒词,他们只会看到 getFromLocationName(...)
是否返回了一个空列表,如果抛出异常则不会。
很遗憾,我没有很好的答案,但据我所知,这是我认为你应该做的。
- 我会仔细检查您是否在您的用户设备上看到地理编码 api 引发的崩溃或异常。
- 如果情况仍然是您只得到零结果,我会制作一个 google 错误票 Android Bug Tracker 看看他们怎么说。我看到有人说在发生冲突的地区他们不会提供服务,但我没有直接从 google 看到任何东西,所以我想弄清楚这一点。
老实说,我认为这真的是您唯一的两个选择,就好像没有崩溃,而且 API 没有明确告诉我们为什么它们会给我们零结果。如果您创建了一个工单,请在此处分享,我很想看看 Google 的回应是什么。
我不确定这是否与您遇到的问题相同,但我会告诉您我的(以及我的部分解决方案)...
我正在 Google 地图上搜索自定义地点,第一次激活地图 activity 时,附近的位置自动显示在地图上(完美),但我注意到当我搜索完全相同的位置(使用 EditText 输入),自定义位置未显示在地图上。
我发现当我转换 THE PLACE ADDRESS(来自 EditText 输入)和来自 GeoCode 的自定义地点地址(来自我的数据库输入)时,Geocode 结果并不相同。
原因是 Geocode 实例(Geocode(context) 甚至 Geocode(context, locale))返回了搜索国家 Locale 中的一些结果 [Geocode(context, locale) 实例似乎没有正在工作]。
例子: (我的默认设备语言环境是 PT-BR) 1 - 如果我正在搜索米兰(意大利),来自 EditText 输入(米兰)的地理编码结果在 PT-BR(米兰)中,而来自位于米兰的 CUSTOMIZED 对象的地理编码结果在 IT(米兰)中。
2 - 如果我正在搜索伦敦(英国),EditText 的地理编码结果是 PT-BR (Londres - Reino Unido) [即使我输入的是英语] 和 CUSTOMIZED 的地理编码结果位于米兰的对象将进入 EN(伦敦 - 英国)。
这样我无法匹配结果(我相信地理编码 returns 应该是 Locale.Default 语言)。
我的解决方案是: 从默认 Geocoder 获取结果地址,将其语言与默认语言 [result.getCountryCode] 进行比较。如果不同,使用第一个结果语言 [new Geocoder(context, Locale.forLanguageTag(result.getCountryCode())] 设置一个新的 Geocoder 实例,并保留这个新结果。
[ 我正在使用相同的 Geocoder(context, locale) 实例从我想要的地方(从 EditText)获取结果并从我的自定义位置(从数据库)获取结果,这样,无论我在 EditText 上插入什么语言,我总是得到正确的结果]
Geocoder geocoder = new Geocoder(parentContext);
Address placeResult = null;
try {
List<Address> addresses = geocoder.getFromLocationName(address, 1);
if (addresses.size() > 0) {
placeResult = addresses.get(0);
Log.d(TAG, String.format(">>> CONVERTED PLACE COUNTRY >>> %s <<<", placeResult.getCountryCode()));
if(!placeResult.getCountryCode().equalsIgnoreCase(Locale.getDefault().getCountry())) {
Log.d(TAG, String.format(">>> CHANGING CONVERTED PLACE COUNTRY >>> From: %s To: %s <<<", Locale.getDefault().getCountry(), placeResult.getCountryCode()));
geocoder = new Geocoder(parentContext, Locale.forLanguageTag(placeResult.getCountryCode()));
addresses = geocoder.getFromLocationName(address, 1);
}
placeResult = addresses.get(0);
} catch (IOException e) {
e.printStackTrace();
return;
}
寻找我的自定义地点:
try {
studioGeoAddress = geocoder.getFromLocation(studioLatitude, studioLongitude, 1).get(0);
Log.d(TAG, String.format(">>> CONVERTED STUDIO GEO ADDRESS >>> %s <<<", studioGeoAddress.toString()));
Log.d(TAG, String.format(">>> CONVERTED STUDIO LOCALE >>> %s <<<", studioGeoAddress.getLocale()));
Log.d(TAG, String.format(">>> STUDIO PROFILE >>> %s <<<", studioProfile.getDisplayName()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS COUNTRY >>> %s | %s <<<", studioGeoAddress.getCountryName(), placeResult.getCountryName()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS ADMIN >>> %s | %s <<<", studioGeoAddress.getAdminArea(), placeResult.getAdminArea()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS SUB-ADMIN >>> %s | %s <<<", studioGeoAddress.getSubAdminArea(), placeResult.getSubAdminArea()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS LOCALITY >>> %s | %s <<<", studioGeoAddress.getLocality(), placeResult.getLocality()));
Log.d(TAG, String.format(">>> STUDIO ADDRESS HAS SUB-LOCALITY >>> %s | %s <<<", studioGeoAddress.getSubLocality(), placeResult.getSubLocality()));
if (placeResult.getSubAdminArea() != null) {
if (studioGeoAddress.getSubAdminArea() != null) {
Log.d(TAG, String.format(">>> STUDIO SUB-ADMIN >>> %s | %s <<<", studioGeoAddress.getSubAdminArea(), placeResult.getSubAdminArea()));
if(studioGeoAddress.getSubAdminArea().equalsIgnoreCase(placeResult.getSubAdminArea())) {
Log.d(TAG, String.format(">>> STUDIO ADDED TO LIST >>> %s [MATCH] <<<", studioProfile.getDisplayName()));
STUDIOS_LIST.add(studioProfile);
}
}
} catch (IOException e) {
e.printStackTrace();
}
那是我的解决方案,也许还有更简单或更简单的方法,但目前有效。
Ps。对不起我的英语..