`
byandby
  • 浏览: 1689206 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

android 位置包..............

阅读更多
   
    android.location 包提供了一些工具来实现基于位置的服务。主要包括 Geocoder 类和LocationManager服务。首先介绍 Geocoder。

1.使用Android进行地理编码

     如果打算使用地图做一些实际的事情,可能必须将地址(或位置)转换为纬度/经度对。此概念称为地理编码,android.location.Geocoder 类提供了此功能。实际上,Geocoder既提供了前向转换,也提供了后向转换--------它可以获取地址并返回经度/纬度,也可以将经度/纬度对转换为一组地址。该类提供了以下方法。
List<Address>  getFromLocation(double latitude,double longitude,int maxResults);
List<Address> getFromLocationName(String locationName, int maxResults, double lowerLeftLatitude, double lowerLeftLongitue, double upperRightLatitude, double upperRightLongitude);
List<Address>  getFromLocationName(String locationName, int maxResults)。

      事实证明,计算地址并不完全属于科学范畴,因为可以通过各种方式来描述位置。例如,getFromLocationName() 方法可以获得地方的名称、物理地址和机场编号,或者该位置的流行名称。因此,这些方法提供了一个地址列表,而不是一个地址。因为这些方法返回一个列表,所以最好提供1~5的maxResults 值来限制结果集,下面我们来看一个查询地址的例子,和原来一样我们得自己定义一个类来继承MapActivity,先来看看运行效果。



  我们的布局文件
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout android:layout_width="fill_parent"
    	android:layout_alignParentBottom="true"
    	android:layout_height="wrap_content" android:orientation="vertical">
		<EditText
			android:id="@+id/location"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:text="请输入地址..."/>
		<Button
			android:id="@+id/geocodeBtn"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:text="Find Location" />
    </LinearLayout>

    	
    	<com.google.android.maps.MapView
	        android:id="@+id/geoMap"
	    	android:clickable="true"
	    	android:layout_width="fill_parent"
	    	android:layout_height="320px"
	        android:apiKey="0XemFEdFemEDqY3dE3Ko9ELJX12MRLjJGKEJ01g"
                 />
            
</RelativeLayout>


  AndroidManifest.xml文件
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
	package="xiaohang.zhimeng" android:versionCode="1" android:versionName="1.0">
	<uses-sdk android:minSdkVersion="10" />
	<application android:icon="@drawable/icon" android:label="@string/app_name">
		<uses-library android:name="com.google.android.maps" />
		<activity android:name=".MainActivity" 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.ACCESS_FINE_LOCATION" />
	<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
	<uses-permission android:name="android.permission.INTERNET" />
</manifest>


   我们的MainActivity类
package xiaohang.zhimeng;

import java.util.List;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;

public class MainActivity extends MapActivity {

	Geocoder geocoder = null;
	MapView mapView = null;

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

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

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);
		mapView = (MapView) findViewById(R.id.geoMap);
		mapView.setBuiltInZoomControls(true);
		// 经度:116.3946533203125
		// 纬度:39.87601941962116
		int lat = (int) (39.87601941962116 * 1E6);
		int lng = (int) (116.3946533203125 * 1E6);
		GeoPoint pt = new GeoPoint(lat, lng);
		mapView.getController().setZoom(10);
		mapView.getController().setCenter(pt);

		Button geoBtn = (Button) findViewById(R.id.geocodeBtn);

		geocoder = new Geocoder(this);

		geoBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				try {
					EditText loc = (EditText) findViewById(R.id.location);
					String locationName = loc.getText().toString();

					List<Address> addressList = geocoder.getFromLocationName(
							locationName, 5);
					if (addressList != null && addressList.size() > 0) {
						int lat = (int) (addressList.get(0).getLatitude() * 1E6);
						int lng = (int) (addressList.get(0).getLongitude() * 1E6);

						GeoPoint pt = new GeoPoint(lat, lng);
						mapView.getController().setZoom(15);
						mapView.getController().setCenter(pt);
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}
}


   但是如果这个类要是这么写,就会有问题了。但是感觉这么写是没错误的,但是每当你点击一次Find Location按钮就会出现一次异常(IOException),异常见下图。



    说什么服务不可以用,去网上一搜 遇见这问题的人还真不少,eoe上边也有 但是没说怎么解决,不了了之了。至于为什么有这个异常,我也不能准确的告诉大家 我也不太清楚,网上说什么的都有。 什么 是bug之类的 等等,大家可以去网上搜搜 最后自己这样写一次试试。但是解决方法还是有的,在这里http://code.google.com/p/android/issues/detail?id=8816  老外搞出来的方法,他们讨论的也很火热,感觉比我们 积极很多。大家看 21楼就行了, 呵呵。

   具体解决方法就是自己定义了两个静态方法,我把这两个方法放到了MapUtility类中,这个类是我自己定义的。
MapUtility类
package xiaohang.zhimeng.tool;

import java.io.IOException;
import java.io.InputStream;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
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 MapUtility {
	public static JSONObject getLocationInfo(String address) {

		HttpGet httpGet = new HttpGet("http://maps.google."
				+ "com/maps/api/geocode/json?address=" + address
				+ "ka&sensor=false");
		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 (ClientProtocolException e) {
		} catch (IOException e) {
		}

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

		return jsonObject;
	}

	// After executing this, another method converts that JSONObject into a
	// GeoPoint.

	public static GeoPoint getGeoPoint(JSONObject jsonObject) {

		Double lon = new Double(0);
		Double lat = new Double(0);

		try {

			lon = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
					.getJSONObject("geometry").getJSONObject("location")
					.getDouble("lng");

			lat = ((JSONArray) jsonObject.get("results")).getJSONObject(0)
					.getJSONObject("geometry").getJSONObject("location")
					.getDouble("lat");

		} catch (JSONException e) {
			e.printStackTrace();
		}
		return new GeoPoint((int) (lat * 1E6), (int) (lon * 1E6));
	}

}


   这两个方法就不多解释了,反正我们最终的目的是需要一个GeoPoint对象,它给我们返回正确的GeoPoint对象就行了,大家可以去原地址去看看他们怎么讨论了,链接在上边我已经贴出来了,现在我们在搜索tian an men 就会把tian an men给我们显示在地图的中央了,没修改之前是 一点 一次异常,现在的效果如下图,(大家知道 tian an men是啥意思吧,自动eye被 oracle搞过一次 法律意识越来越强啊。。。。  )



     要体验地理编码在Android中的使用,可以在 EditText字段中键入位置名称或它的地址,然后点击 Find Location按钮。要找到某个位置的地址,调用 Geocoder的 getFromLocationName()方法。位置可以是地址或流行名称,比如 “故宫”。地理编码是一项实时操作,所以根据Android文档的建议,我们建议将结果限制为5个。对getFromLocationName()的调用返回一个地址列表。示例程序获取该地址列表并处理第一个地址(如果存在)。每个地址都具有经纬度。可以使用它来创建 GeoPoint。然后调用地图控制器并导航到该点。缩放级别可以设置为1~21 (包括1和21)的整数。在从1向21移动时,缩放级别每次将增加两级。

      对于地理编码,应该了解几点。第一,返回的地址并不总是准确的地址。显然,由于返回的地址列表取决于输入的准确度,所以需要尽量向 Geocoder 提供准确的位置名称。第二,尽量将 maxResults 设置为1~5的值。最后,应该认真考虑在不同于UI线程的线程中执行地理编码操作。这有两个原因。第一个很明显:这项操作很耗时,而且你一定不希望UI在进行地理编码时停顿,如果停顿会阻塞整个用户界面。当在执行一些耗时的操作的时候,不能及时地分发 事件,包括用户界面重绘事件。从用户的角度来看,应用程序看上去像挂掉了。更糟糕的是,如果阻塞应用程序的时间过长(5秒钟)Android会向用户提示 一些信息,即打开一个“应用程序没有相应(application not responding)”ANR 的对话框,关于线程的更多内容请大家看这里http://byandby.iteye.com/blog/825071  第二个原因是,对于移动设备,始终需要假设网络连接可能丢失并且连接很弱。因此,需要恰当地处理I/O 异常和超时。计算出地址以后,就可以将结果发送给UI线程,下面我们看看使用后台线程进行地理编码,这个例子和上一个例子一样 唯一不同的就是 这个例子把查询地址的操作放到 另外一个辅助线程里来执行了,上一个是所有的操作都在UI线程里,下面是我们的Activity类,GeocodingDemoActivity,我们看看怎么实现。。。

  GeocodingDemoActivity类
package xiaohang.zhimeng;

import java.util.List;
import org.json.JSONObject;
import xiaohang.zhimeng.tools.MapUtility;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.location.Address;
import android.location.Geocoder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapActivity;
import com.google.android.maps.MapView;

public class GeocodingDemoActivity extends MapActivity {

	Geocoder geocoder = null;
	MapView mapView = null;
	ProgressDialog progDialog = null;
	List<Address> addressList = null;

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

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

	@Override
	protected void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.main);
		mapView = (MapView) findViewById(R.id.geoMap);
		mapView.setBuiltInZoomControls(true);
		// 北京经纬度
		// 经度:116.3946533203125
		// 纬度:39.87601941962116
		int lat = (int) (39.87601941962116 * 1000000);
		int lng = (int) (116.3946533203125 * 1000000);
		GeoPoint pt = new GeoPoint(lat, lng);
		mapView.getController().setZoom(10);
		mapView.getController().setCenter(pt);

		Button geoBtn = (Button) findViewById(R.id.geocodeBtn);
		geoBtn.setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				EditText loc = (EditText) findViewById(R.id.location);
				String locationName = loc.getText().toString();
				progDialog = ProgressDialog.show(GeocodingDemoActivity.this,
						"Processing.....", "Finding Location", true, false);
				findLocation(locationName);

			}
		});
	}

	private void findLocation(final String locationName) {

		Thread thrd = new Thread() {
			@Override
			public void run() {
				System.out.println("线程Name是:"
						+ Thread.currentThread().getName());
				try {
					// do backgrond work
					JSONObject jo = MapUtility.getLocationInfo(locationName);
					GeoPoint gp = MapUtility.getGeoPoint(jo);
					Message message = uiCallback.obtainMessage();
					message.obj = gp;
					message.sendToTarget();
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		};
		thrd.start();
	}

	// ui thread callback handler
	private Handler uiCallback = new Handler() {
		public void handleMessage(android.os.Message msg) {
			System.out.println("线程Name是:" + Thread.currentThread().getName());
			progDialog.dismiss();
			GeoPoint pt = (GeoPoint) msg.obj;
			if (pt != null) {
				mapView.getController().setZoom(15);
				mapView.getController().setCenter(pt);
			} else {
				Dialog foundNothingDlg = new AlertDialog.Builder(
						GeocodingDemoActivity.this).setIcon(0)
						.setTitle("Failed to Find Location")
						.setPositiveButton("OK", null)
						.setMessage("Location Not Found").create();
				foundNothingDlg.show();
			}
		};
	};
}


   这次我们再来看看运行效果。







   从下图我们能看出 查询操作在不同的线程中完成。



  最后在提醒大家如果下载源码 注意替换成自己的 密钥。
 
  源码已上传
  • 大小: 140.5 KB
  • 大小: 63 KB
  • 大小: 51 KB
  • 大小: 64.2 KB
  • 大小: 38.3 KB
  • 大小: 49.6 KB
  • 大小: 22.2 KB
  • test_location.rar (52.4 KB)
  • 描述: 查询操作在辅助线程完成
  • 下载次数: 111
7
7
分享到:
评论
3 楼 仁义忠信是汪屁稀大人 2014-06-04  
很感谢 很详细
2 楼 leeny 2011-11-09  
为什么我用楼主写的代码,查不出经纬度呢,求解啊
1 楼 yilee 2011-07-22  
getFromLocationName(,)输入中文会抛异常,但如果你输"tian an men"就会返回正确值..很奇怪

相关推荐

    android 位置包.........

    查找操作在辅助线程执行 博文链接:https://byandby.iteye.com/blog/1036038

    v7包解决importandroid.support.annotation.RequiresApi

    v7包解决importandroid.support.annotation.RequiresApi

    android 最新版android-support-v4.jar

    注意,这是最新版的android_support-v4.jar包,里面包含了最新添加进去的android.support.v4.view.animation.类,今天是2015年10月7号,这是截至到今天位置最新的android-support-v4.jar

    新版Android开发教程.rar

    难点在于位置营销。 设备商通过卖设备、内置特色应用来获得盈利。也可以兼职专业软件开发者进行赢利。 Google 自身通过基于统一平台为用户提供信息来盈利。 Android Android Android Android 的优势 � 源代码完全...

    android studio 打包自动生成版本号与日期,apk输入路径详解

    打开项目选择如图示1 (build.gradle 项目位置) 二. 1. build.gradle 文件添加内容如下。gradle是【com.android.tools.build:gradle:3.0.0 以下版本】 android{ defaultConfig {...} 自动追加版本号和版本名称 ...

    android adb shell 命令大全

    7. AVD(模拟器)所在位置: Linux(~/.android/avd) Windows(C:\Documents and Settings\Administrator\.android\avd) 8. 启动DDMS: ddms 9. 显示当前运行的全部模拟器: adb devices 10. 对某一模拟器执行...

    Android Studio debug.keystore位置介绍

    如果你在网上搜debug.keystore的位置,大部分文章都会告诉你在 C:\Users\XXX\.android 目录下,但我电脑的该目录下确实没有这个文件,放入同事的debug.keystore也不会生效。 后来在Android SDK的子目录.android下搜...

    AppUpdate-一个简单、轻量、可随意定制 的Android版本更新库 .zip

    支持Android N 支持Android O 支持中/英文双语 支持自定内置对话框的样式 使用HttpURLConnection下载,未集成其他第三方框架更加详细的文档参阅此处《AppUpdate API文档》DownloadManager:配置文档初始化使用...

    Android代码-ViewPagerIndicator

    2. 支持自定义滑动块样式和位置 3. 支持自定义切换tab的过渡效果 4. 支持子界面的预加载和界面缓存 5. 支持设置界面是否可滑动 6. android:minSdkVersion="14" 7.导入方式 gradle导入 compile '...

    Android-app.rar

    Android项目源码GPS实时定位位置共享 Android项目源码QQ登录语音合成桌面控件天气预报 Android项目源码v2ex技术社区非官方客户端 Android项目源码事件日程管理APP Android项目源码任阅小说阅读器高仿追书神器 ...

    Android状态保存、用户偏好设置保存、通过universal_image_loder网络加载图片并做图片缓存处理Demo

    1、将universal-image-loder...jar包放入项目的libs文件里,并引入。 2、将MyApplication.java类放入项目,具体个性细节设置在这个类里面设置。 3、在要加载图片并缓存的地方写入下边的代码: //网络获取图片,并...

    Android SDK开发包国内官网下载地址.pdf

    Android SDK开发包国内官网下载地址.pdf 不知道是因为最近kaihui还是怎么的,打开android sdk官方网站特别的慢,想下载最新版本的platform几乎变成不可能完成的任务,不知道为什么Google不像Apache那样在各国设立...

    osmdroid-android-5.6.4.aar

    设计用于完全替换 Android 内部的 MapView 类,包含一个模块化的地图拼图,支持在线和离线地图以及覆盖地图,支持标注图标、位置跟踪和绘制形状。地图引擎使用 OpenStreetMap

    Android高级编程.pdf

    1.9.1 开发包中的资源 1.9.2 理解Android软件栈 1.9.3 Dalvik虚拟机 1.9.4 Android应用程序架构 1.9.5 Android库 1.9.6 高级Android库 1.10 小结 第2章 开始入手 2.1 Android开发 2.1.1 开始前的准备工作 2.1.2 ...

    adb1.0.26包含fastboot.exe

    ADB,即 Android Debug Bridge,它是 Android 开发/测试人员不可替代的强大工具,也是 Android 设备玩家的好玩具。 注:有部分命令的支持情况可能与 Android 系统版本及定制 ROM 的实现有关。 基本用法 命令语法 ...

    android源码包集合4

    动画效果 translate、scale、alpha、rotate 切换Activity动画 控件位置调整.zip 北京公交线路查询(离线).rar 基于socket通讯的文件续传!.rar 基于股票的一个Android应用(内含源码) .rar 多点缩放字体DEMO .rar ...

    ADB源码(android / platform / system / core)

    adb源码官网:https://android.googlesource.com/platform/system/core/可在以上链接获取adb源码集成到项目中。若下载失败可以下载上面的附件。

     Android的SharedPreferences的使用

    其存储位置在/data/data/&lt;包名&gt;/shared_prefs目录下。SharedPreferences对象本身只能获取数据而不支持存储和修改,存储修改是通过Editor对象实现。比较经典的使用方式例如用户输入框对过往登录账户的存储。 详细介绍...

Global site tag (gtag.js) - Google Analytics