在做一个软件时,用到了定位功能。网上有很多关于google 的GPS定位,但网上关于google定位都没有用,
搜索下原因:(这里建议大家在中国就尽量不使用系统自带的定位)
因为Google的服务器不在中国(就算能网上关于定位的代码能用,那也非常的慢,除非你的应用是在国外使用)
由于网络等原因所以定位一般会失败
于是转向使用百度api来定位。
所用到的百度API参考地址。
取得位置的百度官方sdk参考 Android定位SDK
由坐标获取地址方法参考 Geocoding API 的 7.逆地理编码
先讲解怎么使用百度api获取获取地理坐标
准备工作:
(1)第一步,下载定位Android locSDK3.3。
下载地址:http://developer.baidu.com/map/static/doc/locSDK3.3.zip
(2)第二步,解压缩Android locSDK3.3
准备工作至此已经结束。
一、工程配置
1、第一步,在工程里新建libs文件夹,将开发包里的locSDK_3.3.jar拷贝到libs根目录下,将liblocSDK3.so拷贝到libs\armeabi目录下,拷贝完成后的工程目录如下图所示;
2、第二步(第一步导入后可以使用就不用这一步了):在工程属性->Java Build Path->Libraries中选择“Add External JARs”,选定locSDK_3.3.jar,确定后返回。
通过以上两步操作后,您就可以正常使用百度地图定位SDK为您提供的全部功能了。
在AndroidManifest.xml加入如下所示权限及server
在
由于Location.java继承自Application,所以需要在配置文件中
我做好的如下所示
补充:安列参考
在http://blog.csdn.net/ryantang03/article/details/7951260博客中提到可以通过 Android定位SDK 直接获取地址,但是经过实验不行。或许我这地方并不有名的原因。
于是我使用 Android定位SDK 加 Geocoding API的模式来获取位置。
为了获取的地理坐标能在函数中被调用,我封装了定位函数
MyBaiduLotion.java
package com.baidulocation; import android.content.Context; import com.baidu.location.BDLocation; import com.baidu.location.BDLocationListener; import com.baidu.location.LocationClient; import com.baidu.location.LocationClientOption; public class MyBaiduLotion { Context myContext; private LocationClient locationClient = null; private static final int UPDATE_TIME = 4000; private static int LOCATION_COUTNS = 0; private boolean isFinish = false; MyBDcoordinate myBDcoordinate = null; MyLocation myLocation; String strlocation = ""; public MyBaiduLotion(Context context) { // TODO Auto-generated constructor stub myContext = context; myLocation = new MyLocation(); initLockPst(); } class MyBDcoordinate{ double Latitude; double Longitude; } private void initLockPst(){ locationClient = new LocationClient(this.myContext); //设置定位条件 LocationClientOption option = new LocationClientOption(); option.setOpenGps(true); //是否打开GPS option.setCoorType("bd09ll"); //设置返回值的坐标类型。 option.setPriority(LocationClientOption.NetWorkFirst); //设置定位优先级 option.setProdName("LocationDemo"); //设置产品线名称。强烈建议您使用自定义的产品线名称,方便我们以后为您提供更高效准确的定位服务。 option.setScanSpan(UPDATE_TIME); //设置定时定位的时间间隔。单位毫秒 locationClient.setLocOption(option); //注册位置监听器 locationClient.registerLocationListener(new BDLocationListener() { @Override public void onReceiveLocation(BDLocation location) { // TODO Auto-generated method stub if(myBDcoordinate != null){ stopOpetateClient(); //locationInfoTextView.setText("stop" + LOCATION_COUTNS); return; } if(LOCATION_COUTNS > 5){ stopOpetateClient(); return; } if (location == null) { LOCATION_COUTNS ++; return; } //location.getLocType(); //location.getLatitude() //location.getLongitude(); if(location.getLocType() != 161){ LOCATION_COUTNS ++; return; } myBDcoordinate = new MyBDcoordinate(); myBDcoordinate.Latitude = location.getLatitude(); myBDcoordinate.Longitude = location.getLongitude(); } @Override public void onReceivePoi(BDLocation location) { } }); } private void stopOpetateClient(){ locationClient.stop(); isFinish = true; } private void startOpetateClient(){ locationClient.start(); /* *当所设的整数值大于等于1000(ms)时,定位SDK内部使用定时定位模式。 *调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。 *如果定位SDK根据定位依据发现位置没有发生变化,就不会发起网络请求, *返回上一次定位的结果;如果发现位置改变,就进行网络请求进行定位,得到新的定位结果。 *定时定位时,调用一次requestLocation,会定时监听到定位结果。 */ isFinish = false; locationClient.requestLocation(); } public boolean getIsFinish(){//获取定位是否完成或终止 return isFinish; } public void opetateClient(){//开始或停止。 if (locationClient == null) { return; } if (locationClient.isStarted()) { stopOpetateClient(); }else { startOpetateClient(); /* *当所设的整数值大于等于1000(ms)时,定位SDK内部使用定时定位模式。 *调用requestLocation( )后,每隔设定的时间,定位SDK就会进行一次定位。 *如果定位SDK根据定位依据发现位置没有发生变化,就不会发起网络请求, *返回上一次定位的结果;如果发现位置改变,就进行网络请求进行定位,得到新的定位结果。 *定时定位时,调用一次requestLocation,会定时监听到定位结果。 */ locationClient.requestLocation(); } } /*********************************/ public double getLatValue(){//纬度 return myBDcoordinate.Latitude; } public double getLongValue(){//经度 return myBDcoordinate.Longitude; } public void desClient(){//当处在定位时Activity销毁时调用 if (locationClient != null && locationClient.isStarted()) { locationClient.stop(); locationClient = null; } } }
下方Key的申请地址为:http://lbsyun.baidu.com/apiconsole/key
在官方的文档中关于官方说的返回的 json, 需要加个[] 再才能解析。于是直接封装了个直接有坐标获取地址的类。
package com.baidulocation; import java.io.BufferedReader; import java.io.InputStreamReader; 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; public class MyLocation { String key = "F9da85afead8b6e9c4738e5e5b79eb97"; public String getAddress(String latValue, String longValue){ String location = getJsonLocation(latValue, longValue); location = getLocation(makeResults(location)); return location; } private String getJsonLocation(String latValue, String longValue){ String urlStr = "http://api.map.baidu.com/geocoder?location=" + latValue + "," + longValue + "&output=json&key=" + key; HttpClient httpClient = new DefaultHttpClient(); String responseData = ""; try{ //向指定的URL发送Http请求 HttpResponse response = httpClient.execute(new HttpGet(urlStr)); //取得服务器返回的响应 HttpEntity entity = response.getEntity(); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(entity.getContent())); String line = ""; while((line = bufferedReader.readLine()) != null){ responseData = responseData + line; } } catch (Exception e) { e.printStackTrace(); } return responseData; } private String makeResults(String result){ String dealResult = result.substring(0, result.indexOf("result") +8) + "[" + result.substring(result.indexOf("result") +8, result.length()-1) + "]}"; return dealResult; } private String getLocation(String str){ JSONArray jsonObjs; String location = ""; try { jsonObjs = new JSONObject(str).getJSONArray("result"); //取出数组中第一个json对象(本示例数组中实际只包含一个元素) JSONObject jsonObj = jsonObjs.getJSONObject(0); //解析得formatted_address值 String address = jsonObj.getString("formatted_address"); String bussiness = jsonObj.getString("business"); location = address + ":" + bussiness; } catch (JSONException e) { // TODO Auto-generated catch block e.printStackTrace(); } //取出数组中第一个json对象(本示例数组中实际只包含一个元素) return location; } }
获取坐标室外会有8秒左右的延迟,所以在获取地理名称时需要等待获取坐标完成后。在主main中,定义一个线程(这里不能再直接建个类来直接获取地名了,需要在Aactivity中实现)
我的工程如下布局,主要看activity中的线程如何实现获取位置的
activity_main.xml布局如下
MainActivity.java中,主要看线程内的怎么处理获取坐标的延迟。
package com.baidulocation; import android.app.Activity; 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.TextView; public class MainActivity extends Activity { private TextView locationInfoTextView = null; private Button startButton = null; MyBaiduLotion myLotion; MyLocation myLocation; String strlocation = ""; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); locationInfoTextView = (TextView) this.findViewById(R.id.tv_loc_info); startButton = (Button) this.findViewById(R.id.btn_start); startButton.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { myLotion = new MyBaiduLotion(MainActivity.this); myLocation = new MyLocation(); myLotion.opetateClient(); new LocationTHread().start(); } }); } class LocationTHread extends Thread{ @Override public void run() { // TODO Auto-generated method stub super.run(); if(myLotion != null) while(!myLotion.getIsFinish()){ try { sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } if(myLotion.myBDcoordinate != null){ strlocation = myLocation.getAddress(myLotion.getLatValue() +"", myLotion.getLongValue() + ""); myHandler.sendEmptyMessage(1); } } } Handler myHandler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); locationInfoTextView.setText(strlocation); } }; @Override protected void onDestroy() { super.onDestroy(); //myLotion.desClient(); } }
在手机上运行能获取坐标(室外获取到地理名称8到10秒。室内时间更长或无法定位)(需链接网咯)
dome地址http://pan.baidu.com/share/link?shareid=1002864869&uk=2065228996 编码utf-8