Location服务之Geocoder

提到Android基于位置的服务,就不得不提android.location包,location包提供了很便捷的API来实现基于位置的服务。主要包括Geocoder和LocationManager。今天就先来介绍一下Geocoder。

Geocoder可以在街道地址和经纬度地图坐标之间进行转换。它提供了对两种地理编码功能的访问:

Forward Geocoding(前向地理编码):查找某个地址的经纬度

Reverse Geocoding(反向地理编码):查找一个给定的经纬度所对应的街道地址。

分别对应以下方法:

view plaincopy to clipboardprint?
01.List<Address>  getFromLocationName(String locationName, int maxResults)  
02.List<Address>  getFromLocation(double latitude,double longitude,int maxResults); 
List<Address>  getFromLocationName(String locationName, int maxResults)
List<Address>  getFromLocation(double latitude,double longitude,int maxResults);

我们新建一个location的项目。因为示例要使用到地图服务,所以创建时Build Target要选择Google APIs这一项。

然后修改/res/layout/main.xml,代码如下:

view plaincopy to clipboardprint?
01.<?xml version="1.0" encoding="utf-8"?> 
02.<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android
03.    android:orientation="vertical" 
04.    android:layout_width="fill_parent" 
05.    android:layout_height="fill_parent"> 
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:clickable="true" 
11.        android:apiKey="your apiKey goes here"/> 
12.    <LinearLayout 
13.        android:layout_width="fill_parent" 
14.        android:layout_height="wrap_content"> 
15.        <EditText 
16.            android:id="@+id/name" 
17.            android:layout_width="wrap_content" 
18.            android:layout_height="wrap_content" 
19.            android:layout_weight="1"/> 
20.        <Button 
21.            android:id="@+id/find" 
22.            android:layout_width="wrap_content" 
23.            android:layout_height="wrap_content" 
24.            android:text="Find"/> 
25.    </LinearLayout> 
26.</FrameLayout> 
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    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:clickable="true"
  android:apiKey="your apiKey goes here"/>
 <LinearLayout
  android:layout_width="fill_parent"
     android:layout_height="wrap_content">
  <EditText
   android:id="@+id/name"
   android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_weight="1"/>
     <Button
      android:id="@+id/find"
   android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="Find"/>
 </LinearLayout>
</FrameLayout>

然后我们来看一下MainActivity.java文件,代码如下:

view plaincopy to clipboardprint?
01.package com.scott.location;  
02. 
03.import java.io.IOException;  
04.import java.util.List;  
05. 
06.import android.location.Address;  
07.import android.location.Geocoder;  
08.import android.os.Bundle;  
09.import android.view.View;  
10.import android.widget.Button;  
11.import android.widget.EditText;  
12.import android.widget.ImageView;  
13.import android.widget.Toast;  
14. 
15.import com.google.android.maps.GeoPoint;  
16.import com.google.android.maps.MapActivity;  
17.import com.google.android.maps.MapView;  
18.import com.google.android.maps.MapView.LayoutParams;  
19. 
20.public class MainActivity extends MapActivity {  
21.      
22.    private MapView mapView;  
23.    private EditText name;  
24.    private Button find;  
25.      
26.    private Geocoder geocoder;  
27.      
28.    private static final double lat = 39.908716;    
29.    private static final double lng = 116.397529;    
30.      
31.    @Override 
32.    public void onCreate(Bundle savedInstanceState) {  
33.        super.onCreate(savedInstanceState);  
34.        setContentView(R.layout.main);  
35.          
36.        mapView = (MapView) findViewById(R.id.mapView);  
37.        mapView.getController().setZoom(17);  
38.        mapView.getController().animateTo(new GeoPoint((int)(lat * 1E6),(int)(lng * 1E6)));  
39.          
40.        geocoder = new Geocoder(this);  
41.          
42.        name = (EditText) findViewById(R.id.name);  
43.        find = (Button) findViewById(R.id.find);  
44.          
45.        find.setOnClickListener(new View.OnClickListener() {  
46.            @Override 
47.            public void onClick(View v) {  
48.                String keyword = name.getText().toString();  
49.                try {  
50.                    List<Address> addrs = geocoder.getFromLocationName(keyword, 3);  
51.                    if (addrs != null && addrs.size() > 0) {  
52.                        int latE6 = (int) (addrs.get(0).getLatitude() * 1E6);  
53.                        int lngE6 = (int) (addrs.get(0).getLongitude() * 1E6);  
54.                        GeoPoint point = new GeoPoint(latE6, lngE6);  
55.                        mapView.getController().animateTo(point);  
56.                          
57.                        final MapView.LayoutParams params = new MapView.LayoutParams(LayoutParams.WRAP_CONTENT,  
58.                                LayoutParams.WRAP_CONTENT, point, LayoutParams.BOTTOM_CENTER);  
59.                        final ImageView marker = new ImageView(MainActivity.this);  
60.                        marker.setImageResource(R.drawable.marker);  
61.                        marker.setOnClickListener(new View.OnClickListener() {  
62.                            @Override 
63.                            public void onClick(View v) {  
64.                                Toast.makeText(getApplicationContext(), "hello geocoder!", Toast.LENGTH_SHORT).show();  
65.                            }  
66.                        });  
67.                        mapView.addView(marker, params);  
68.                    }  
69.                } catch (IOException e) {  
70.                    e.printStackTrace();  
71.                }  
72.            }  
73.        });  
74.    }  
75. 
76.    @Override 
77.    protected boolean isRouteDisplayed() {  
78.        return false;  
79.    }  
80.} 
package com.scott.location;

import java.io.IOException;
import java.util.List;

import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import com.google.android.maps.MapView.LayoutParams;

public class MainActivity extends MapActivity {
 
 private MapView mapView;
 private EditText name;
 private Button find;
 
 private Geocoder geocoder;
 
 private static final double lat = 39.908716; 
 private static final double lng = 116.397529; 
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
       
        mapView = (MapView) findViewById(R.id.mapView);
        mapView.getController().setZoom(17);
        mapView.getController().animateTo(new GeoPoint((int)(lat * 1E6),(int)(lng * 1E6)));
       
        geocoder = new Geocoder(this);
       
        name = (EditText) findViewById(R.id.name);
        find = (Button) findViewById(R.id.find);
       
        find.setOnClickListener(new View.OnClickListener() {
   @Override
   public void onClick(View v) {
    String keyword = name.getText().toString();
    try {
     List<Address> addrs = geocoder.getFromLocationName(keyword, 3);
     if (addrs != null && addrs.size() > 0) {
      int latE6 = (int) (addrs.get(0).getLatitude() * 1E6);
      int lngE6 = (int) (addrs.get(0).getLongitude() * 1E6);
      GeoPoint point = new GeoPoint(latE6, lngE6);
      mapView.getController().animateTo(point);
      
      final MapView.LayoutParams params = new MapView.LayoutParams(LayoutParams.WRAP_CONTENT,
        LayoutParams.WRAP_CONTENT, point, LayoutParams.BOTTOM_CENTER);
      final ImageView marker = new ImageView(MainActivity.this);
      marker.setImageResource(R.drawable.marker);
      marker.setOnClickListener(new View.OnClickListener() {
       @Override
       public void onClick(View v) {
        Toast.makeText(getApplicationContext(), "hello geocoder!", Toast.LENGTH_SHORT).show();
       }
      });
      mapView.addView(marker, params);
     }
    } catch (IOException e) {
     e.printStackTrace();
    }
   }
  });
    }

 @Override
 protected boolean isRouteDisplayed() {
  return false;
 }
}

最后需要在AndroidManifest.xml中的application标签之间加入google map library:

view plaincopy to clipboardprint?
01.<uses-library android:name="com.google.android.maps" /> 
<uses-library android:name="com.google.android.maps" />

然后就是一些位置服务所需的权限:

view plaincopy to clipboardprint?
01.<uses-permission android:name="android.permission.INTERNET" /> 
02.<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />    
03.<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /> 
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> 
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

有一点需要跟朋友们提一下,Geocoder查找是同步地进行的,因此,它们将会阻塞调用它们的线程。对于低速的数据连接来说,这可能会导致出现ANR(Application Not Respond)的问题。在大部分情况下,更好的做法是把这些查找移动到服务或者后台线程中,前面几篇文章中也涉及到了一些异步任务的相关知识,不熟悉的朋友们可以参看以下Handler和AsyncTask的使用。为了清晰和简洁起见,上面代码中的查找操作直接放在了UI线程中,应用时最好不要这样写。

做完上面的操作,基本上就算是完成了该示例。不过如果使用模拟器时用的是Google API v8时会出现一个异常,将无法完成查找功能:

 

这是什么原因呢?在网上搜寻了一通,发现讨论区,真的很给力:http://code.google.com/p/android/issues/detail?id=8816

看看个别的评论:

 

 

 

 

看来真机和v7都没问题,v8会出问题。

也有高人给出解决方案,另辟蹊径,使用访问url的方式,获取json数据,然后解析获取经度和纬度,最后再组装成一个GeoPoint对象即可。我们新建一个LocationUtil.java文件,代码如下:

view plaincopy to clipboardprint?
01.package com.scott.location;  
02. 
03.import java.io.InputStream;  
04. 
05.import org.apache.http.HttpEntity;  
06.import org.apache.http.HttpResponse;  
07.import org.apache.http.client.HttpClient;  
08.import org.apache.http.client.methods.HttpGet;  
09.import org.apache.http.impl.client.DefaultHttpClient;  
10.import org.json.JSONArray;  
11.import org.json.JSONException;  
12.import org.json.JSONObject;  
13. 
14.import com.google.android.maps.GeoPoint;  
15. 
16.public class LocationUtil {  
17.      
18.    public static GeoPoint getFromLocationName(String address) {  
19.        String url = "http://maps.google.com/maps/api/geocode/json";  
20.        HttpGet httpGet = new HttpGet(url + "?sensor=false&address=" + address);  
21.        HttpClient client = new DefaultHttpClient();  
22.        HttpResponse response;  
23.        StringBuilder stringBuilder = new StringBuilder();  
24.        try {  
25.            response = client.execute(httpGet);  
26.            HttpEntity entity = response.getEntity();  
27.            InputStream stream = entity.getContent();  
28.            int b;  
29.            while ((b = stream.read()) != -1) {  
30.                stringBuilder.append((char) b);  
31.            }  
32.        } catch (Exception e) {  
33.            e.printStackTrace();  
34.        }  
35. 
36.        JSONObject jsonObject = new JSONObject();  
37.        try {  
38.            jsonObject = new JSONObject(stringBuilder.toString());  
39.        } catch (JSONException e) {  
40.            e.printStackTrace();  
41.        }  
42.        return getGeoPoint(jsonObject);  
43.    }  
44. 
45.    private static GeoPoint getGeoPoint(JSONObject jsonObject) {  
46.        try {  
47.            JSONArray array = (JSONArray) jsonObject.get("results");  
48.            JSONObject first = array.getJSONObject(0);  
49.            JSONObject geometry = first.getJSONObject("geometry");  
50.            JSONObject location = geometry.getJSONObject("location");  
51.              
52.            double lat = location.getDouble("lat");  
53.            double lng = location.getDouble("lng");  
54.              
55.            return new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));  
56.        } catch (JSONException e) {  
57.            e.printStackTrace();  
58.        }  
59.        return null;  
60.    }  
61. 
62.} 
package com.scott.location;

import java.io.InputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.android.maps.GeoPoint;

public class LocationUtil {
 
 public static GeoPoint getFromLocationName(String address) {
  String url = "http://maps.google.com/maps/api/geocode/json";
  HttpGet httpGet = new HttpGet(url + "?sensor=false&address=" + address);
  HttpClient client = new DefaultHttpClient();
  HttpResponse response;
  StringBuilder stringBuilder = new StringBuilder();
  try {
   response = client.execute(httpGet);
   HttpEntity entity = response.getEntity();
   InputStream stream = entity.getContent();
   int b;
   while ((b = stream.read()) != -1) {
    stringBuilder.append((char) b);
   }
  } catch (Exception e) {
   e.printStackTrace();
  }

  JSONObject jsonObject = new JSONObject();
  try {
   jsonObject = new JSONObject(stringBuilder.toString());
  } catch (JSONException e) {
   e.printStackTrace();
  }
  return getGeoPoint(jsonObject);
 }

 private static GeoPoint getGeoPoint(JSONObject jsonObject) {
  try {
   JSONArray array = (JSONArray) jsonObject.get("results");
   JSONObject first = array.getJSONObject(0);
   JSONObject geometry = first.getJSONObject("geometry");
   JSONObject location = geometry.getJSONObject("location");
   
   double lat = location.getDouble("lat");
   double lng = location.getDouble("lng");
   
   return new GeoPoint((int) (lat * 1E6), (int) (lng * 1E6));
  } catch (JSONException e) {
   e.printStackTrace();
  }
  return null;
 }

}
 

然后对MainActivity.java关键地方进行改写:

view plaincopy to clipboardprint?
01.GeoPoint point = LocationUtil.getFromLocationName(keyword); 
GeoPoint point = LocationUtil.getFromLocationName(keyword);

大功告成,当我们搜索后把结果中的第一个显示到地图中,然后点击图标时,弹出提示。我们来看一下效果:

 

以上是关于android.location包基于位置服务中Geocoder的基本介绍,更多的内容会在以后找机会和大家再分享。

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/liuhe688/archive/2011/06/24/6566505.aspx

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值