Если вы хотите вызвать один из API в SDK, работающем на базе служб Google Play, таких как Google Sign-in или ML Kit, вам необходимо сначала создать экземпляр клиентского объекта API. Эти объекты автоматически управляют подключением к сервисам Google Play. Когда соединение доступно, каждый клиентский объект API выполняет запросы по порядку. В противном случае клиентский объект ставит запросы в очередь. Если в документации не указано иное, создание клиентских объектов обходится дешево; можно создавать новых клиентов API каждый раз, когда вы хотите вызвать методы API.
В этом руководстве показано, как выполнять вызовы API к любому SDK, работающему на базе сервисов Google Play, в том числе как получить доступ к сервисам, не требующим авторизации, и сервисам, требующим авторизации .
Начать
Для начала добавьте необходимые инструменты и зависимости в проект вашего приложения, как описано в руководстве по настройке сервисов Google Play .
Доступ, когда авторизация не требуется
Чтобы получить доступ к службе, которая не требует авторизации API, получите экземпляр клиентского объекта службы, передав ему либо текущий Context
, либо текущую Activity
. Перед выполнением каких-либо вызовов API пользователям предлагается при необходимости обновить сервисы Google Play.
Например, чтобы получить последнее известное местоположение устройства с помощью поставщика Fused Location Provider для Android, добавьте логику, показанную в следующем фрагменте кода:
Котлин
// Code required for requesting location permissions omitted for brevity. val client = LocationServices.getFusedLocationProviderClient(this) // Get the last known location. In some rare situations, this can be null. client.lastLocation.addOnSuccessListener { location : Location? -> location?.let { // Logic to handle location object. } }
Ява
// Code required for requesting location permissions omitted for brevity. FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this); // Get the last known location. In some rare situations, this can be null. client.getLastLocation() .addOnSuccessListener(this, location -> { if (location != null) { // Logic to handle location object. } });
Доступ, когда требуется авторизация
Чтобы получить доступ к сервису, требующему авторизации пользователя, выполните следующие действия:
- Войдите в систему .
- Запросите разрешение на доступ к областям , которые требуются службе.
- Получите экземпляр клиентского объекта службы, передав ему объект
GoogleSignInAccount
пользователя в дополнение к объектуContext
илиActivity
.
В следующем примере реализовано считывание ежедневных шагов пользователя с помощью API Google Fit. Чтобы просмотреть аналогичную реализацию в контексте полного проекта, просмотрите основное действие приложения BasicHistoryApiKotlin на GitHub.
Котлин
class FitFragment : Fragment() { private val fitnessOptions: FitnessOptions by lazy { FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE) .addDataType(DataType.TYPE_STEP_COUNT_DELTA) .build() } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { fitSignIn() } /* * Checks whether the user is signed in. If so, executes the specified * function. If the user is not signed in, initiates the sign-in flow, * specifying the function to execute after the user signs in. */ private fun fitSignIn() { if (oAuthPermissionsApproved()) { readDailySteps() } else { GoogleSignIn.requestPermissions( this, SIGN_IN_REQUEST_CODE, getGoogleAccount(), fitnessOptions ) } } private fun oAuthPermissionsApproved() = GoogleSignIn.hasPermissions(getGoogleAccount(), fitnessOptions) /* * Gets a Google account for use in creating the fitness client. This is * achieved by either using the last signed-in account, or if necessary, * prompting the user to sign in. It's better to use the * getAccountForExtension() method instead of the getLastSignedInAccount() * method because the latter can return null if there has been no sign in * before. */ private fun getGoogleAccount(): GoogleSignInAccount = GoogleSignIn.getAccountForExtension(requireContext(), fitnessOptions) /* * Handles the callback from the OAuth sign in flow, executing the function * after sign-in is complete. */ override fun onActivityResult( requestCode: Int, resultCode: Int, data: Intent?) { super.onActivityResult(requestCode, resultCode, data) when (resultCode) { RESULT_OK -> { readDailySteps() } else -> { // Handle error. } } } /* * Reads the current daily step total. */ private fun readDailySteps() { Fitness.getHistoryClient(requireContext(), getGoogleAccount()) .readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA) .addOnSuccessListener { dataSet -> val total = when { dataSet.isEmpty -> 0 else -> dataSet.dataPoints.first() .getValue(Field.FIELD_STEPS).asInt() } Log.i(TAG, "Total steps: $total") } .addOnFailureListener { e -> Log.w(TAG, "There was a problem getting the step count.", e) } } companion object { const val SIGN_IN_REQUEST_CODE = 1001 } }
Ява
public class FitFragment extends Fragment { private final FitnessOptions fitnessOptions = FitnessOptions.builder() .addDataType(DataType.TYPE_STEP_COUNT_CUMULATIVE) .addDataType(DataType.TYPE_STEP_COUNT_DELTA) .build(); @Override public void onViewCreated( @NotNull View view, @Nullable Bundle savedInstanceState) { fitSignIn(); } /* * Checks whether the user is signed in. If so, executes the specified * function. If the user is not signed in, initiates the sign-in flow, * specifying the function to execute after the user signs in. */ private void fitSignIn() { if (oAuthPermissionsApproved()) { readDailySteps(); } else { GoogleSignIn.requestPermissions(this, SIGN_IN_REQUEST_CODE, getGoogleAccount(), fitnessOptions); } } private boolean oAuthPermissionsApproved() { return GoogleSignIn.hasPermissions(getGoogleAccount(), fitnessOptions); } /* * Gets a Google account for use in creating the fitness client. This is * achieved by either using the last signed-in account, or if necessary, * prompting the user to sign in. It's better to use the * getAccountForExtension() method instead of the getLastSignedInAccount() * method because the latter can return null if there has been no sign in * before. */ private GoogleSignInAccount getGoogleAccount() { return GoogleSignIn.getAccountForExtension( requireContext(), fitnessOptions); } /* * Handles the callback from the OAuth sign in flow, executing the function * after sign-in is complete. */ @Override public void onActivityResult( int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { readDailySteps(); } else { // Handle error. } } /* * Reads the current daily step total. */ private void readDailySteps() { AtomicInteger total = new AtomicInteger(); Fitness.getHistoryClient(requireContext(), getGoogleAccount()) .readDailyTotal(DataType.TYPE_STEP_COUNT_DELTA) .addOnSuccessListener(dataSet -> { if (!dataSet.isEmpty()) total.set(Integer.parseInt(dataSet.getDataPoints() .get(0).getValue(FIELD_STEPS).toString())); Log.i(TAG, "Total steps: $total"); }) .addOnFailureListener(e -> { Log.w(TAG, "There was a problem getting the step count.", e); }); } private static final int SIGN_IN_REQUEST_CODE = 1001; }
Проверьте доступность API
Прежде чем включить в своем приложении функцию, которая зависит от API сервисов Google Play, включите проверку доступности API на устройстве. Для этого вызовите checkApiAvailability()
.
В следующем фрагменте кода показано, как проверить доступность поставщика объединенного местоположения.
Котлин
fun getLastLocationIfApiAvailable(context: Context?): Task<Location>? { val client = getFusedLocationProviderClient(context) return GoogleApiAvailability.getInstance() .checkApiAvailability(client) .onSuccessTask { _ -> client.lastLocation } .addOnFailureListener { _ -> Log.d(TAG, "Location unavailable.")} }
Ява
public Task<Location> getLastLocationIfApiAvailable(Context context) { FusedLocationProviderClient client = getFusedLocationProviderClient(context); return GoogleApiAvailability.getInstance() .checkApiAvailability(client) .onSuccessTask(unused -> client.getLastLocation()) .addOnFailureListener(e -> Log.d(TAG, "Location unavailable.")); }