不用百度地图,不用高德地图,使用原生的android api也可以定位并做相应的优化

来源:互联网 发布:网络新技术专题报告 编辑:程序博客网 时间:2024/05/18 00:54

 

之前使用过高德地图和百度地图,大部分都还是很准,不过有时也漂移得很利害,没有别的办法,只能上报给相应的地图公司,等呀等,无聊的时候就研究了一下,android自己的原生api,嘿,原来也可以使用,官网还给了优化的东西,好了,不多说了,上图上代码:

 

 

下面来说说主要关键代码:

private LocationManager locationManager=null;

locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);

上面代码是获取相应的定位管理器。

 

locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER,0, 0,locationListener);

使用定位管理器对象请求定位,第一个参数可以是NETWORK_PROVIDER(网络定位基于基站和wifi),和GPS_PROVIDER(GPS定位基于卫星)当然定位需要获取权限,所以要在AndroidManifest.xml文件声明:

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

或者

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

他们都声明比较保险,但文档说,如果要用到NETWORK_PROVIDERGPS_PROVIDER,可以使用ACCESS_FINE_LOCATION,如果只用到NETWORK_PROVIDER,就声明ACCESS_COARSE_LOCATION就可以了,推荐声明ACCESS_FINE_LOCATION这个吧,省得麻烦,第二个参数是连续定位的间隔时间,这里的单位是毫秒,第三个参数是连续定位的间隔距离,单位是米,最后那个参数是定位结果的回调,我下面会列出来

   LocationListenerlocationListener=newLocationListener() {

       public void onLocationChanged(Location location) {

         // Called whena new location is found by the network location provider.

         //makeUseOfNewLocation(location);

         if(isBetterLocation(location,curLocation)){

            curLocation=location;

            getAddrByhandler(curLocation);

         }

         Log.e(getClass().getName(),"location lat:"+location.getLatitude()+",lon:"+location.getLongitude());

       }

 

       public void onStatusChanged(String provider,intstatus, Bundleextras) {

         Log.e(getClass().getName(),"onStatusChanged");

       }

 

       public void onProviderEnabled(String provider) {

         Log.e(getClass().getName(),"onProviderEnabled");

       }

 

       public void onProviderDisabled(String provider) {

         Log.e(getClass().getName(),"onProviderDisabled");

       }

     };

上面代码定位结果的回调,当定位到结果,我保存前会检查其的新旧合理性,过滤掉一些不太好的结果,代码我会贴到下面:

     protected boolean isBetterLocation(Locationlocation, Location currentBestLocation) {

          if (currentBestLocation == null) {

              return true;

          }

 

          long timeDelta = location.getTime() -currentBestLocation.getTime();

          boolean isSignificantlyNewer = timeDelta> EXPIRE_TIME;

          boolean isSignificantlyOlder = timeDelta< -EXPIRE_TIME;

          boolean isNewer = timeDelta > 0;

 

          if (isSignificantlyNewer) {

              return true;

          } else if (isSignificantlyOlder) {

              return false;

          }

 

          int accuracyDelta = (int)(location.getAccuracy() - currentBestLocation.getAccuracy());

          boolean isLessAccurate = accuracyDelta >0;

          boolean isMoreAccurate = accuracyDelta <0;

          boolean isSignificantlyLessAccurate =accuracyDelta > 200;

 

          boolean isFromSameProvider =isSameProvider(location.getProvider(),

                  currentBestLocation.getProvider());

 

          if (isMoreAccurate) {

              return true;

          } else if (isNewer &&!isLessAccurate) {

              return true;

          } else if (isNewer &&!isSignificantlyLessAccurate && isFromSameProvider) {

              return true;

          }

          return false;

      }

 

上面的代码主要是根据刚刚返回的结果与之前已存的结果在时间新旧,定位的精准度和是否是同种定位来源上作比较,把好的好的留下,定位结果返回的只有经纬度一些信息,其中不包括详细的地址,下面我将介绍通过经纬度来获取相应的详细地址:

private Geocoder geocoder=null;

geocoder = new Geocoder(this,Locale.getDefault());

上面是创建一个地理编码器对象,下面介绍如何使用它:

   privatevoid getAddrByhandler(Location location){

      List<Address>addresses = null;

      try{

           addresses =geocoder.getFromLocation(location.getLatitude(),

                   location.getLongitude(),1);

       } catch (IOException ioException) {

           Log.e(TAG, "服务不可用!", ioException);

       } catch (IllegalArgumentExceptionillegalArgumentException) {

           Log.e(TAG, "无效的经纬度" + ". " +"Latitude = " + location.getLatitude()+", Longitude = " +

                   location.getLongitude(),illegalArgumentException);

       }

       if (addresses == null ||addresses.size()  == 0) {

           Log.e(TAG, "没有找到相关地址!");

       } else {

           Address address = addresses.get(0);

           ArrayList<String>addressFragments = new ArrayList<String>();

           curAddr="";

           for(int i = 0; i <address.getMaxAddressLineIndex(); i++) {

              addressFragments.add(address.getAddressLine(i));

              curAddr=curAddr+address.getAddressLine(i);

           }

          if(!TextUtils.isEmpty(address.getFeatureName())

               &&!addressFragments.isEmpty()

           && !addressFragments.get(addressFragments.size()-1).equals(address.getFeatureName())){

           addressFragments.add(address.getFeatureName());

           curAddr=curAddr+address.getFeatureName();

           }

           updateShowData();

           Log.i(TAG, "详情地址已经找到,地址:"+curAddr);

       }

   }

上面是通过经纬度把相应的详细地址取到,其中我测试的结果address.getMaxAddressLineIndex()是2,但结果却是那个列表却是3,有点坑,所以我补写了一段把address.getFeatureName()加上去了(刚刚没有拿到的),好了,主要代码就已经写完了,有的匆匆忙忙,有很多不足之处,请大家指点,谢谢大家!

原代码的demo已经上传,请移步到如下地址:

http://download.csdn.net/detail/bright789/9388324

参考了资料:

http://developer.android.com/guide/topics/location/strategies.html#BestPerformance

http://developer.android.com/training/location/display-address.html


 

 

0 0
原创粉丝点击