Android那些事儿之LBS定位,实践测试lbs
最近一朋友让我了解下安卓LBS获取位置信息,于是动手实践了一把。搜了一圈发现有篇博文可以参考:Android那些事儿之LBS定位,但是原文作者没有提供源码下载,于是动手实现了,现记录下来备忘,代码附在后面各位有用得上的直接拿去。
以下是原文的转载:
2012-05-24 11:37:00
翻了翻Android Developer找到一个不错的东西LocationManager。LocationManager是通过listener的方式来告知调用者,而原来写好的模块是直接return的,于是得稍微改造一下:
首先定义一个Model:
- public class LocationData {
- String lat;
- String lon;
- String address;
- }
然后LBS的所有功能都封装到一个工具类里面:
首先在构造函数里面获取系统服务中的LocationManager:
- public class LBSTool {
- private Context mContext;
- private LocationManager mLocationManager;
- private LocationData mLocation;
- private LBSThread mLBSThread;
- private MyLocationListner mNetworkListner;
- private MyLocationListner mGPSListener;
- private Looper mLooper;
- public LBSTool(Context context) {
- mContext = context;
- //获取Location manager
- mLocationManager = (LocationManager)mContext.getSystemService(Context.LOCATION_SERVICE);
- }
- ......
- }
然后是入口方法,这里会启动一个子线程去获取地理位置信息,并让主线程进入等待,时长通过timeout设置
- /**
- * 开始定位
- * @param timeout 超时设置
- * @return LocationData位置数据,如果超时则为null
- */
- public LocationData getLocation(long timeout) {
- mLocation = null;
- mLBSThread = new LBSThread();
- mLBSThread.start();//启动LBSThread
- timeout = timeout > 0 ? timeout : 0;
- synchronized (mLBSThread) {
- try {
- Log.i(Thread.currentThread().getName(), "Waiting for LocationThread to complete...");
- mLBSThread.wait(timeout);//主线程进入等待,等待时长timeout ms
- Log.i(Thread.currentThread().getName(), "Completed.Now back to main thread");
- }
- catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- mLBSThread = null;
- return mLocation;
- }
子线程通过调用registerLocationListener开启位置服务的监听,并且讲监听器分配给指定looper
- private class LBSThread extends Thread {
- @Override
- public void run() {
- setName("location thread");
- Log.i(Thread.currentThread().getName(), "--start--");
- Looper.prepare();//给LBSThread加上Looper
- mLooper = Looper.myLooper();
- registerLocationListener();
- Looper.loop();
- Log.e(Thread.currentThread().getName(), "--end--");
- }
- }
- private void registerLocationListener () {
- Log.i(Thread.currentThread().getName(), "registerLocationListener");
- if (isGPSEnabled()) {
- mGPSListener=new MyLocationListner();
- //五个参数分别为位置服务的提供者,最短通知时间间隔,最小位置变化,listener,listener所在消息队列的looper
- mLocationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 5000, 0, mGPSListener, mLooper);
- }
- if (isNetworkEnabled()) {
- mNetworkListner=new MyLocationListner();
- mLocationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 3000, 0, mNetworkListner, mLooper);
- }
- }
isGPSEnabled和isNetworkEnabled分别为判断当前手机是否开启了GPS以及网络的状况(包含了是否开启wifi和移动网络),以决定使用哪一种服务提供者:GPS_PROVIDER或者NETWORK_PROVIDER。
- /**
- * 判断GPS是否开启
- * @return
- */
- public boolean isGPSEnabled() {
- if(mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
- Log.i(Thread.currentThread().getName(), "isGPSEnabled");
- return true;
- }
- else {
- return false;
- }
- }
- /**
- * 判断Network是否开启(包括移动网络和wifi)
- * @return
- */
- public boolean isNetworkEnabled() {
- return (isWIFIEnabled() || isTelephonyEnabled());
- }
- /**
- * 判断移动网络是否开启
- * @return
- */
- public boolean isTelephonyEnabled() {
- boolean enable = false;
- TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
- if (telephonyManager != null) {
- if (telephonyManager.getNetworkType() != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
- enable = true;
- Log.i(Thread.currentThread().getName(), "isTelephonyEnabled");
- }
- }
- return enable;
- }
- /**
- * 判断wifi是否开启
- */
- public boolean isWIFIEnabled() {
- boolean enable = false;
- WifiManager wifiManager = (WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
- if(wifiManager.isWifiEnabled()) {
- enable = true;
- Log.i(Thread.currentThread().getName(), "isWIFIEnabled");
- }
- return enable;
- }
当LocationManager在大于最短时间且检测到最小位置变化时,就会通知给监听器,然后我们就可以通过返回的经纬度信息去google服务器查找对应的地址,然后停止LocationManger的工作,解除LBSThread中的Looper,让LBSThread结束,最后通知主线程可以继续,整个流程结束。
- private class MyLocationListner implements LocationListener{
- @Override
- public void onLocationChanged(Location location) {
- // 当LocationManager检测到最小位置变化时,就会回调到这里
- Log.i(Thread.currentThread().getName(), "Got New Location of provider:"+location.getProvider());
- unRegisterLocationListener();//停止LocationManager的工作
- try {
- synchronized (mLBSThread) {
- parseLatLon(location.getLatitude()+"", location.getLongitude()+"");//解析地理位置
- mLooper.quit();//解除LBSThread的Looper,LBSThread结束
- mLBSThread.notify();//通知主线程继续
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- //后3个方法此处不做处理
- @Override
- public void onStatusChanged(String provider, int status, Bundle extras) {}
- @Override
- public void onProviderEnabled(String provider) {}
- @Override
- public void onProviderDisabled(String provider) {}
- };
- /**
- * 使用经纬度从goole服务器获取对应地址
- * @param 经纬度
- */
- private void parseLatLon(String lat, String lon) throws Exception {
- Log.e(Thread.currentThread().getName(), "---parseLatLon---");
- Log.e(Thread.currentThread().getName(), "---"+lat+"---");
- try {
- HttpClient httpClient = new DefaultHttpClient();
- HttpGet get = new HttpGet("http://ditu.google.cn/maps/geo?output=json&q="+lat+","+lon);
- HttpResponse response = httpClient.execute(get);
- String resultString = EntityUtils.toString(response.getEntity());
- JSONObject jsonresult = new JSONObject(resultString);
- if(jsonresult.optJSONArray("Placemark") != null) {
- mLocation = new LocationData();
- mLocation.lat = lat;
- mLocation.lon = lon;
- mLocation.address = jsonresult.optJSONArray("Placemark").optJSONObject(0).optString("address");
- }
- }
- catch (Exception e) {
- e.printStackTrace();
- }
- }
- /**
- * 注销监听器
- */
- private void unRegisterLocationListener () {
- if(mGPSListener!=null){
- mLocationManager.removeUpdates(mGPSListener);
- mGPSListener=null;
- }
- if(mNetworkListner!=null){
- mLocationManager.removeUpdates(mNetworkListner);
- mNetworkListner=null;
- }
- }
接下来可以在界面上安放个button:
- locationBtn.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- //return mode
- LBSTool lbs = new LBSTool(LBStestActivity.this);
- LocationData location = lbs.getLocation(120000);
- if (location != null) {
- Log.i("---lat---",location.lat);
- Log.i("---lon---",location.lon);
- Log.i("---address---",location.address);
- Toast.makeText(LBStestActivity.this, location.lat + " " + location.lon + " " + location.address, Toast.LENGTH_LONG).show();
- }
- }
- });
最后别忘了加入权限:
- <uses-permission android:name="android.permission.INTERNET" />
- <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
- <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
- <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
- <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
此外,LocationManager还有些高级的用法,比如设置一些关键参数,以及获取最后一次定位信息等等:
- Criteria criteria = new Criteria();
- criteria.setAccuracy(Criteria.ACCURACY_FINE); // 高精度
- criteria.setAltitudeRequired(false);
- criteria.setBearingRequired(false);
- criteria.setCostAllowed(true);
- criteria.setPowerRequirement(Criteria.POWER_LOW); // 低功耗
- String bestprovider = locationManager.getBestProvider(criteria, true); // 获取GPS信息
- Location location = locationManager.getLastKnownLocation(bestprovider); // 通过GPS获取位置
- Log.e("--bestprovider--", bestprovider);
- Log.e("--bestprovider--", location.getLatitude()+"");
本文出自 “Android那些事儿” 博客,请务必保留此出处http://winwyf.blog.51cto.com/4561999/875617
问题:
google api 过时了,google中国退出后, 这种方式:"HttpGet get = new HttpGet("http://ditu.google.cn/maps/geo?output=json&q="+lat+","+lon); "取不到地址信息了。
解决方法:
http://maps.google.com/maps/api/geocode/json?latlng=" + lat + "," + lon + "&language=zh-CN&sensor=false
效果:
源码:
Android那些事儿之LBS定位,实践测试lbs的更多相关文章
- Android之仿ele地图定位效果
PS:最近项目要求,希望在选择地址的时候能够仿ele来实现定位效果.因此就去做了一下.不过ele使用高德地图实现的,我是用百度地图实现的.没办法,公司说用百度那就用百度的吧.个人觉得高德应该更加的精准 ...
- 实现Android的不同精度的定位(基于网络和GPS)
解决方案: 实现Android的不同精度的定位(基于网络和GPS) Android中的定位服务的相关类基本上都在android.location包中,其中位置服务管理器(LocationManager ...
- LBS定位技术
http://www.cnblogs.com/LBSer/p/3295642.html LBS定位技术从方法上可分成三类:基于三角关系的定位技术.基于场景分析的定位技术.基于临近关系的定位技术(唐毅和 ...
- android 高德地图出现【定位失败key鉴权失败】
如题:android 高德地图出现[定位失败key鉴权失败] 原因:使用的是debug模式下的SHA1,发布的版本正确获取SHA1的方式见: 方法二使用 keytool(jdk自带工具),按照如下步骤 ...
- 【Android Api 翻译1】Android Texting(2)Testing Fundamentals 测试基础篇
Testing Fundamentals The Android testing framework, an integral part of the development environment, ...
- Android 设计随便说说之简单实践(合理组合)
上一篇(Android 设计随便说说之简单实践(模块划分))例举了应用商店设计来说明怎么做模块划分.模块划分主要依赖于第一是业务需求,具体是怎么样的业务.应用商店则包括两个业务,就是向用户展示appl ...
- 在Android Studio中进行单元测试和UI测试
本篇教程翻译自Google I/O 2015中关于测试的codelab,掌握科学上网的同学请点击这里阅读:Unit and UI Testing in Android Studio.能力有限,如有翻译 ...
- Android Texting(2)Testing Fundamentals 测试基础篇
Testing Fundamentals The Android testing framework, an integral part of the development environment, ...
- Android系统中是否开启定位及定位模式的判断
1.关于Android系统中不同的定位模式 Android系统中包括3中定位模式: 使用GPS.WLAN和移动网络 使用WLAN和移动网络 仅使用GPS 截图 特点 同时使用GPS.WIFI及基站 ...
随机推荐
- dubbo配置文件报错解决思路
导入dubbo项目到Eclipse,配置文件报了如下异常: Multiple annotations found at this line: - cvc-complex-type.2.4.c: The ...
- Nodejs学习笔记(十一)--- 数据采集器示例(request和cheerio)
目录 写在之前 示例 示例要求 采集器 加入代理 请求https 写在之后... 写在之前 很多人都有做数据采集的需求,用不同的语言,不同的方式都能实现,我以前也用C#写过,主要还是发送各类请求和正则 ...
- Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据
Atitit.列表页面and条件查询的实现最佳实践(1)------设置查询条件and提交查询and返回json数据 1. 1. 配置条件字段@Conditional 1 1 2. 2. 配置条件字段 ...
- atitit.自适应设计悬浮图片的大小and 位置
atitit.自适应设计悬浮图片的大小and 位置 #--------最好使用relate定位.. 中间,图片的大小和位置走能相对table, 没有遮罩左的或者哈面儿文本的问题,要悬浮,使用top:- ...
- 每天一个linux命令(4):mkdir命令
linux mkdir 命令用来创建指定的名称的目录,要求创建目录的用户在当前目录中具有写权限,并且指定的目录名不能是当前目录中已有的目录. 1.命令格式: mkdir [选项] 目录... 2.命令 ...
- Nginx在安装过程经常出现的问题
在Linux操作系统下搭建Nginx服务器,很多时候会出现不同的错误,在此我们在搭建过程中出现的错误进行一些总结: 主要问题有: 1.防火墙问题 2.缺少gc++ 3.缺少pcre.zlib库 解决办 ...
- 使用retrofit注意
retrofit-1.7.1 依赖以下包 okhttp-2.0.0 okio-1.0.0 okhttp-urlconnection-2.0.0 ExtCertPathValidatorExceptio ...
- 【转】iOS超全开源框架、项目和学习资料汇总
iOS超全开源框架.项目和学习资料汇总(1)UI篇iOS超全开源框架.项目和学习资料汇总(2)动画篇iOS超全开源框架.项目和学习资料汇总(3)网络和Model篇iOS超全开源框架.项目和学习资料汇总 ...
- 查看Exchange邮件队列(queue)
#加载Exchange管理模块 Add-PSSnapin Microsoft.Exchange.Management.PowerShell.snapin get-queue #查看队列 get-mes ...
- 【Android开发坑系列】如何让Service尽可能存活
流行的思路如下[2015-11-20更新]: 1.让Service杀不死.Service的onStartCommand返回START_STICKY,同时onDestroy里面调用startServic ...