เข้าถึง Google APIs

เมื่อต้องการเรียก API ตัวใดตัวหนึ่งใน SDK ที่ขับเคลื่อนโดยบริการ Google Play เช่น Google Sign-In หรือ ML Kit คุณต้องสร้างอินสแตนซ์ของออบเจ็กต์ไคลเอ็นต์ API ก่อน ออบเจ็กต์เหล่านี้จะจัดการ การเชื่อมต่อกับบริการ Google Play โดยอัตโนมัติ เมื่อมีการเชื่อมต่อ ออบเจ็กต์ของไคลเอ็นต์ API แต่ละรายการจะดำเนินการกับคำขอตามลำดับ ไม่เช่นนั้นออบเจ็กต์ไคลเอ็นต์จะจัดคิวคำขอ หากเอกสารประกอบจะระบุไว้เป็นอย่างอื่น ออบเจ็กต์ไคลเอ็นต์นั้นไม่มีต้นทุนในการสร้าง คุณสามารถสร้างไคลเอ็นต์ API ใหม่ทุกครั้งที่คุณต้องการเรียกใช้เมธอด API ได้

คู่มือนี้แสดงวิธีเรียก API ไปยัง SDK ที่ขับเคลื่อนโดยบริการ Google Play รวมถึงวิธีเข้าถึงบริการที่ไม่กำหนดให้ต้องมีการให้สิทธิ์ และบริการที่ต้องมีการให้สิทธิ์

เริ่มต้นใช้งาน

หากต้องการเริ่มต้นใช้งาน ให้เพิ่มเครื่องมือและทรัพยากร Dependency ที่จำเป็นในโปรเจ็กต์แอป ตามที่อธิบายไว้ในคำแนะนำเกี่ยวกับวิธีตั้งค่าบริการ Google Play

สิทธิ์เข้าถึงเมื่อไม่จำเป็นต้องให้สิทธิ์

หากต้องการเข้าถึงบริการที่ไม่ต้องใช้การให้สิทธิ์ API ให้รับอินสแตนซ์ของออบเจ็กต์ไคลเอ็นต์ของบริการ โดยส่งผ่าน Context ปัจจุบันหรือ Activity ปัจจุบัน ก่อนเรียกใช้ API ระบบจะแจ้งให้ผู้ใช้อัปเกรดบริการ Google Play หากจำเป็น

ตัวอย่างเช่น หากต้องการรับตำแหน่งที่ทราบล่าสุดของอุปกรณ์โดยใช้ Fused Location Provider สำหรับ Android ให้เพิ่มตรรกะที่แสดงในข้อมูลโค้ดต่อไปนี้

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

สิทธิ์เข้าถึงเมื่อต้องมีการให้สิทธิ์

ในการเข้าถึงบริการที่ต้องมีการให้สิทธิ์ผู้ใช้ ให้ทำตามขั้นตอนต่อไปนี้

  1. ให้ผู้ใช้ลงชื่อเข้าใช้
  2. ขอสิทธิ์ในการเข้าถึงขอบเขตที่บริการต้องการ
  3. รับอินสแตนซ์ของออบเจ็กต์ไคลเอ็นต์ของบริการ โดยส่งผ่านออบเจ็กต์ GoogleSignInAccount ของผู้ใช้นอกเหนือจากออบเจ็กต์ Context หรือ Activity

ตัวอย่างต่อไปนี้เป็นการอ่านขั้นตอนรายวันของผู้ใช้โดยใช้ Google Fit API หากต้องการดูการติดตั้งใช้งานที่คล้ายกันในบริบทของโปรเจ็กต์แบบเต็ม โปรดดูกิจกรรมหลักของแอป BasicHistoryApiKotlin ใน GitHub

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

ก่อนเปิดใช้ฟีเจอร์ในแอปที่ต้องใช้ API ของบริการ Google Play ให้ระบุการตรวจสอบความพร้อมใช้งานของ API ในอุปกรณ์ด้วย หากต้องการดำเนินการ โปรดโทรหา checkApiAvailability()

ข้อมูลโค้ดต่อไปนี้แสดงวิธีตรวจสอบความพร้อมใช้งานของผู้ให้บริการ Fused Location

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