基于位置的服务(Location based service)是移动设备所特有的。根据移动设备的位置可以开发出很多有意思的应用。
1、获取手机的位置信息
我们希望做出来的效果如图所示:
首先,布局代码如下:
<TextView
android:id="@+id/position_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/hello_world" />
在活动中代码如下,请注意注释说明:
public class MainActivity extends Activity {
private TextView positionView; //TextView控件
private LocationManager locationManager; //位置管理器
private String provider; //位置提供器,有三种,基于网络, GPS,以及PASSIVE_PROVIER(不常用)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
positionView = (TextView)findViewById(R.id.position_view);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); //获取位置管理器实例,直接调用系统方法就可以
List<String> providerList = locationManager.getProviders(true);//获取所有可用的位置提供器
if(providerList.contains(LocationManager.GPS_PROVIDER)){
//如果提供器中有GPS提供器,即检测到手机是可以通过GPS提供位置服务
provider = LocationManager.GPS_PROVIDER;
}else if(providerList.contains(LocationManager.NETWORK_PROVIDER)){
//如果检测到无线位置提供方式
provider = LocationManager.NETWORK_PROVIDER;
}else{
//如果没有位置提供器 那么弹出提示
Toast.makeText(this, "没有位置提供器", Toast.LENGTH_SHORT).show();
return;
}
Location location = locationManager.getLastKnownLocation(provider);//获取位置信息
if(location != null){
//显示当前设备的位置信息
showLocation(location);
}
//根据provider提供的位置信息,每隔5秒,当距离相差1米的时候,监听器处理相应时间。主要用于当位置变化的时候,定时更新位置信息
locationManager.requestLocationUpdates(provider, 5000, 1, loactionListener);
}
LocationListener loactionListener = new LocationListener() {
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
//状态改变
}
@Override
public void onProviderEnabled(String arg0) {
//提供器可用
}
@Override
public void onProviderDisabled(String arg0) {
//提供器不可用
}
@Override
public void onLocationChanged(Location arg0) {
//位置改变
showLocation(arg0);
}
};
protected void onDestroy() {
super.onDestroy();
//移除监听器
if(locationManager != null){
locationManager.removeUpdates(loactionListener);
}
}
private void showLocation(Location location){
//获取经度和维度,并显示出来
String currentPostion = location.getLatitude()+"\n"+location.getLongitude();
positionView.setText(currentPostion);
}
}
因为要访问位置信息,在配置文件中,要配置如下一句:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
现在看到的只是经纬度信息,如何才能看到能够被大家看懂的经纬度信息呢?下面,我们希望做到如下这样子:(由于网络原因,无法访问到google api,如可以,应该显示城市街道信息)
此时,代码应该如下所示:
public class MainActivity extends Activity {
private TextView positionView; //TextView控件
private LocationManager locationManager; //位置管理器
private String provider; //位置提供器,有三种,基于网络, GPS,以及PASSIVE_PROVIER(不常用)
public static final int SHOW_LOCATION = 0; //标识码,用于handler传递信息使用
private Handler handler = new Handler(){ //处理子线程传递过来的信息
public void handleMessage(Message msg){
switch (msg.what) {
case SHOW_LOCATION: //展示位置信息
String currentPosition = (String)msg.obj;
positionView.setText(currentPosition);
break;
default:
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
positionView = (TextView)findViewById(R.id.position_view);
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE); //获取位置管理器实例,直接调用系统方法就可以
List<String> providerList = locationManager.getProviders(true);//获取所有可用的位置提供器
if(providerList.contains(LocationManager.GPS_PROVIDER)){
//如果提供器中有GPS提供器,即检测到手机是可以通过GPS提供位置服务
provider = LocationManager.GPS_PROVIDER;
}else if(providerList.contains(LocationManager.NETWORK_PROVIDER)){
//如果检测到无线位置提供方式
provider = LocationManager.NETWORK_PROVIDER;
}else{
//如果没有位置提供器 那么弹出提示
Toast.makeText(this, "没有位置提供器", Toast.LENGTH_SHORT).show();
return;
}
Location location = locationManager.getLastKnownLocation(provider);//获取位置信息
if(location != null){
//显示当前设备的位置信息
showLocation(location);
}
//根据provider提供的位置信息,每隔5秒,当距离相差1米的时候,监听器处理相应时间。主要用于当位置变化的时候,定时更新位置信息
locationManager.requestLocationUpdates(provider, 5000, 1, loactionListener);
}
LocationListener loactionListener = new LocationListener() {
@Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
//状态改变
}
@Override
public void onProviderEnabled(String arg0) {
//提供器可用
}
@Override
public void onProviderDisabled(String arg0) {
//提供器不可用
}
@Override
public void onLocationChanged(Location arg0) {
//位置改变
showLocation(arg0);
}
};
protected void onDestroy() {
super.onDestroy();
//移除监听器
if(locationManager != null){
locationManager.removeUpdates(loactionListener);
}
}
private void showLocation(final Location location){
//开启子线程获取位置信息 通过调用google的接口获取地址信息
new Thread(new Runnable() {
@Override
public void run() {
try{
//首先拼凑出反向地址编码的接口地址
StringBuilder url = new StringBuilder();
url.append("http://maps.googleapis.com/maps/api/geocode/json?latlng=");
url.append(location.getLatitude()).append(",");
url.append(location.getLongitude()).append("&sensor=false");
//通过Httpclient来获取服务器数据
HttpClient httpClient = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url.toString());
//在请求报头中指明语言,保证服务器返回的是中文数据
httpGet.addHeader("Accept-Language", "zh-CN");
HttpResponse httpResponse = httpClient.execute(httpGet);
if(httpResponse.getStatusLine().getStatusCode() == 200){
//如果访问成功
HttpEntity entity = httpResponse.getEntity();
String response = EntityUtils.toString(entity,"utf-8"); //从entity中获取数据
//通过json解析返回数据
JSONObject jsonObject = new JSONObject(response);
JSONArray resultArray = jsonObject.getJSONArray("results");
if(resultArray.length() > 0){
JSONObject subObject = resultArray.getJSONObject(0);
String address = subObject.getString("formatted_address");
Message msg = new Message();
msg.what = SHOW_LOCATION;
msg.obj = location.getLatitude()+"\n"+location.getLongitude()+"\n"+address;
handler.sendMessage(msg);
}
}
}catch(Exception e){
Message msg = new Message();
msg.what = SHOW_LOCATION;
msg.obj = location.getLatitude()+"\n"+location.getLongitude()+"\n"+"不能获取位置信息";
handler.sendMessage(msg);
e.printStackTrace();
}
}
}).start();
}
}
在配置文件中,要写明申请网络访问权限:
<uses-permission android:name="android.permission.INTERNET"/>
ok,这样就可以知道设备的经纬度信息和所在位置信息了。