Android地图开发中的地理编码与地理反编码


地理编码(Geocoding)与地理反编码(Reverse Geocoding)是地图操作中的常见操作,前者表示通过街道地址请求空间坐标,后者表示通过空间坐标请求街道地址。通俗的说,二者就是街道地址与经纬度的转换。举例来说,前者就是输入查询"上海市杨浦区四平路1239号"得到(31.285207060526762, 121.50546412914991),而后者则表示这个反过程。

在实际的移动开发过程中,地图相关的操作对于地理编码与地理反编码的使用都是十分普遍。幸运的是,Android的MapView控件中对于这两者都进行了封装,因此可以方便的利用Google Map Service进行二者查询。下面将对开发过程做一个简单介绍。

首先必须进行MapKey的申请,任何地图的显示都需要申请一个MapKey。具体的申请步骤可见

http://code.google.com/intl/zh-CN/android/maps-api-signup.html

然后可以建立一个基于Google APIs的程序,并且在AndroidManifest.xml中加入地图API的支持。

view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
03.      package="net.learn2develop.GoogleMaps" 
04.      android:versionCode="1" 
05.      android:versionName="1.0.0"> 
06.    <application android:icon="@drawable/icon" android:label="@string/app_name"> 
07.    <uses-library android:name="com.google.android.maps" />    
08.        <activity android:name=".MapsActivity" 
09.                  android:label="@string/app_name"> 
10.            <intent-filter> 
11.                <action android:name="android.intent.action.MAIN" /> 
12.                <category android:name="android.intent.category.LAUNCHER" /> 
13.            </intent-filter> 
14.        </activity> 
15.    </application> 
16.   
17.    <uses-permission android:name="android.permission.INTERNET" /> 
18.</manifest> 
19.</xml> 
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="net.learn2develop.GoogleMaps"
      android:versionCode="1"
      android:versionName="1.0.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
    <uses-library android:name="com.google.android.maps" /> 
        <activity android:name=".MapsActivity"
                  android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

    <uses-permission android:name="android.permission.INTERNET" />
</manifest>
</xml>

接着可以在主Layout文件中加入对于地图的显示,这里需要加入刚才申请的MapKey,否则地图将无法正常显示。

view plaincopy to clipboardprint?01.<?xml version="1.0" encoding="utf-8"?>  02.<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    03.    android:layout_width="fill_parent"    04.    android:layout_height="fill_parent">  05.    06.    <com.google.android.maps.MapView    07.        android:id="@+id/mapView"  08.        android:layout_width="fill_parent"  09.        android:layout_height="fill_parent"  10.        android:enabled="true"  11.        android:clickable="true"  12.        android:apiKey="MapKey"  13.        />  14.    15.</RelativeLayout>  <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <com.google.android.maps.MapView
        android:id="@+id/mapView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:enabled="true"
        android:clickable="true"
        android:apiKey="MapKey"
        />

</RelativeLayout>

接着在主Activity的JAVA文件进行修改,支持地图显示。

view plaincopy to clipboardprint?
01.import com.google.android.maps.MapActivity;  
02.import com.google.android.maps.MapView;  
03.import android.os.Bundle;  
04.   
05.public class MapsActivity extends MapActivity   
06.{      
07.    /** Called when the activity is first created. */ 
08.    @Override 
09.    public void onCreate(Bundle savedInstanceState)  
10.    {  
11.        super.onCreate(savedInstanceState);  
12.        setContentView(R.layout.main);  
13.    MapView mapView = (MapView) findViewById(R.id.mapView);  
14.    mapView.setBuiltInZoomControls(true);  
15.    }  
16.} 
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import android.os.Bundle;

public class MapsActivity extends MapActivity
{   
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
MapView mapView = (MapView) findViewById(R.id.mapView);
mapView.setBuiltInZoomControls(true);
    }
}

此时运行程序,地图应该就可以正常显示了,见下图。

Android地图开发中的地理编码与地理反编码_第1张图片





此时我们再向程序中加入地理编码与地理反编码的功能,其参考代码如下。

地理编码:

view plaincopy to clipboardprint?
01.Geocoder geoCoder = new Geocoder(this, Locale.getDefault());      
02.try {  
03.    List<Address> addresses = geoCoder.getFromLocationName(  
04.        "上海市杨浦区四平路1239号", 5);  
05.    String add = "";  
06.    if (addresses.size() > 0) {  
07.        p = new GeoPoint(  
08.                (int) (addresses.get(0).getLatitude() * 1E6),   
09.                (int) (addresses.get(0).getLongitude() * 1E6));  
10.        mc.animateTo(p);      
11.        mapView.invalidate();  
12.    }      
13.} catch (IOException e) {  
14.    e.printStackTrace();  
15.} 
        Geocoder geoCoder = new Geocoder(this, Locale.getDefault());   
        try {
            List<Address> addresses = geoCoder.getFromLocationName(
                "上海市杨浦区四平路1239号", 5);
            String add = "";
            if (addresses.size() > 0) {
                p = new GeoPoint(
                        (int) (addresses.get(0).getLatitude() * 1E6),
                        (int) (addresses.get(0).getLongitude() * 1E6));
                mc.animateTo(p);   
                mapView.invalidate();
            }   
        } catch (IOException e) {
            e.printStackTrace();
        }

地理反编码,其中MapOverlay为地图图层上的叠加图层,用于标识的显示以及点击事件的捕捉。


view plaincopy to clipboardprint?
01.class MapOverlay extends com.google.android.maps.Overlay  
02.    {  
03.        @Override 
04.        public boolean draw(Canvas canvas, MapView mapView,   
05.        boolean shadow, long when)   
06.        {  
07.          //...  
08.        }  
09.   
10.        @Override 
11.        public boolean onTouchEvent(MotionEvent event, MapView mapView)   
12.        {     
13.            //---when user lifts his finger---  
14.            if (event.getAction() == 1) {                  
15.                GeoPoint p = mapView.getProjection().fromPixels(  
16.                    (int) event.getX(),  
17.                    (int) event.getY());  
18.   
19.                Geocoder geoCoder = new Geocoder(  
20.                    getBaseContext(), Locale.getDefault());  
21.                try {  
22.                    List<Address> addresses = geoCoder.getFromLocation(  
23.                        p.getLatitudeE6()  / 1E6,   
24.                        p.getLongitudeE6() / 1E6, 1);  
25.   
26.                    String add = "";  
27.                    if (addresses.size() > 0)   
28.                    {  
29.                        for (int i=0; i<addresses.get(0).getMaxAddressLineIndex();   
30.                             i++)  
31.                           add += addresses.get(0).getAddressLine(i) + "\n";  
32.                    }  
33.   
34.                    Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();  
35.                }  
36.                catch (IOException e) {                  
37.                    e.printStackTrace();  
38.                }     
39.                return true;  
40.            }  
41.            else                  
42.                return false;  
43.        }          
44.    } 
class MapOverlay extends com.google.android.maps.Overlay
    {
        @Override
        public boolean draw(Canvas canvas, MapView mapView,
        boolean shadow, long when)
        {
          //...
        }

        @Override
        public boolean onTouchEvent(MotionEvent event, MapView mapView)
        {  
            //---when user lifts his finger---
            if (event.getAction() == 1) {               
                GeoPoint p = mapView.getProjection().fromPixels(
                    (int) event.getX(),
                    (int) event.getY());

                Geocoder geoCoder = new Geocoder(
                    getBaseContext(), Locale.getDefault());
                try {
                    List<Address> addresses = geoCoder.getFromLocation(
                        p.getLatitudeE6()  / 1E6,
                        p.getLongitudeE6() / 1E6, 1);

                    String add = "";
                    if (addresses.size() > 0)
                    {
                        for (int i=0; i<addresses.get(0).getMaxAddressLineIndex();
                             i++)
                           add += addresses.get(0).getAddressLine(i) + "\n";
                    }

                    Toast.makeText(getBaseContext(), add, Toast.LENGTH_SHORT).show();
                }
                catch (IOException e) {               
                    e.printStackTrace();
                }  
                return true;
            }
            else               
                return false;
        }       
    }
最终实现结果如下图所示,地理编码,查询“上海市杨浦区四平路1239号”,结果其实略有偏差。中国的地址与邮编比较混乱,所以结果有些地方无法做到完全准确。

Android地图开发中的地理编码与地理反编码_第2张图片


地理反编码

Android地图开发中的地理编码与地理反编码_第3张图片

你可能感兴趣的:(java,UI,android,Google)