注:本文翻譯自Google官方的Android Developers Training文檔,譯者技術(shù)一般,由于喜愛安卓而產(chǎn)生了翻譯的念頭,純屬個人興趣愛好。
原文鏈接: http://developer.android.com/training/location/display-address.html
前兩節(jié)課程講解了如何以 Location 對象的形式(包含經(jīng)緯度的信息)來獲取用戶的當(dāng)前地理位置信息。雖然經(jīng)緯度信息對于計算距離或者顯示一個地圖位置很有用,但在很多情況下,當(dāng)前地點的地址往往作用更大。
Android API提供了一個特性,它可以針對經(jīng)緯度信息估計出用戶所在的街道地址。這節(jié)課將講解如何使用這一地址查詢功能。
Note:
地址查詢需要一個沒有包括在核心Android框架中的后端服務(wù)。如果這個后端服務(wù)無法獲取, Geocoder.getFromLocation() 會返回一個空的list。輔助方法 isPresent() 在API 9及以上版本中可以獲得,它可以用來檢查后端服務(wù)是否可以獲取。
下列章節(jié)中的樣例代碼均假設(shè)你的應(yīng)用已經(jīng)獲取了當(dāng)前地點,并將它以一個 Location 對象的形式存儲于全局變量 mLocation 中。
一). 定義地址查詢?nèi)蝿?wù)
要獲取給定經(jīng)緯度的地址信息,調(diào)用
Geocoder.getFromLocation()
,它會返回一個包含地址的list。該方法是同步的,并且會耗費較長的時間去執(zhí)行,所以你應(yīng)該在一個
AsyncTask
中的
doInBackground()
里面進行調(diào)用。
當(dāng)你的應(yīng)用在獲取地址時,顯示一個執(zhí)行任務(wù)的標識告訴用戶你的應(yīng)用正在執(zhí)行后臺程序是有必要的。我們首先將這個標識的初始狀態(tài)設(shè)置為 android:visibility="gone" ,這可以使得它初始時不可見并且從布局層次結(jié)構(gòu)中移除。當(dāng)你開始地址查詢時,你應(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元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
