Google ログインや ML Kit などの Google Play 開発者サービスを搭載した 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 を使用してユーザーの日次の歩数を読み取っています。完全なプロジェクトのコンテキストで同様の実装を表示するには、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.")); }