Dostęp do interfejsów API Google

Jeśli chcesz wywołać jeden z interfejsów API w pakiecie SDK opartym na Usługach Google Play, np. Google Sign-In lub ML Kit, musisz najpierw utworzyć instancję obiektu klienckiego API. Obiekty te automatycznie zarządzają połączeniem z Usługami Google Play. Gdy połączenie jest dostępne, każdy obiekt klienta API wykonuje żądania w określonej kolejności. W przeciwnym razie obiekt klienta umieszcza żądania w kolejce. O ile dokumentacja nie wskazuje inaczej, obiekty klienta są tanie. Można tworzyć nowe klienty interfejsu API za każdym razem, gdy chcesz wywoływać metody interfejsu API.

Z tego przewodnika dowiesz się, jak wywoływać interfejsy API w pakietach SDK obsługiwanych przez Usługi Google Play, w tym jak uzyskiwać dostęp do usług, które nie wymagają autoryzacji, i tych, które wymagają autoryzacji.

Rozpocznij

Zacznij od dodania niezbędnych narzędzi i zależności w projekcie aplikacji zgodnie z opisem w przewodniku konfigurowania usług Google Play.

Dostęp, gdy autoryzacja nie jest wymagana

Aby uzyskać dostęp do usługi, która nie wymaga autoryzacji interfejsu API, pobierz instancję obiektu klienckiego usługi, przekazując do niej bieżący Context lub bieżący obiekt Activity. Przed wykonaniem jakichkolwiek wywołań interfejsu API użytkownicy są w razie potrzeby proszeni o uaktualnienie Usług Google Play.

Jeśli np. chcesz określić ostatnią znaną lokalizację urządzenia na Androidzie, dodaj funkcję przedstawioną w tym fragmencie kodu:

Kotlin

// 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.
    }
}

Java

// 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.
            }
        });

Dostęp, gdy wymagana jest autoryzacja

Aby uzyskać dostęp do usługi, która wymaga autoryzacji użytkownika, wykonaj te czynności:

  1. Zaloguj użytkownika.
  2. Poproś o dostęp do zakresów, których wymaga usługa.
  3. Pobranie instancji obiektu klienckiego usługi, przekazując do niego obiekt GoogleSignInAccount użytkownika oprócz obiektu Context lub Activity.

W poniższym przykładzie pokazano, jak odczytywać codzienne kroki użytkownika za pomocą interfejsu Google Fit API. Aby wyświetlić podobną implementację w kontekście całego projektu, wyświetl główną aktywność aplikacji BasicHistoryApiKotlin na GitHubie.

Kotlin

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
    }
}

Java

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;
}

Sprawdź dostępność interfejsu API

Zanim włączysz w aplikacji funkcję zależną od interfejsu API Usług Google Play, sprawdź jego dostępność na urządzeniu. Aby to zrobić, wywołaj checkApiAvailability().

Poniższy fragment kodu pokazuje, jak sprawdzić dostępność dostawcy uśrednionej lokalizacji.

Kotlin

fun getLastLocationIfApiAvailable(context: Context?): Task<Location>? {
    val client = getFusedLocationProviderClient(context)
    return GoogleApiAvailability.getInstance()
        .checkApiAvailability(client)
        .onSuccessTask { _ -> client.lastLocation }
        .addOnFailureListener { _ -> Log.d(TAG, "Location unavailable.")}
}

Java

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."));
}