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