定位服务API案例
定位服務API案例
要使用定位服務API,需要確保設備已經下載并安裝了HMS Core服務組件,并將Location Kit的SDK集成到項目中。
指定應用權限
- Android提供了兩種位置權限: ACCESS_COARSE_LOCATION(粗略的位置權限)和ACCESS_FINE_LOCATION(精確的位置權限)。需要在“AndroidManifest.xml”文件中申請權限:
- 在Android Q版本中,如果需要應用程序在后臺執行時也具備持續定位能力,需要在“AndroidManifest.xml”文件中申請ACCESS_BACKGROUND_LOCATION權限:
- 在“AndroidManifest.xml”中添加后,還要在代碼中動態申請一下權限(Android 6.0危險權限要求):
- // Android SDK<=28 所需權限動態申請
- if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.P) {
-
Log.i(TAG, "android sdk <= 28 Q"); -
if (ActivityCompat.checkSelfPermission(this, -
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED -
&& ActivityCompat.checkSelfPermission(this, -
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) { -
String[] strings = -
{Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION}; -
ActivityCompat.requestPermissions(this, strings, 1); -
} - } else {
-
// Android SDK>28 所需權限動態申請,需添加“android.permission.ACCESS_BACKGROUND_LOCATION”權限 -
if (ActivityCompat.checkSelfPermission(this, -
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED -
&& ActivityCompat.checkSelfPermission(this, -
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED -
&& ActivityCompat.checkSelfPermission(this, -
"android.permission.ACCESS_BACKGROUND_LOCATION") != PackageManager.PERMISSION_GRANTED) { -
String[] strings = {android.Manifest.permission.ACCESS_FINE_LOCATION, -
android.Manifest.permission.ACCESS_COARSE_LOCATION, -
"android.permission.ACCESS_BACKGROUND_LOCATION"}; -
ActivityCompat.requestPermissions(this, strings, 2); -
} - }
創建定位服務客戶端
在項目中使用到定位服務的Activity中的onCreate()方法中創建一個FusedLocationProviderClient實例,通過該實例調用定位相關接口。 - // 定位交互接入對象
- private FusedLocationProviderClient fusedLocationProviderClient;
- // 定位請求信息對象
- private LocationRequest mLocationRequest;
- protected void onCreate(Bundle savedInstanceState) {
-
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this); - }
說明
當傳入參數為非Activity類型時,如果使用FusedLocationProviderClient實例調用定位服務接口發生異常,就不會彈出UI交互界面提示用戶處理,只會返回錯誤碼。例如:當HMS Core不符合定位服務的版本要求時,便會返回錯誤碼907135003,此時需要手動升級HMS Core。如果需要拉起升級引導界面,建議傳入Activity類型參數替代Context類型,創建FusedLocationProviderClient實例。
檢查設備定位設置
設備的相關定位設置會影響定位服務的定位結果,例如位置開關選項處于關閉狀態時,將無法獲取到位置信息。因此,建議在持續獲取位置信息之前,先檢查設備設置是否滿足定位條件。定位服務提供了檢查設備定位相關設置的能力,通過LocationServices的getSettingsClient(Activity activity)獲取SettingsClient實例,然后調用checkLocationSettings(LocationSettingsRequest locationSettingsRequest)接口獲取定位設置結果,當設置不滿足定位條件時,可以調用startResolutionForResult接口用于彈框提示用戶打開對應的權限(HMS Core 定位權限必須打開,Android Q版本必須選擇“始終允許”)。 - 調用getSettingsClient()接口獲取SettingsClient實例。
- SettingsClient settingsClient = LocationServices.getSettingsClient(this);
- 調用checkLocationSettings()檢查設備設置。
- LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
- mLocationRequest = new LocationRequest();
- builder.addLocationRequest(mLocationRequest);
- LocationSettingsRequest locationSettingsRequest = builder.build();
- // 檢查設備定位設置
- settingsClient.checkLocationSettings(locationSettingsRequest)
-
// 檢查設備定位設置接口成功監聽回調 -
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() { -
@Override -
public void onSuccess(LocationSettingsResponse locationSettingsResponse) { -
// 設置滿足定位條件,再發起位置請求 -
fusedLocationProviderClient -
.requestLocationUpdates(mLocationRequest, mLocationCallback,Looper.getMainLooper()) -
// 請求位置更新接口成功監聽回調 -
.addOnSuccessListener(new OnSuccessListener<Void>() { -
@Override -
public void onSuccess(Void aVoid) { -
// ... -
} -
}); -
} -
}) -
// 檢查設備定位設置接口失敗監聽回調 -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
// 設置不滿足定位條件 -
int statusCode = ((ApiException) e).getStatusCode(); -
switch (statusCode) { -
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED: -
try { -
ResolvableApiException rae = (ResolvableApiException) e; -
// 調用startResolutionForResult可以彈窗提示用戶打開相應權限 -
rae.startResolutionForResult(MainActivity.this, 0); -
} catch (IntentSender.SendIntentException sie) { -
// … -
} -
break; -
} -
} -
});
持續獲取位置信息
如果希望應用可以持續獲取設備位置,可以使用定位服務提供的requestLocationUpdates()接口。該接口根據入參形式的不同,將以兩種不同的形式將位置信息返回。一種是通過調用已經定義的LocationCallback類中onLocationResult()回調方法返回一個包含位置信息的LocationResult對象,另一種是將位置信息置于PendingIntent擴展信息中返回。
當應用程序不再需要接收位置更新時,應當停止位置更新,以便于降低功耗。要停止位置更新,可以調用removeLocationUpdates(),傳入與requestLocationUpdates()接口相對應的LocationCallback或PendingIntent對象。這里以回調方式作為樣例,代碼如下。詳細的參數說明請參見LocationService接口說明。
- 設置持續定位請求參數。
- LocationRequest mLocationRequest = new LocationRequest();
- // 設置位置更新的間隔(單位為毫秒)
- mLocationRequest.setInterval(10000);
- // 設置定位類型
- mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
- 定義位置更新回調。
- LocationCallback mLocationCallback;
- mLocationCallback = new LocationCallback() {
-
@Override -
public void onLocationResult(LocationResult locationResult) { -
if (locationResult != null) { -
// 處理位置回調結果 -
} -
} - };
- 調用requestLocationUpdates()進行持續定位。
- fusedLocationProviderClient
-
.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.getMainLooper()) -
.addOnSuccessListener(new OnSuccessListener<Void>() { -
@Override -
public void onSuccess(Void aVoid) { -
// 接口調用成功的處理 -
} -
}) -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
// 接口調用失敗的處理 -
} -
});
說明
如果接口調用成功,獲取位置信息失敗,請參見接口調用成功,獲取不到位置信息。
4. 調用removeLocationUpdates()停止位置更新。
- // 注意:停止位置更新時,mLocationCallback必須與requestLocationUpdates方法中的LocationCallback參數為同一對象。
- fusedLocationProviderClient.removeLocationUpdates(mLocationCallback)
-
// 停止位置更新成功監聽回調 -
.addOnSuccessListener(new OnSuccessListener<Void>() { -
@Override -
public void onSuccess(Void aVoid) { -
//... -
} -
}) -
// 停止位置更新失敗監聽回調 -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
// ... -
} -
});
獲取最后的已知位置
應用可以調用getLastLocation()方法獲取設備最后的已知位置,大多情況下,該位置即為設備的當前位置。代碼樣例如下:
- // 獲取最后的已知位置
- Task task = fusedLocationProviderClient.getLastLocation()
-
// 獲取最后的已知位置成功監聽回調 -
.addOnSuccessListener(new OnSuccessListener<Location>() { -
@Override -
public void onSuccess(Location location) { -
if (location == null) { -
return; -
} -
// 成功時Location對象處理邏輯 -
// ... -
} -
}) -
// 獲取最后的已知位置失敗監聽回調 -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
// ... -
} -
});
說明
getLastLocation()方法是從系統緩存中獲取位置信息的。如果獲取的位置信息為null,則可能是系統緩存已經被清除;此時先調用requestLocationUpdates()方法獲取位置信息以刷新緩存,再調用getLastLocation()方法即可以獲取到位置信息。
使用模擬位置信息功能
具體操作步驟:打開“設置 > 系統和更新 > 開發人員選項 > 選擇模擬位置信息應用 > 選擇要模擬位置信息應用”(如果沒有發現“開發人員選項”,請執行如下操作:“設置 > 關于手機 > 版本號”,連續點擊“版本號”7次,“開發人員選項”會出現在“系統與更新”頁面,再重復上述操作),代碼開發步驟如下:
- 在AndroidManifest.xml文件中配置模擬定位權限。
- <uses-permission
- android:name=“android.permission.ACCESS_MOCK_LOCATION”
- tools:ignore=“MockLocation,ProtectedPermissions” />
- 設置mock模式,調用setMockMode(boolean isMockMode)。
- // 設置mock模式,參數傳入ture:模擬模式;false:正常狀態
- boolean mockFlag = true;
- fusedLocationProviderClient.setMockMode(mockFlag)
-
.addOnSuccessListener(new OnSuccessListener<Void>() { -
@Override -
public void onSuccess(Void aVoid) { -
Log.i(TAG, "setMockMode onSuccess"); -
} -
}) -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
Log.i(TAG, "setMockMode onFailure:" + e.getMessage()); -
} -
}); - 設置模擬位置信息,調用setMockLocation(Location mockLocation)。
- // 設置模擬位置信息
- final Location mockLocation = new Location(LocationManager.GPS_PROVIDER);
- mockLocation.setLongitude(118.76);
- mockLocation.setLatitude(31.98);
- fusedLocationProviderClient.setMockLocation(mockLocation)
-
// 設置模擬位置信息成功監聽回調 -
.addOnSuccessListener(new OnSuccessListener<Void>() { -
@Override -
public void onSuccess(Void aVoid) { -
Log.i(TAG, "setMockLocation onSuccess"); -
} -
}) -
// 設置模擬位置信息失敗監聽回調 -
.addOnFailureListener(new OnFailureListener() { -
@Override -
public void onFailure(Exception e) { -
Log.i(TAG, "setMockLocation onFailure:" + e.getMessage()); -
} -
});
總結
- 上一篇: HiCar SDK概述
- 下一篇: 活动识别API服务开发