注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/location/display-address.html
前兩節(jié)課程講解了如何以 Location 對象的形式(包含經(jīng)緯度的信息)來獲取用戶的當前地理位置信息。雖然經(jīng)緯度信息對于計算距離或者顯示一個地圖位置很有用,但在很多情況下,當前地點的地址往往作用更大。
Android API提供了一個特性,它可以針對經(jīng)緯度信息估計出用戶所在的街道地址。這節(jié)課將講解如何使用這一地址查詢功能。
Note:
地址查詢需要一個沒有包括在核心Android框架中的后端服務(wù)。如果這個后端服務(wù)無法獲取, Geocoder.getFromLocation() 會返回一個空的list。輔助方法 isPresent() 在API 9及以上版本中可以獲得,它可以用來檢查后端服務(wù)是否可以獲取。
下列章節(jié)中的樣例代碼均假設(shè)你的應(yīng)用已經(jīng)獲取了當前地點,并將它以一個 Location 對象的形式存儲于全局變量 mLocation 中。
一). 定義地址查詢?nèi)蝿?wù)
要獲取給定經(jīng)緯度的地址信息,調(diào)用
Geocoder.getFromLocation()
,它會返回一個包含地址的list。該方法是同步的,并且會耗費較長的時間去執(zhí)行,所以你應(yīng)該在一個
AsyncTask
中的
doInBackground()
里面進行調(diào)用。
當你的應(yīng)用在獲取地址時,顯示一個執(zhí)行任務(wù)的標識告訴用戶你的應(yīng)用正在執(zhí)行后臺程序是有必要的。我們首先將這個標識的初始狀態(tài)設(shè)置為 android:visibility="gone" ,這可以使得它初始時不可見并且從布局層次結(jié)構(gòu)中移除。當你開始地址查詢時,你應(yīng)該將它的可見性設(shè)置為“ visible ”。
下面的代碼片段展示了如何在你的布局文件中添加一個 ProgressBar :
<
ProgressBar
android:id
="@+id/address_progress"
android:layout_width
="wrap_content"
android:layout_height
="wrap_content"
android:layout_centerHorizontal
="true"
android:indeterminate
="true"
android:visibility
="gone"
/>
要創(chuàng)建一個后臺任務(wù),定義一個 AsyncTask 的子類,用來調(diào)用 getFromLocation() 并返回地址。定義一個 名字叫 mAddress 的 TextView 對象,用來顯示返回的地址,另外一個 ProgressBar 對象允許你可以對后臺執(zhí)行的標識進行控制,例如:
public
class
MainActivity
extends
FragmentActivity {
...
private
TextView mAddress;
private
ProgressBar mActivityIndicator;
...
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
...
mAddress
=
(TextView) findViewById(R.id.address);
mActivityIndicator
=
(ProgressBar) findViewById(R.id.address_progress);
}
...
/**
* A subclass of AsyncTask that calls getFromLocation() in the
* background. The class definition has these generic types:
* Location - A Location object containing
* the current location.
* Void - indicates that progress units are not used
* String - An address passed to onPostExecute()
*/
private
class
GetAddressTask
extends
AsyncTask
<Location, Void, String>
{
Context mContext;
public
GetAddressTask(Context context) {
super
();
mContext
=
context;
}
...
/**
* Get a Geocoder instance, get the latitude and longitude
* look up the address, and return it
*
* @params params One or more Location objects
*
@return
A string containing the address of the current
* location, or an empty string if no address can be found,
* or an error message
*/
@Override
protected
String doInBackground(Location... params) {
Geocoder geocoder
=
new
Geocoder(mContext, Locale.getDefault());
//
Get the current location from the input parameter list
Location loc = params[0
];
//
Create a list to contain the result address
List<Address> addresses =
null
;
try
{
/*
* Return 1 address.
*/
addresses
=
geocoder.getFromLocation(loc.getLatitude(),
loc.getLongitude(),
1
);
}
catch
(IOException e1) {
Log.e(
"LocationSampleActivity"
,
"IO Exception in getFromLocation()"
);
e1.printStackTrace();
return
("IO Exception trying to get address"
);
}
catch
(IllegalArgumentException e2) {
//
Error message to post in the log
String errorString = "Illegal arguments " +
Double.toString(loc.getLatitude())
+
" , " +
Double.toString(loc.getLongitude())
+
" passed to address service"
;
Log.e(
"LocationSampleActivity"
, errorString);
e2.printStackTrace();
return
errorString;
}
//
If the reverse geocode returned an address
if
(addresses !=
null
&& addresses.size() > 0
) {
//
Get the first address
Address address = addresses.get(0
);
/*
* Format the first line of address (if available),
* city, and country name.
*/
String addressText
=
String.format(
"%s, %s, %s"
,
//
If there's a street address, add it
address.getMaxAddressLineIndex() > 0 ?
address.getAddressLine(
0) : ""
,
//
Locality is usually a city
address.getLocality(),
//
The country of the address
address.getCountryName());
//
Return the text
return
addressText;
}
else
{
return
"No address found"
;
}
}
...
}
...
}
在下一章節(jié)將會向你展示如何在用戶接口顯示地址。
二). 定義一個顯示結(jié)果的方法
doInBackground() 返回的地址查詢結(jié)果是一個String的類型。值被傳遞到 onPostExecute() 中,在這個方法里你將會對結(jié)果做進一步的處理。由于 onPostExecute() 方法是在UI線程中執(zhí)行的,它可以用來更新用戶接口;例如,它可以關(guān)閉進度條并且將結(jié)果顯示給用戶:
private
class
GetAddressTask
extends
AsyncTask
<Location, Void, String>
{
...
/**
* A method that's called once doInBackground() completes. Turn
* off the indeterminate activity indicator and set
* the text of the UI element that shows the address. If the
* lookup failed, display the error message.
*/
@Override
protected
void
onPostExecute(String address) {
//
Set activity indicator visibility to "gone"
mActivityIndicator.setVisibility(View.GONE);
//
Display the results of the lookup.
mAddress.setText(address);
}
...
}
最后的步驟就是要運行地址查詢了。
三). 執(zhí)行查詢?nèi)蝿?wù)
要獲取地址,調(diào)用 execute() 方法。例如,下面的代碼片段在用戶點擊了“獲取地址”這一按鈕后,啟動地址查詢:
public
class
MainActivity
extends
FragmentActivity {
...
/**
* The "Get Address" button in the UI is defined with
* android:onClick="getAddress". The method is invoked whenever the
* user clicks the button.
*
*
@param
v The view object associated with this method,
* in this case a Button.
*/
public
void
getAddress(View v) {
//
Ensure that a Geocoder services is available
if
(Build.VERSION.SDK_INT >=
Build.VERSION_CODES.GINGERBREAD
&&
Geocoder.isPresent()) {
//
Show the activity indicator
mActivityIndicator.setVisibility(View.VISIBLE);
/*
* Reverse geocoding is long-running and synchronous.
* Run it on a background thread.
* Pass the current location to the background task.
* When the task finishes,
* onPostExecute() displays the address.
*/
(
new
GetAddressTask(
this
)).execute(mLocation);
}
...
}
...
}
在下一節(jié)課,我們將會講解如何去定義感興趣的地點并調(diào)用地理圍欄,以及如何使用它來檢測用戶是否接近感興趣的地點。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061
微信掃一掃加我為好友
QQ號聯(lián)系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元

