0Pricing
Android Academy · บทเรียน

การรับตำแหน่งของผู้ใช้

พื้นฐานผู้ให้บริการตำแหน่งแบบรวม

การรับตำแหน่งของผู้ใช้ เป็นบทเรียน Android Academy ฟรีบน CoddyKit นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Android Academy และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

ผู้ใช้อยู่ที่ไหน

แอปส่วนใหญ่ที่ใช้ข้อมูลตำแหน่งเริ่มต้นด้วยคำถามเดียว: ตอนนี้อุปกรณ์อยู่ที่ไหน Android ตอบคำถามนี้ผ่าน ผู้ให้บริการตำแหน่งแบบผสาน ซึ่งเป็นส่วนหนึ่งของบริการ Google Play

ในบทเรียนนี้ คุณจะเพิ่มการพึ่งพา ขออ่านตำแหน่งหนึ่งครั้ง รับฟังการอัปเดตอย่างต่อเนื่อง และนำผลลัพธ์มาแสดงใน Compose

เหตุผลที่ใช้ผู้ให้บริการแบบผสาน

Android มีแหล่งข้อมูลตำแหน่งหลายแหล่ง ได้แก่ GPS, Wi‑Fi และเสาสัญญาณโทรศัพท์ ผู้ให้บริการตำแหน่งแบบผสานจะรวมข้อมูลเหล่านี้อย่างชาญฉลาด เพื่อให้ได้ตำแหน่งที่ดีที่สุดโดยใช้แบตเตอรี่น้อยที่สุด

ปัจจุบันแทบไม่จำเป็นต้องใช้ LocationManager โดยตรงอีกแล้ว เพราะไคลเอ็นต์แบบผสานใช้งานง่ายกว่าและฉลาดกว่า

// build.gradle.kts (module)
dependencies {
    implementation("com.google.android.gms:play-services-location:21.3.0")
}

การประกาศสิทธิ์

ตำแหน่งเป็นทรัพยากรที่มีความละเอียดอ่อน ให้ประกาศสิทธิ์ใน AndroidManifest.xml ใช้ ACCESS_FINE_LOCATION สำหรับตำแหน่งที่แม่นยำ หรือ ACCESS_COARSE_LOCATION สำหรับตำแหน่งโดยประมาณ

การประกาศเป็นเพียงขั้นตอนแรกเท่านั้น คุณต้องขอสิทธิ์ขณะทำงานด้วย ซึ่งจะกล่าวถึงในบทเรียนถัดไป

<!-- AndroidManifest.xml -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />

การสร้างไคลเอ็นต์แบบผสาน

รับ FusedLocationProviderClient จาก LocationServices ใน Compose ให้รับบริบทด้วย LocalContext.current และจดจำไคลเอ็นต์ไว้ เพื่อไม่ให้มีการสร้างใหม่ทุกครั้งที่จัดองค์ประกอบใหม่

import com.google.android.gms.location.LocationServices

@Composable
fun rememberFusedClient() = run {
    val context = LocalContext.current
    remember {
        LocationServices.getFusedLocationProviderClient(context)
    }
}

การรับตำแหน่งล่าสุดที่ทราบ

คำตอบที่เร็วที่สุดคือ lastLocation ซึ่งเป็นตำแหน่งล่าสุดที่ระบบเก็บไว้ในแคชแล้ว ผลลัพธ์ที่ได้คือ Task ดังนั้นให้ผูกตัวรับฟังความสำเร็จไว้

ค่านี้อาจเป็น null หากช่วงที่ผ่านมาไม่มีแอปใดขอตำแหน่ง ดังนั้นให้ตรวจสอบค่า null ทุกครั้ง

@SuppressLint("MissingPermission")
fun fetchLastLocation(
    client: FusedLocationProviderClient,
    onResult: (Location?) -> Unit
) {
    client.lastLocation
        .addOnSuccessListener { location -> onResult(location) }
        .addOnFailureListener { onResult(null) }
}

รอ Task ด้วยโครูทีน

การเรียกกลับจะซ้อนกันอย่างรวดเร็ว ไลบรารี kotlinx-coroutines-play-services เพิ่ม .await() เพื่อให้คุณอ่านตำแหน่งด้วยโค้ดแบบพักการทำงานที่อ่านง่าย

import kotlinx.coroutines.tasks.await

@SuppressLint("MissingPermission")
suspend fun currentLastLocation(
    client: FusedLocationProviderClient
): Location? {
    return client.lastLocation.await()
}

การขอตำแหน่งใหม่

lastLocation อาจไม่ใช่ตำแหน่งปัจจุบัน หากต้องการตำแหน่งที่อัปเดตล่าสุด ให้เรียก getCurrentLocation พร้อมระบุระดับความสำคัญ PRIORITY_HIGH_ACCURACY ใช้ GPS ส่วน PRIORITY_BALANCED_POWER_ACCURACY ช่วยประหยัดแบตเตอรี่

import com.google.android.gms.location.Priority
import com.google.android.gms.location.CurrentLocationRequest

@SuppressLint("MissingPermission")
suspend fun freshLocation(
    client: FusedLocationProviderClient
): Location? {
    val request = CurrentLocationRequest.Builder()
        .setPriority(Priority.PRIORITY_HIGH_ACCURACY)
        .build()
    return client.getCurrentLocation(request, null).await()
}

การอัปเดตตำแหน่งอย่างต่อเนื่อง

สำหรับการนำทางหรือการติดตาม คุณต้องใช้ กระแสข้อมูล ของการอัปเดต ให้สร้าง LocationRequest พร้อมช่วงเวลา แล้วลงทะเบียน LocationCallback ผ่าน requestLocationUpdates

หยุดการอัปเดตทุกครั้งเมื่อใช้งานเสร็จ เพื่อประหยัดแบตเตอรี่

import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationResult
import com.google.android.gms.location.LocationCallback

val request = LocationRequest.Builder(
    Priority.PRIORITY_HIGH_ACCURACY,
    5000L // 5 seconds
).build()

val callback = object : LocationCallback() {
    override fun onLocationResult(result: LocationResult) {
        result.lastLocation?.let { /* use it */ }
    }
}

การอัปเดตในรูปแบบ Flow

รูปแบบที่สะอาดคือห่อการอัปเดตไว้ใน callbackFlow เพื่อให้ผู้ใช้ข้อมูลรวบรวมตำแหน่งได้ และการอัปเดตจะหยุดโดยอัตโนมัติเมื่อการรวบรวมสิ้นสุดลงผ่าน awaitClose

import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.callbackFlow

@SuppressLint("MissingPermission")
fun FusedLocationProviderClient.locationFlow(request: LocationRequest) = callbackFlow {
    val cb = object : LocationCallback() {
        override fun onLocationResult(result: LocationResult) {
            result.lastLocation?.let { trySend(it) }
        }
    }
    requestLocationUpdates(request, cb, Looper.getMainLooper())
    awaitClose { removeLocationUpdates(cb) }
}

การแสดงตำแหน่งใน Compose

รวบรวมผลลัพธ์ใน composable โดยใช้ LaunchedEffect สำหรับการอ่านเพียงครั้งเดียว หรือใช้ collectAsStateWithLifecycle สำหรับกระแสข้อมูล จากนั้นแสดงพิกัด

@Composable
fun LocationLabel(client: FusedLocationProviderClient) {
    var location by remember { mutableStateOf<Location?>(null) }
    LaunchedEffect(Unit) {
        location = freshLocation(client)
    }
    Text(
        location?.let { "Lat ${it.latitude}, Lng ${it.longitude}" }
            ?: "Locating..."
    )
}

ข้อแลกเปลี่ยนระหว่างแบตเตอรี่กับความแม่นยำ

ตำแหน่งเป็นหนึ่งในสาเหตุหลักที่ทำให้แอปมือถือใช้แบตเตอรี่สูง เลือกความแม่นยำต่ำที่สุดที่ยังตอบโจทย์ ใช้ช่วงเวลาการอัปเดตที่ยาวที่สุดเท่าที่ยอมรับได้ และ หยุดการอัปเดตทุกครั้ง เมื่อหน้าจอถูกปิดไปแล้ว

ความแม่นยำสูงและการอัปเดตถี่จะทำให้แบตเตอรี่หมดเร็ว ควรสงวนไว้สำหรับการนำทางที่กำลังใช้งานอยู่

ตรวจสอบความเข้าใจ

คุณต้องการตำแหน่งปัจจุบันที่แม่นยำที่สุดเพียงครั้งเดียวทันที โดยใช้ฟังก์ชันที่พักการทำงาน วิธีใดเหมาะสมที่สุด

สรุปทบทวน

ตอนนี้คุณสามารถอ่านตำแหน่งของอุปกรณ์ได้แล้ว:

  • เพิ่ม play-services-location และประกาศ ACCESS_FINE/COARSE_LOCATION
  • รับ FusedLocationProviderClient จาก LocationServices
  • ใช้ lastLocation สำหรับตำแหน่งจากแคช และใช้ getCurrentLocation สำหรับตำแหน่งใหม่
  • รับการอัปเดตเป็นกระแสข้อมูลผ่าน requestLocationUpdates หรือ callbackFlow และหยุดการอัปเดตเพื่อประหยัดแบตเตอรี่

ถัดไป: การวาดเครื่องหมายและเลื่อนกล้องไปยังพิกัดเหล่านั้น

คำถามที่พบบ่อย

บทเรียน “การรับตำแหน่งของผู้ใช้” ฟรีหรือไม่

ใช่ — ข้อความเต็มของ “การรับตำแหน่งของผู้ใช้” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Android Academy ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Android Academy มีบทเรียนทั้งหมด 4 บทเรียน

คุณจะเรียนรู้อะไรในบทเรียน “การรับตำแหน่งของผู้ใช้”

พื้นฐานผู้ให้บริการตำแหน่งแบบรวม คุณปฏิบัติ Android Academy ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน

คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Android Academy หรือไม่

ไม่จำเป็นต้องมีประสบการณ์มาก่อน Android Academy บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 2 จากทั้งหมด 4 บทเรียน

บทเรียน “การรับตำแหน่งของผู้ใช้” ใช้เวลานานแค่ไหน

บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย

ฉันเขียนและรันโค้ดในบทเรียน Android Academy นี้ได้ไหม

ได้ บทเรียน Android Academy ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ

บทเรียนทั้งหมดในหลักสูตรนี้

  1. การแสดงแผนที่
  2. การรับตำแหน่งของผู้ใช้
  3. หมุดและกล้อง
  4. การขอสิทธิ์ตำแหน่งอย่างถูกต้อง
← กลับไปที่ Android Academy