最近项目中有用到了google map,故写下接入google map的心得;由于国内的地图在海外无法使用,所以当你的应用是海外使用,则不得不考虑使用google map。
环境搭建可以参考文章 点击这里 或者 官方文档;然后我想说的是google map 申请key的时候,不要加限制,比如包名限制,这样在调试的时候比较方便;第二,在使用地图的时候,要才行。(总的来说获取key,就是到console.cloud.google.com 然后去设置一下)
map 的key 不用包名绑定,只有平台和签名文件的签名限制,也和google-service.json 文件没有关系。对于添加限制可以按照官方文档,进入到如下界面:
说到定位,android 可以用sdk中Location 实现,也可以借助play service中的map去实现(这里要手机安装play services app);前者实现没有限制,借助GPS(高精度)和网络(低精度)实现定位,手机系统的GPS设置开关,网络是依靠连接的基站实现的。记得加上权限:
第一种方式: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 = 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