Android开发之位置定位详解与实例解析(GPS定位、Google网络定位,BaiduLBS(SDK)定位)
在android开发中地图和定位是很多软件不可或缺的内容,这些特色功能也给人们带来了很多方便。定位一般分为三种发方案:即GPS定位、Google网络定位以及基站定位
最简单的手机定位方式当然是通过GPS模块(现在大部分的智能机应该都有了)。GPS方式准确度是最高的,但是它的缺点也非常明显:1,比较耗电;2,绝大部分用户默认不开启GPS模块;3,从GPS模块启动到获取第一次定位数据,可能需要比较长的时间;4,室内几乎无法使用。这其中,缺点2,3都是比较致命的。需要指出的是,GPS走的是卫星通信的通道,在没有网络连接的情况下也能用。
另外一种常见的定位方式是基站定位。大致思路就是采集到手机上的基站ID号(cellid)和其它的一些信息(MNC,MCC,LAC等等),然后通过网络访问一些定位服务,获取并返回对应的经纬度坐标。基站定位的精确度不如GPS,但好处是能够在室内用,只要网络通畅就行。
还有Wifi定位。和基站定位类似,这种方式是通过获取当前所用的wifi的一些信息,然后访问网络上的定位服务以获得经纬度坐标。因为它和基站定位其实都需要使用网络,所以在Android也统称为Network方式。
最后需要解释一点的是AGPS方式。很多人将它和基站定位混为一谈,但其实AGPS的本质仍然是GPS,只是它会使用基站信息对获取GPS进行辅助,然后还能对获取到的GPS结果进行修正,所以AGPS要比传统的GPS更快,准确度略高。
本文分别介绍GPS定位、以及基于Google的网络Wifi定位,以及最后的使用百度LBS的定位(百度LBS的定位功能比较强大,集成了GPS,网络wifi以及基站定位三种定位方法)。主要用例就是利用这三种方法获取位置经纬度,以及利用经纬度来获取所在的城市及区域
而根据经纬度来获取所在位置的城市及区域全部都是采用百度地图的API:http://api.map.baidu.com/geocoder?output=json&location=39.983228,116.491146key=您的key
,这个key需要你自己申请百度开发者账号来得到的。
首先来看看定位实例效果图如下:
1.GPS定位
(1)打开GPS设置
private void openGPSSettings() {
LocationManager alm = (LocationManager) this
.getSystemService(Context.LOCATION_SERVICE);
if (alm.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER)) {
Toast.makeText(this, "GPS模块正常", Toast.LENGTH_SHORT).show();
doWork();
return;
} else {
Toast.makeText(this, "请开启GPS!", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(Settings.ACTION_SECURITY_SETTINGS);
startActivityForResult(intent, 0); // 此为设置完成后返回到获取界面
} }
(2)通过GPS获取经纬度信息
private void doWork() { String msg = ""; LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE); Criteria criteria = new Criteria();
// 获得最好的定位效果
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(false);
criteria.setCostAllowed(false);
// 使用省电模式
criteria.setPowerRequirement(Criteria.POWER_LOW);
// 获得当前的位置提供者
String provider = locationManager.getBestProvider(criteria, true);
// 获得当前的位置
Location location = locationManager.getLastKnownLocation(provider); double latitude = location.getLatitude();
double longitude = location.getLongitude(); locationString = "&location=" + latitude + "," + longitude;
keyString = "&key=您的key";
questURL = questURL + locationString + keyString; new ReadJSONFeedTask().execute(questURL);
}
(3)由经纬度获取所在城市和区域的ReadJSONFeedTask类的实现:
/**
* 由经纬度获取所在的城市及区域信息
* @author caizhiming
*
*/
private class ReadJSONFeedTask extends AsyncTask<String, Void, String> { StringBuilder stringBuilder = new StringBuilder(); @Override
protected String doInBackground(String... urls) {
// TODO Auto-generated method stub
return readJSONFeed(urls[0]);
} @Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
String strItem; try { JSONObject jsonObject = new JSONObject(result);
JSONObject resultObject = jsonObject.getJSONObject("result");
JSONObject addressComponentObject = resultObject
.getJSONObject("addressComponent");
String city = addressComponentObject.getString("city");
String district = addressComponentObject.getString("district"); city = "城市:" + city;
district = " 区:" + district;
stringBuilder.append(city + district);
textView.setText(stringBuilder.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
/**
* 请求json数据
* @param url
* @author caizhiming
*/
public String readJSONFeed(String url) {
StringBuilder stringBuilder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse response;
try {
response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
} else {
Log.e("JSON", "Failed to download file");
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringBuilder.toString();
}
2. 网络WIFI定位
(1) 通过网络WIFI来获取经纬度信息:
/* ====================Google Location By NetWork=========================== */
private void getLocationByNetwork() {
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener() { // Provider的状态在可用、暂时不可用和无服务三个状态直接切换时触发此函数
@Override
public void onStatusChanged(String provider, int status,
Bundle extras) { } // Provider被enable时触发此函数,比如GPS被打开
@Override
public void onProviderEnabled(String provider) { } // Provider被disable时触发此函数,比如GPS被关闭
@Override
public void onProviderDisabled(String provider) { } // 当坐标改变时触发此函数,如果Provider传进相同的坐标,它就不会被触发
@Override
public void onLocationChanged(Location location) {
if (location != null) {
Log.e("Map",
"Location changed : Lat: " + location.getLatitude()
+ " Lng: " + location.getLongitude());
}
}
};
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER, 1000, 0, locationListener);
Location location = locationManager
.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
double latitude = 0;
double longitude = 0;
if (location != null) {
latitude = location.getLatitude(); // 经度
longitude = location.getLongitude(); // 纬度
} locationString = "&location=" + latitude + "," + longitude;
keyString = "&key=你的key";
questURL = questURL + locationString + keyString;
Toast.makeText(this, locationString, Toast.LENGTH_LONG).show();
new ReadJSONFeedTask().execute(questURL);
}
(2)由经纬度获取所在城市和区域的ReadJSONFeedTask类的实现:
/**
* 由经纬度获取所在的城市及区域信息
* @author caizhiming
*
*/
private class ReadJSONFeedTask extends AsyncTask<String, Void, String> { StringBuilder stringBuilder = new StringBuilder(); @Override
protected String doInBackground(String... urls) {
// TODO Auto-generated method stub
return readJSONFeed(urls[0]);
} @Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
String strItem; try { JSONObject jsonObject = new JSONObject(result);
JSONObject resultObject = jsonObject.getJSONObject("result");
JSONObject addressComponentObject = resultObject
.getJSONObject("addressComponent");
String city = addressComponentObject.getString("city");
String district = addressComponentObject.getString("district"); city = "城市:" + city;
district = " 区:" + district;
stringBuilder.append(city + district);
textView.setText(stringBuilder.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
/**
* 请求json数据
* @param url
* @author caizhiming
*/
public String readJSONFeed(String url) {
StringBuilder stringBuilder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse response;
try {
response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
} else {
Log.e("JSON", "Failed to download file");
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringBuilder.toString();
}
3.使用百度LBS的SDK定位
(1)导入百度的LBS的SDK开发Jar包,开发者可以到百度开发者中心去下载即可。即BaiduLBS_Android.jar包,放在项目的libs目录下即可。需要注意的是,同时需要在libs目录下建立armeabi目录,并在该目录下放sdk中的liblocSDK4d.so文件,这样才能使用sdk。
(2)初始化百度LBS定位信息,包括初始化定位客户端,定位监听器,定位模式等信息:
/**
* baidu lbs location
*
* @author caizhiming
*/
private void InitLocation() {
Log.v("LocationActivity", "InitLocation"); mLocationClient = new LocationClient(this.getApplicationContext()); // 声明LocationClient类
myListener = new MyLocationListener();
mLocationClient.registerLocationListener(myListener); // 注册监听函数 LocationClientOption option = new LocationClientOption();
option.setLocationMode(tempMode);// 设置定位模式
option.setCoorType(tempcoor);// 返回的定位结果是百度经纬度,默认值gcj02
int span = 3000; option.setScanSpan(span);// 设置发起定位请求的间隔时间为5000ms
option.setIsNeedAddress(false);
mLocationClient.setLocOption(option);
}
另外,还需要在AndroidMenifest.xml中配置key信息如下:
<!-- meta-data需要写在application中 -->
<meta-data
android:name="com.baidu.lbsapi.API_KEY"
android:value="您的key" />
最后还需要AndroidMenifest.xml中配置相应需要的权限如下:
<!-- baidu lbs -->
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.READ_PHONE_STATE" >
</uses-permission>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" >
</uses-permission>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" >
</uses-permission>
<uses-permission android:name="android.permission.READ_LOGS" >
</uses-permission>
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
(3)启动百度LBS的定位服务并获取经纬度等信息:
/**
* baidu lbs location
*
* @author caizhiming
*/
private void getLocationByBaiduLBS() { Log.v("LocationActivity", "getLocationByBaiduLBS");
mLocationClient.start();
}
/**
* baidu lbs location
*
* @author caizhiming
*/
public class MyLocationListener implements BDLocationListener {
@Override
public void onReceiveLocation(BDLocation location) {
Log.v("LocationActivity", "MyLocationListener-onReceiveLocation");
if (location == null)
return;
StringBuffer sb = new StringBuffer(256);
sb.append("time : ");
sb.append(location.getTime());
sb.append("\nerror code : ");
sb.append(location.getLocType());
sb.append("\nlatitude : ");
sb.append(location.getLatitude());
sb.append("\nlontitude : ");
sb.append(location.getLongitude());
sb.append("\nradius : ");
sb.append(location.getRadius());
if (location.getLocType() == BDLocation.TypeGpsLocation) {
sb.append("\nspeed : ");
sb.append(location.getSpeed());
sb.append("\nsatellite : ");
sb.append(location.getSatelliteNumber());
} else if (location.getLocType() == BDLocation.TypeNetWorkLocation) {
sb.append("\naddr : ");
sb.append(location.getAddrStr());
}
logMsg(sb.toString()); locationString = "&location=" + location.getLatitude() + ","
+ location.getLongitude();
keyString = "&key=你的key";
questURL = questURL + locationString + keyString;
new ReadJSONFeedTask().execute(questURL); }
}
(4)由经纬度获取所在城市和区域的ReadJSONFeedTask类的实现:
/**
* 由经纬度获取所在的城市及区域信息
* @author caizhiming
*
*/
private class ReadJSONFeedTask extends AsyncTask<String, Void, String> { StringBuilder stringBuilder = new StringBuilder(); @Override
protected String doInBackground(String... urls) {
// TODO Auto-generated method stub
return readJSONFeed(urls[0]);
} @Override
protected void onPostExecute(String result) {
// TODO Auto-generated method stub
String strItem; try { JSONObject jsonObject = new JSONObject(result);
JSONObject resultObject = jsonObject.getJSONObject("result");
JSONObject addressComponentObject = resultObject
.getJSONObject("addressComponent");
String city = addressComponentObject.getString("city");
String district = addressComponentObject.getString("district"); city = "城市:" + city;
district = " 区:" + district;
stringBuilder.append(city + district);
textView.setText(stringBuilder.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} } }
/**
* 请求json数据
* @param url
* @author caizhiming
*/
public String readJSONFeed(String url) {
StringBuilder stringBuilder = new StringBuilder();
HttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet(url);
HttpResponse response;
try {
response = client.execute(httpGet);
StatusLine statusLine = response.getStatusLine();
int statusCode = statusLine.getStatusCode();
if (statusCode == 200) {
HttpEntity entity = response.getEntity();
InputStream content = entity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(content));
String line;
while ((line = reader.readLine()) != null) {
stringBuilder.append(line);
}
} else {
Log.e("JSON", "Failed to download file");
}
} catch (ClientProtocolException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return stringBuilder.toString();
}
Android开发之位置定位详解与实例解析(GPS定位、Google网络定位,BaiduLBS(SDK)定位)的更多相关文章
- Android开发——事件分发机制详解
0. 前言 转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52566965 深入学习事件分发机制,是为了解决在Android开发中 ...
- Android开发 ExpandableListView 可折叠列表详解
前言 在需要实现一个List的item需要包含列表的时候,我们就可以选择ExpandableListView. 其实这个View的原始设计还是ListView的那套.就是增加2层的ListView而已 ...
- Android开发:程序目录结构详解
HelloWorld程序的目录结构概述 我们可以在文件夹中看到,HelloWorld程序的目录主要包括:src文件夹.gen文件夹.Android文件夹.assets.res文件夹. AndroidM ...
- Android 开发 存储目录的详解
简介 Android设备,有3个地方的文件存储位置,他们分别是: 内部存储空间(用户无法浏览到此目录) 外部存储空间(就是手机自身的文件管理目录,用户可以浏览) SD卡的存储空间(需要插入T卡) Sh ...
- Android 开发 MaterialDialog框架的详解
前言 开始之前还是需要废话一下,因为有一些坑需要告知.首先MaterialDialog在GitHub上作者已经转型使用100% Kotlin语言编写,虽然可以在Java里调用Kotlin使用.但是个人 ...
- android 开发 View _5_ Paint详解
转载:http://blog.csdn.net/abcdef314159 //Paint的setStyle,Style共有3种 setStyle(Style style) Paint.Style.FI ...
- android开发之动画的详解 整理资料 Android开发程序小冰整理
/** * 作者:David Zheng on 2015/11/7 15:38 * * 网站:http://www.93sec.cc * * 微博:http://weibo.com/mcxiaob ...
- Android开发之线性布局详解(布局权重)
布局权重 线性布局支持给个别的子视图设定权重,通过android:layout_weight属性.就一个视图在屏幕上占多大的空间而言,这个属性给其设 定了一个重要的值.一个大的权重值,允许它扩大到填充 ...
- Android开发——HandlerThread以及IntentService详解
.HandlerThread Android API提供了HandlerThread来创建线程.官网的解释是: //Handy class for starting a new thread that ...
随机推荐
- vim多标签,多窗口
多标签 进入vim前 vim -p <文件名> 以多标签形式打开文件.如vim -p * 就是编辑当前目录的所有文件, vim编辑中 :tabnew 增加一个标签 :tabc 关闭当前的t ...
- bzoj1007
其实吧,就是一个半平面交,而且不用考虑转回来的情况,所以只要极角排序然后用栈即可给的是点斜式,比极角很方便至于完整版的半平面交还没写过,看到再说吧 ..] of longint; v:..] of b ...
- bzoj1103
其实这道题和以前在poj上做过的将树映射到树状数组的题目很像 首先不难想到,将一条边从土路修成公路,只对以这条边连接的孩子结点为根的子树有影响: 于是和之前那道poj的题目很像,后序遍历树,对每个节点 ...
- C#编程实现Excel文档中搜索文本
有了在Word文档中编程实现搜索文本的经验,在Excel中实现这个功能也并非难事. 打开Excel的VBA帮助,查看Excel的对象模型,很容易找到完成这个功能需要的几个集合和对象:Applicati ...
- Codevs_1166_[NOIP2007]_矩阵取数游戏_(动态规划+高精度)
描述 http://codevs.cn/problem/1166/ 分析 #include <iostream> #include <cstring> #include < ...
- 深入浅MFC
视图类CView 在MFC"文档/视图"架构中,CView类是所有视图类的基类,它提供了用户自定义视图类的公共接口.在"文档/视图"架构中,文档负责管理和维护数 ...
- ☀【css】透明
让IE浏览器支持RGBA颜色http://www.hujuntao.com/web/css/ie-browser-support-for-rgba-color.html 透明纯色背景 backgrou ...
- 用PowerShell批量部署wsp包
转:http://www.xuebuyuan.com/168337.html 提供wsp部署的参数: $wsppath:wsp文件所在的路径,如"c:\" $wspnames:路径 ...
- [King.yue]关于代码调试时的缓存问题的一个解决办法
后台构造数据更改之后,页面数据一直不变,试过各种办法,清空浏览器缓存,停止端口重新运行,关掉程序重新打开,都不可以.最终全部重新生成之后,终于可以正常调试了. 另:调试ASP.NET网站程序的时候,为 ...
- [Stephen]关于Ext.net fileupload 的兼容性解决问题
在firefox下,利用fileupload上传图片后,通过后端将image 的src路径进行更新,刷新前段界面显示没有问题. 但是在以IE为内核的360中,这种上传后的更新导致一个命名为Action ...