google map 接入指南——定位

最近项目中有用到了google map,故写下接入google map的心得;由于国内的地图在海外无法使用,所以当你的应用是海外使用,则不得不考虑使用google map。


google map 基本环境搭建

环境搭建可以参考文章 点击这里 或者  官方文档;然后我想说的是google map 申请key的时候,不要加限制,比如包名限制,这样在调试的时候比较方便;第二,在使用地图的时候,要翻墙才行。(总的来说获取key,就是到console.cloud.google.com 然后去设置一下)

定位功能

说到定位,android 可以用sdk中Location 实现,也可以借助play service中的map去实现(这里要手机安装play services app);前者实现没有限制,借助GPS(高精度)和网络(低精度)实现定位,手机系统的GPS设置开关,网络是依靠连接的基站实现的。记得加上权限:<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" /> ,这个权限包含了<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />,所以只需申请第一个就可以了。

第一种方式:Android api:android.Location包下的实现

public Location getGpsInfo(Context context) {
        Location location = null;
        try{
            Criteria criteria = new Criteria();
            criteria.setAccuracy(Criteria.ACCURACY_COARSE);//低精度,如果设置为高精度,依然获取不了location。
            criteria.setAltitudeRequired(false);//不要求海拔
            criteria.setBearingRequired(false);//不要求方位
            criteria.setCostAllowed(true);//允许有花费
            criteria.setPowerRequirement(Criteria.POWER_LOW);//低功耗

            LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
            //从可用的位置提供器中,匹配以上标准的最佳提供器
            if(locationManager != null){
                String locationProvider = locationManager.getBestProvider(criteria, true);
                location = locationManager.getLastKnownLocation(locationProvider);
            }
           
        }catch (SecurityException e){
            e.printStackTrace();
        }

        return location;
    }

或者是两个分开来写:用GPS获取,NetWork获取,当一种获取不到的时候换另一种方式;

/**
     * GPS获取定位方式
     */
    public static Location getGPSLocation(@NonNull Context context) {
        Location location = null;
        LocationManager manager = getLocationManager(context);
        //高版本的权限检查
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {//是否支持GPS定位
            //获取最后的GPS定位信息,如果是第一次打开,一般会拿不到定位信息,一般可以请求监听,在有效的时间范围可以获取定位信息
            location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
        }
        return location;
    }

    /**
     * network获取定位方式
     */
    public static Location getNetWorkLocation(Context context) {
        Location location = null;
        LocationManager manager = getLocationManager(context);
        //高版本的权限检查
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return null;
        }
        if (manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {//是否支持Network定位
            //获取最后的network定位信息
            location = manager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
        }
        return location;
    }

或则

locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
            lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
            if (lastKnownLocation == null){
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
                lastKnownLocation = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }

其实和上面的一样,注意一点,当用户关闭了GPS定位服务,设备联网后(wifi或移动数据)仍然可以定位的,这时候可以进行检查并提醒用户进行打开定位服务,获取更精确的定位:

 Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
 startActivityForResult(intent, GPS_REQUEST_CODE);


private boolean checkGPSIsOpen() {
    boolean isOpen;
    LocationManager locationManager = (LocationManager) this
            .getSystemService(Context.LOCATION_SERVICE);
    isOpen = locationManager.isProviderEnabled(android.location.LocationManager.GPS_PROVIDER);
    return isOpen;
}

第二种方式:用play service中的api获取(也是官方推荐的方式),但有个缺点要安装google 服务,翻墙,但这样很多国产手机都不行,华为,三星都试过,google的pixel手机可以的,不知道什么原因。所以很蛋疼....

一、用FusedLocationProviderClient实现,

实例化
FusedLocationProviderClientmFusedLocationProviderClient =  LocationServices.getFusedLocationProviderClient(this);

 //获取位置  在点击定位按钮或者是onMapReady之后
 Task locationResult = mFusedLocationProviderClient.getLastLocation();

mFusedLocationProviderClient.requestLocationUpdates( mLocationRequest, mLocationCallback,  null);

    private void createLocationRequest(){
        mLocationRequest = LocationRequest.create();
        mLocationRequest.setInterval(10000); //5 seconds
        mLocationRequest.setFastestInterval(5000); //3 seconds
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

 LocationCallback mLocationCallback = new LocationCallback() {
                @Override
                public void onLocationResult(LocationResult locationResult) {
                    if (locationResult == null) {
                        return;
                    }
                    for (Location location : locationResult.getLocations()) {
                        if (location != null) {
                            //TODO: UI updates.
                            Log.d(TAG, "onLocationResult: " + location.toString());
                        }
                    }
                }
            };

二、mGoogleApiClient 实现,官方文档连接 点击 ;

    @Override
    public void onConnected(@Nullable Bundle bundle) {
      
        Location mLastLocation = null;
        try {
            mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        } catch (SecurityException e) {
            e.printStackTrace();
        }


// 在onMapReady中调用连接和创建对象
 mGoogleApiClient.connect();


//在onMapReady中创建mGoogleApiClient  实例对象
 mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

上面的2种方法均是google 推荐的,但是在国产手机基本不行,上面已说过,原因不明。最后还是推荐第一种provider的方式;

地理反编码

在进行到定位后,我们需要把地理编码经纬度换成生活中人们使用的地址,这时候就需要用到地理反编码了,相关参考文档官方文档。注意这是耗时任务,要在子线程进行,否则界面会出现卡顿现象。具体代码展现:

/**
     * 逆地理编码 耗时任务 需要子线程进行
     * @param latitude
     * @param longitude
     * @return
     */
    public String getAddress(double latitude, double longitude) {
        Geocoder geocoder = new Geocoder(mActivity, Locale.getDefault());
        try {
            List<Address> address = geocoder.getFromLocation(latitude, longitude, 1);
            LogUtil.debugLog("onCameraChange", "得到位置当前" + address + "'\n"
                    + "经度:" + String.valueOf(address.get(0).getLongitude()) + "\n"
                    + "纬度:" + String.valueOf(address.get(0).getLatitude()) + "\n"
                    + "纬度:" + "国家:" + address.get(0).getCountryName() + "\n"
                    + "code"  + address.get(0).getCountryCode() +"\n"
                    + "城市:" + address.get(0).getLocality() + "\n"
                    + "名称:" + address.get(0).getAddressLine(1) + "\n"
                    + "街道:" + address.get(0).getAddressLine(0)
            );
            //+ "  " + address.get(0).getLocality() + " " + address.get(0).getCountryName()
            return address.get(0).getAddressLine(0) ;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

这时候,拿到你想要的信息,如果定位可以根据address.get(0).getCountryCode 来判断国家,这样就实现定位功能了。

参考资料:

另外,附上相应的学习文档:

https://developer.android.com/training/location/

https://developers.google.com/maps/documentation/android-sdk/location

https://developers.google.com/maps/documentation/android-sdk/current-place-tutorial

https://developers.google.com/android/reference/com/google/android/gms/maps/GoogleMap 这是相应的google play service里面的服务api

SDK Location的介绍: 

https://developer.android.com/guide/topics/location/strategies

https://developer.android.com/reference/android/location/Location

 

猜你喜欢

转载自blog.csdn.net/sjh_389510506/article/details/84574736