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