Android 定位2
1.思路分析
- 首先获得当前自己所在位置的经纬度。
- 把我们获得的经纬度转换成我们能看得懂的具体位置信息
2.具体逻辑
- 借助Android本身的LocationManager这个类提供的方法来获取经纬度。
- 毫无疑问,要想使用LocationManager就必须要先获取它的实例,我们可以调用Context的getSystemService()方法获取,即:LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
- 其次我们要选择要使用的位置提供器,只要有GPS和无线网络两种(GPS_PROVIDER和NETWORK_PROVIDER),虽然两者都能实现定位的功能,但是各有自己的特点,GPS定位精度高,但是非常耗电,网络定位精度稍差,但耗电量比较少。具体如:List providers = lm.getProviders(true); 先判断有哪些位置提供器可供使用,最后通过List 容器的contains()方法来判断具体是哪一种
- 之后再获得一个Location这个类的对象,Location这个类是这个demo的核心类,因为它的对象包含了一系列的地理位置信息,如精度、纬度、海拔,有了其之后我们只需要从中取出我们所需要的信息即可。具体代码:Location location = lm.getLastKnownLocation(provider); 纬度即:double latitude = location.getLatitude(); 精度即:double longitude = location.getLongitude.
- 有了经纬度之后,我们只要通过百度GeoCoding API进行反向地理编码,就可以把我们获得的经纬度转换成我们能够看得懂的地理位置信息。本来Geogle 自己就提供了GeoCoding供我们反向地理编码,但现在服务器好像访问不了了,翻墙也没用,所以这里我选择了百度GeoCoding ,但是它们的原理都是一样的,我们向百度的服务器发起一条http请求,并将经纬度作为参数一同传递过去,然后服务器会帮我们把这个经纬值转换成看得懂的位置信息,再将这些信息返回给手机端,我们只需要去解析处理这些数据即可。
- 要想使用百度GeoCoding,首先需要拥有一个百度账号,其次再申请一个key,网址如下:http://lbsyun.baidu.com/apiconsole/key,随后选择创建应用,应用类型:服务端,写IP白名单, 格式如: 202.198.16.3,202.198.0.0/16 填写IP地址或IP前缀网段,英文半角逗号分隔 ,如果没有限制,直接设置0.0.0.0/0即可,因为只有IP白名单内的服务器才能成功发起调用 ,之后提交。之后会出现一个访问应用(ak),例如我的:pPGNKs75nVZPloDFuppTLFO3WXebPgXg
- 之后向服务器发起网络请求,String url = "http://api.map.baidu.com/geocoder/v2/?ak=pPGNKs75nVZPloDFuppTLFO3WXebPgXg&callback=renderReverse&location="+latitude+","+longitude+"&output=json&pois=0";
- 之后解析服务器给我们返回的数据,数据格式自己可以把上述网址在浏览器打开看一下,如果太多不好分析,可以在线解析一下即可。
3.demo:
public class ShowLocation extends AppCompatActivity {
private String provider;//位置提供器 private LocationManager locationManager;//位置服务 private Location location; private Button btn_show; private TextView tv_show; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.location_show); init();//关联控件 locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);//获得位置服务 provider = judgeProvider(locationManager); if (provider != null) {//有位置提供器的情况 //为了压制getLastKnownLocation方法的警告 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { return; } location = locationManager.getLastKnownLocation(provider); if (location != null) { getLocation(location);//得到当前经纬度并开启线程去反向地理编码 } else { tv_show.setText("暂时无法获得当前位置"); } }else{//不存在位置提供器的情况 } } private void init() { btn_show = (Button) findViewById(R.id.btn_show_location); tv_show = (TextView) findViewById(R.id.tv_location_show); } /** * 得到当前经纬度并开启线程去反向地理编码 */ public void getLocation(Location location) { String latitude = location.getLatitude()+""; String longitude = location.getLongitude()+""; String url = "http://api.map.baidu.com/geocoder/v2/?ak=pPGNKs75nVZPloDFuppTLFO3WXebPgXg&callback=renderReverse&location="+latitude+","+longitude+"&output=json&pois=0"; new MyAsyncTask(url).execute(); } /** * 判断是否有可用的内容提供器 * @return 不存在返回null */ private String judgeProvider(LocationManager locationManager) { List<String> prodiverlist = locationManager.getProviders(true); if(prodiverlist.contains(LocationManager.NETWORK_PROVIDER)){ return LocationManager.NETWORK_PROVIDER; }else if(prodiverlist.contains(LocationManager.GPS_PROVIDER)) { return LocationManager.GPS_PROVIDER; }else{ Toast.makeText(ShowLocation.this,"没有可用的位置提供器",Toast.LENGTH_SHORT).show(); } return null; } class MyAsyncTask extends AsyncTask<Void,Void,Void>{ String url = null;//要请求的网址 String str = null;//服务器返回的数据 String address = null; public MyAsyncTask(String url){ this.url = url; } @Override protected Void doInBackground(Void... params) { str = GetHttpConnectionData.getData(url); return null; } @Override protected void onPostExecute(Void aVoid) { try { str = str.replace("renderReverse&&renderReverse",""); str = str.replace("(",""); str = str.replace(")",""); JSONObject jsonObject = new JSONObject(str); JSONObject address = jsonObject.getJSONObject("result"); String city = address.getString("formatted_address"); String district = address.getString("sematic_description"); tv_show.setText("当前位置:"+city+district); } catch (JSONException e) { e.printStackTrace(); } super.onPostExecute(aVoid); } } }
效果图如下: