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. } }
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. } });
認証が必要な場合のアクセス
ユーザーの承認が必要なサービスにアクセスするには、次の操作を行います。
- ユーザーのログインを行う。
- サービスに必要なスコープへのアクセス権をリクエストします。
- サービスのクライアント オブジェクトのインスタンスを取得し、
Context
オブジェクトまたはActivity
オブジェクトに加えて、ユーザーのGoogleSignInAccount
オブジェクトを渡します。
次の例は、Google Fit API を使用してユーザーの 1 日の歩数を読み取るコードを実装しています。完全なプロジェクトのコンテキストで同様の実装を確認するには、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 } }
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; }
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.")); }