Google API 액세스

Google Play 서비스(예: Google 로그인 또는 ML Kit)를 기반으로 하는 SDK의 API 중 하나를 호출하려면 먼저 API 클라이언트 객체의 인스턴스를 만들어야 합니다. 이러한 객체는 Google Play 서비스에 대한 연결을 자동으로 관리합니다. 연결을 사용할 수 있으면 각 API 클라이언트 객체가 요청을 순서대로 실행합니다. 그렇지 않으면 클라이언트 객체가 요청을 큐에 추가합니다. 문서에 달리 명시되지 않는 한 클라이언트 객체는 생성하는 데 비용이 들지 않습니다. API 메서드를 호출할 때마다 새 API 클라이언트를 만들 수 있습니다.

이 가이드에서는 승인이 필요하지 않은 서비스와 승인이 필요한 서비스에 액세스하는 방법을 비롯하여 Google Play 서비스에서 제공하는 SDK에 API를 호출하는 방법을 보여줍니다.

시작하기

시작하려면 Google Play 서비스를 설정하는 방법에 관한 가이드에 설명된 대로 앱 프로젝트에 필요한 도구와 종속 항목을 추가합니다.

승인이 필요하지 않은 경우 액세스

API 승인이 필요하지 않은 서비스에 액세스하려면 서비스의 클라이언트 객체 인스턴스를 가져와서 현재 Context 또는 현재 Activity를 전달합니다. API 호출이 실행되기 전에 필요한 경우 사용자에게 Google Play 서비스를 업그레이드하라는 메시지가 표시됩니다.

예를 들어 Android용 Fused Location Provider를 사용하여 마지막으로 알려진 기기 위치를 가져오려면 다음 코드 스니펫에 표시된 로직을 추가합니다.

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

자바

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

승인이 필요한 액세스

사용자 승인이 필요한 서비스에 액세스하려면 다음 단계를 완료하세요.

  1. 사용자를 로그인합니다.
  2. 서비스에 필요한 범위에 액세스할 권한을 요청합니다.
  3. 서비스의 클라이언트 객체 인스턴스를 가져와 Context 또는 Activity 객체 외에도 사용자의 GoogleSignInAccount 객체를 전달합니다.

다음 예에서는 Google Fit API를 사용하여 사용자의 일일 걸음 수를 읽는 기능을 구현합니다. 전체 프로젝트 컨텍스트에서 유사한 구현을 보려면 GitHub에서 BasicHistoryApiKotlin 앱의 기본 활동을 확인하세요.

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

자바

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 사용 가능 여부 확인

앱에서 Google Play 서비스 API에 종속되는 기능을 사용 설정하기 전에 기기에서 API의 가용성을 확인하는 검사를 포함하세요. 이렇게 하려면 checkApiAvailability()를 호출합니다.

다음 코드 스니펫은 융합 위치 제공업체의 가용성을 확인하는 방법을 보여줍니다.

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