【Android Developers Training】 105. 显示一

系统 2710 0

注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接: http://developer.android.com/training/location/display-address.html


前两节课程讲解了如何以 Location 对象的形式(包含经纬度的信息)来获取用户的当前地理位置信息。虽然经纬度信息对于计算距离或者显示一个地图位置很有用,但在很多情况下,当前地点的地址往往作用更大。

Android API提供了一个特性,它可以针对经纬度信息估计出用户所在的街道地址。这节课将讲解如何使用这一地址查询功能。

Note:

地址查询需要一个没有包括在核心Android框架中的后端服务。如果这个后端服务无法获取, Geocoder.getFromLocation() 会返回一个空的list。辅助方法 isPresent() 在API 9及以上版本中可以获得,它可以用来检查后端服务是否可以获取。

下列章节中的样例代码均假设你的应用已经获取了当前地点,并将它以一个 Location 对象的形式存储于全局变量 mLocation 中。


一). 定义地址查询任务

要获取给定经纬度的地址信息,调用 Geocoder.getFromLocation() ,它会返回一个包含地址的list。该方法是同步的,并且会耗费较长的时间去执行,所以你应该在一个 AsyncTask 中的 doInBackground() 里面进行调用。

当你的应用在获取地址时,显示一个执行任务的标识告诉用户你的应用正在执行后台程序是有必要的。我们首先将这个标识的初始状态设置为 android:visibility="gone" ,这可以使得它初始时不可见并且从布局层次结构中移除。当你开始地址查询时,你应该将它的可见性设置为“ 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"
      
      
        />
      
    

要创建一个后台任务,定义一个 AsyncTask 的子类,用来调用 getFromLocation() 并返回地址。定义一个 名字叫 mAddress TextView 对象,用来显示返回的地址,另外一个 ProgressBar 对象允许你可以对后台执行的标识进行控制,例如:

      
        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"
      
        ;

            }

        }

        ...

    }

    ...

}
      
    

在下一章节将会向你展示如何在用户接口显示地址。


二). 定义一个显示结果的方法

doInBackground() 返回的地址查询结果是一个String的类型。值被传递到 onPostExecute() 中,在这个方法里你将会对结果做进一步的处理。由于 onPostExecute() 方法是在UI线程中执行的,它可以用来更新用户接口;例如,它可以关闭进度条并且将结果显示给用户:

      
        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);

        }

        ...

    }
      
    

最后的步骤就是要运行地址查询了。


三). 执行查询任务

要获取地址,调用 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);

        }

        ...

    }

    ...

}
      
    

在下一节课,我们将会讲解如何去定义感兴趣的地点并调用地理围栏,以及如何使用它来检测用户是否接近感兴趣的地点。

【Android Developers Training】 105. 显示一个位置地址


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论