เข้าถึง Google API

เมื่อต้องการเรียกหนึ่งใน 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

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