การรับตำแหน่งของผู้ใช้
พื้นฐานผู้ให้บริการตำแหน่งแบบรวม
การรับตำแหน่งของผู้ใช้ เป็นบทเรียน 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 ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การแสดงแผนที่
- การรับตำแหน่งของผู้ใช้
- หมุดและกล้อง
- การขอสิทธิ์ตำแหน่งอย่างถูกต้อง