`

googleMap(其二)获取手机所在地的经纬度

 
阅读更多
上文说到获取手机所在地的经纬度,那么有几种方式呢?通过GPS,network.而地位API中提供了LocationManager,以及Location。其中LocationManager用来获得位置服务,Location用来获取位置。具体代码如下:


private GeoPoint getGeoPoint(){
        LocationManager locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
        Location location=locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        return new GeoPoint((int)location.getLatitude(),(int)location.getLongitude());
    }


从这里我们可以知道一个经纬度对象GeoPoint,它接受2个整形的经纬度值。在这里我们是使用GPS获取当前经纬度,如果用network呢?那么久换LocationManager.NETWORK_PROVIDER

当然,我们可能要考虑到更多的情况,比如说GPS模式是关闭的,那么如何启动它?很简单,我们只要判断是否启用了GPS,如果没有则跳到Settings中进行启用。代码如下:


boolean flag=locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        if(!flag){
            Intent intent=new Intent(Settings.ACTION_SECURITY_SETTINGS);
        }


以上是获得当前手机所在地的经纬度。

当然当我们行走时候,位置是不断变化的,我们怎么才能够检测到位置的变化,并显示出来呢?

我们这里需要用到位置监听器LocationListener,当然,我们会查询出最佳的数据,因此需要设置Criteria

代码如下:



//获得最佳服务
    private Criteria getCriteria(){
        Criteria criteria=new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_FINE);// 高精度
        criteria.setAltitudeRequired(false);//海拔
        criteria.setBearingRequired(false);//地轴线
        criteria.setCostAllowed(false); //付费
        criteria.setPowerRequirement(Criteria.POWER_LOW);//电量低
        return criteria;
    }


实例化LocationListener,在不同的回调函数中处理,这里我们只处理位置变化回调函数onLocationChanged,具体代码如下:



//位置监听器,监听位置的改变
    LocationListener locationListener=new LocationListener(){
        //当位置变化时候激发
        @Override
        public void onLocationChanged(Location location) {
            //根据位置获取经纬度对象
            getGeoPoint(location);
        }
        //GPS,或者network可时候激发
        @Override
        public void onProviderDisabled(String provider) {
            
            
        }
        //GPS,或者network不可时候激发
        @Override
        public void onProviderEnabled(String provider) {
            
            
        }
        //GPS,或者network状态改变时候激发
        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            switch(status){
            case LocationProvider.OUT_OF_SERVICE:
                 //不在服务
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                //暂不可用
                break;
            case LocationProvider.AVAILABLE :
                 //可用
                break;
                 
            }
            
        }
    };


既然定义好了监听处理类后,我们就可以在LocationManager中注册这个监听:



private void registeListener(){
        LocationManager locationManager=(LocationManager)getSystemService(Context.LOCATION_SERVICE);
        if(!locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
            //如果GPS不可用,则跳转到Settings中进行设置
            Intent intent=new Intent(Settings.ACTION_SECURITY_SETTINGS);
            startActivity(intent);
        }
        //查询最设和的服务信息    
        String provider=locationManager.getBestProvider(getCriteria(), true);
        //设置位置监听器,间隔5秒改变一次
        locationManager.requestLocationUpdates(provider, 5000, 0, locationListener);
    }



这里locationManager.requestLocationUpdates(provider, 5000, 0, locationListener); 第一个参数是位置提供器,第2个是多少毫米请求一次,第3个是移动最小距离(米),第4个就是监听类了。

当然,我们可以取消位置监听:locationManager.removeUpdates(locationListener);

既然可以动态获取手机经纬度,那么怎么把经纬度解析成我们实际地址呢?
我们可以采用Geocoder类的getFromLocation方法解析位置信息,然后返回一系列地址信息List<Address>,再根据最符合的Address获取国家、州县、街道等等地址信息,代码如下:



//根据经纬度获得地址(国家,州县,街道等等)
    private void showAddressFromGeoPoint(GeoPoint gPoint) throws IOException{
        StringBuilder sb=new StringBuilder();
        Geocoder geoCode=new Geocoder(this,Locale.getDefault());
        List<Address> addresses=geoCode.getFromLocation(gPoint.getLatitudeE6()/1E6, gPoint.getLongitudeE6()/1E6, 1);
        if(addresses.size()>0){
            Address address=addresses.get(0);
            for(int i=0;i<address.getMaxAddressLineIndex();i++){
                sb.append(address.getAddressLine(i)+"\n");
            }
            sb.append(address.getLocality()+"\n");
            sb.append(address.getPostalCode()+"\n");
            sb.append(address.getCountryName()+"\n");
            
            Toast.makeText(this, sb.toString(), Toast.LENGTH_LONG).show();
        }
    }



以上是把经纬度、位置等信息解析成地址,那么反过来,我们是不是可以根据地址名称获得经纬度位置,然后在地图上标识起来呢?当然可以,现在就来根据实际地址获取经纬度吧:

跟上述方式一样,调用Geocoder的getFromLocationName方法,获得地址列表,然后取出最佳的地址,再获取经纬度,代码如下:



//根据地址获取经纬度信息GeoPoint
    private GeoPoint getGeoPointFromAddressName(String locationName) throws IOException{
        Geocoder geoCode=new Geocoder(this,Locale.getDefault());
        List<Address> addresses=geoCode.getFromLocationName(locationName, 1);
        if(addresses!=null){
         double lati=addresses.get(0).getLatitude();
         double longi=addresses.get(0).getLongitude();
            return new GeoPoint((int)(lati*1E6),(int)(longi*1E6));
        }
            return null;
    }



如果,我想知道,我是否逼近了某个区域范围,然后手机就发出通知,这个怎么办?

逼近某个范围,就是有一个经纬度对象GeoPoint 固定,另外一个GeoPoint 不断靠近变化,要测量这2个点的距离,可以使用Location的distanceBetween方法。具体代码如下:


//计算2点距离,经纬度
    private float getDistance(GeoPoint startPoint,GeoPoint endPoint){
        float []results=new float[3];
        Location.distanceBetween(startPoint.getLatitudeE6()/1E6, startPoint.getLongitudeE6()/1E6, 
                endPoint.getLatitudeE6()/1E6, endPoint.getLongitudeE6()/1E6,
                results);
            return results[0]; 
    }



上述代码就实现了2个点距离检测,然后我们可以根据判断2点距离是否在某一距离范围内,代码如下:


//判断是否在多少米范围内
    private boolean isNearAround(GeoPoint startPoint,GeoPoint endPoint,float meter){
         float distance=getDistance(startPoint,endPoint);
         return (meter-distance>0)?true:false;
    }


以上就是逼近某地范围的方法,但是你可能会想,我们的位置如果是变化的呢?所以你就必须在位置变化时候更新GeoPoint ,位置变化监听器LocationListener有个onLocationChanged方法回调每次变化的位置,当然你看了以上说明后自然知道怎么调用了。

再来几个开发中常会遇到问题吧。

我们怎么获取手机屏幕上一点对应的经纬度?(手机屏幕点转化为经纬度),或者某一经纬度怎么对应手机屏幕上一点的位置?

我们可以使用Projection类的fromPixels,以及toPixels方法分别转化为屏幕一点,以及屏幕一点的经纬度,当然获取 Projection是需要我们地图对象的getProjection方法,具体代码如下:



//屏幕上一点获得经纬度
    private GeoPoint FormScreenPoint(Point screen){
        Projection projection=mapView.getProjection();
        GeoPoint gpoint=projection.fromPixels(screen.x, screen.y);
        return gpoint;
    }
    
    //根据经纬度定位到手机屏幕上一点
    private Point FromGeoPoint(GeoPoint gPoint){
        Point out =new Point();
        Projection projection=mapView.getProjection();
        projection.toPixels(gPoint, out);
        return out;
    }



有了前面几项基础知识后,我们可以更深入发展了,就想之前提及的,在手机屏幕上绘制一个图层,标记一张图片或者一些信息,然后我们点击这个标记,他会提示一些信息。
这里主要就是如何解决标记到地图的问题了
这里使用到一个类Overlay,这个可作为地图上的标记,因此我们首先基础这个标记,然后绘制自己的图钉(图片),再重写它的onTouchEvent方法,以便点击这个图层时候提示信息,当然我们可以传递经纬度对象GeoPoint进去,以便在地图中显示:



//自定义图层标记
    private class MyOverLay extends Overlay{
        GeoPoint in=null;
        public MyOverLay(GeoPoint in){
            this.in=in;
        }
        //在自定义绘制图层的方法中添加图钉(一张图片)
        @Override
        public boolean draw(Canvas canvas,MapView mapView,
                    boolean shadow,long when){
            //经纬度转化屏幕一点
            Point out=new Point();
            Projection proj=mapView.getProjection();
            proj.toPixels(in, out);
            
            //获得图片并调用canvas绘制图片,其中第3个参数为Y轴坐标具体看图
            Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
            canvas.drawBitmap(bitmap, out.x, out.y-50, null);
            return true;
        }
        
        @Override
        public boolean onTouchEvent(MotionEvent e,MapView mapView){
             if(e.getAction()==MotionEvent.ACTION_UP){
                 //根据屏幕一点获取经纬度
                 GeoPoint gpoint=mapView.getProjection().fromPixels((int)e.getX(), (int)e.getY());
                 //然后显示经纬度
                 String msg="您点击的地方经度为:"+gpoint.getLatitudeE6()/1E6+",纬度为:"+gpoint.getLongitudeE6()/1E6;
                 Toast.makeText(getApplication(), msg, Toast.LENGTH_LONG).show();
                 
                 //当然,您可以使用传递过来的对象,比如GeoPoint获取一些其他自定义对象信息,比如说什么地方,什么公司以及风景区等
                 
             }
            return true;
        } 
    }



我们可以看到我们绘制了一个图形,以及重写了触摸的方法,在触摸时候提示信息,接下来,我们必须把它“钉”在地图上进行显示,当然了,默认MapView都自动加载了图层,我们只需调用
List<Overlay> overlays=mapView.getOverlays(); 方法获得图层列表,然后把我们自定义的图层添加进去即可,代码如下:



 //在屏幕上打上标记(图钉)
    private void putOverLay(GeoPoint in){
//        /定义标记
        MyOverLay myOverLay=new MyOverLay(in);
        List<Overlay> overlays=mapView.getOverlays();
        overlays.clear();
        overlays.add(myOverLay);
        mapView.invalidate();
    }


这里解析一个问题,我们说是canvas.drawBitmap(bitmap, out.x, out.y-50, null);中第3个参数是要减去50呢?你看看这幅图就明白了,需要减去高才可以使图钉的指针正好对应屏幕的某点。



完成。假如你完全理解上面一系列东西,那么LBS已经有了基础。
分享到:
评论

相关推荐

    android 获取经纬度

    Location 在Android 开发中还是经常用到的,比如 通过经纬度获取天气,根据Location 获取所在地区详细Address (比如Google Map 开发).等。而在Android 中通过LocationManager 来获取Location .通常获取Location 有...

    android获取经纬度且解析位置

    android获取经纬度且解析位置,该demo能够通过network和gps获取当前所在的经纬信息,并能实时的更新,并且能通过经纬度信息上传到googleMap上获取相对应的地址信息,返回的事json字符串,最后解析成一般的地址信息。...

    Google Android SDK开发范例大全(第3版) 4/5

    《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...

    Google Android SDK开发范例大全(第3版) 3/5

    《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...

    Google Android SDK开发范例大全(第3版) 5/5

    《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...

    Android开发之Location用法实例分析

    Location 在Android 开发中还是经常用到的,如通过经纬度获取天气,根据Location 获取所在地区详细Address (比如Google Map 开发)等。而在Android 中通过LocationManager来获取Location .通常获取Location 有GPS ...

    Google Android SDK开发范例大全(第3版) 1/5

    《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...

    Google Android SDK开发范例大全(第3版)part2

     《Google Android SDK开发范例大全(第3版)》在上一版的基础上,以Android手机应用程序开发(采用Android SDK 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序...

    《Google Android SDK开发范例大全(第3版)》.pdf

     《google android sdk开发范例大全(第3版)》在上一版的基础上,以android手机应用程序开发(采用android sdk 2.3.3)为主题,超过200多个范例全面且深度地整合了手机、网络及服务等多个开发领域,为读者提高程序设计...

Global site tag (gtag.js) - Google Analytics