รับการอัปเดตตำแหน่งใน Android ด้วย Kotlin

1. ก่อนเริ่มต้น

Android 10 และ 11 ช่วยให้ผู้ใช้ควบคุมแอปของตนได้มากขึ้น การเข้าถึงตำแหน่งอุปกรณ์

เมื่อแอปที่ทำงานใน Android 11 ขอสิทธิ์เข้าถึงตำแหน่ง ผู้ใช้จะมี 4 ตัวเลือกดังต่อไปนี้

  • อนุญาตตลอด
  • อนุญาตขณะใช้แอปเท่านั้น (ใน Android 10)
  • ครั้งเดียวเท่านั้น (ใน Android 11)
  • ปฏิเสธ

Android 10

6a1029175b467c77.png

Android 11

73d8cc88c5877c25.png

ใน Codelab นี้ คุณจะได้เรียนรู้วิธีรับการอัปเดตตำแหน่งและวิธีรองรับตำแหน่งใน Android ทุกเวอร์ชัน โดยเฉพาะ Android 10 และ 11 เมื่อจบ Codelab แล้ว คุณจะเห็นแอปที่เป็นไปตามแนวทางปฏิบัติแนะนำในปัจจุบันสำหรับการเรียกข้อมูลการอัปเดตตำแหน่ง

ข้อกำหนดเบื้องต้น

สิ่งที่คุณจะต้องทำ

  • ทำตามแนวทางปฏิบัติแนะนำสำหรับตำแหน่งใน Android
  • จัดการสิทธิ์เข้าถึงตำแหน่งในเบื้องหน้า (เมื่อผู้ใช้ขอให้แอปเข้าถึงตำแหน่งของอุปกรณ์ขณะที่ใช้งานแอป)
  • แก้ไขแอปที่มีอยู่เพื่อเพิ่มการสนับสนุนสำหรับการขอสิทธิ์เข้าถึงตำแหน่งโดยเพิ่มโค้ดสำหรับการสมัครใช้บริการและยกเลิกการสมัครใช้บริการตำแหน่ง
  • เพิ่มการรองรับแอปสำหรับ Android 10 และ 11 ด้วยการเพิ่มตรรกะเพื่อเข้าถึงตำแหน่งในตำแหน่งเบื้องหน้าหรือขณะใช้งาน

สิ่งที่คุณต้องมี

  • Android Studio 3.4 ขึ้นไปเพื่อเรียกใช้โค้ด
  • อุปกรณ์/โปรแกรมจำลองที่แสดงตัวอย่าง Android 10 และ 11 สำหรับนักพัฒนาซอฟต์แวร์

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

โคลนที่เก็บของโปรเจ็กต์เริ่มต้น

เพื่อช่วยคุณเริ่มต้นโดยเร็วที่สุด คุณสามารถต่อยอดจากโปรเจ็กต์เริ่มต้นนี้ได้ หากคุณติดตั้ง Git ไว้ คุณสามารถเรียกใช้คำสั่งต่อไปนี้:

 git clone https://github.com/android/codelab-while-in-use-location

โปรดไปที่หน้า GitHub โดยตรง

หากคุณไม่มี Git คุณสามารถรับโปรเจ็กต์เป็นไฟล์ ZIP:

นำเข้าโปรเจ็กต์

เปิด Android Studio เลือก "เปิดโปรเจ็กต์ Android Studio ที่มีอยู่" จากหน้าจอต้อนรับ และเปิดไดเรกทอรีโครงการ

หลังจากโหลดโปรเจ็กต์แล้ว คุณอาจเห็นการแจ้งเตือนว่า Git ไม่ได้ติดตามการเปลี่ยนแปลงในเครื่องทั้งหมด คุณสามารถคลิกไม่สนใจ (จะไม่มีการส่งการเปลี่ยนแปลงใดๆ กลับไปยังที่เก็บ Git)

ที่มุมบนซ้ายของหน้าต่างโปรเจ็กต์ คุณควรเห็นบางอย่างที่คล้ายรูปภาพด้านล่างหากอยู่ในมุมมอง Android (หากอยู่ในมุมมองโปรเจ็กต์ คุณจะต้องขยายโปรเจ็กต์เพื่อให้เห็นสิ่งเดียวกัน)

fa825dae96c5dc18.png

มี 2 โฟลเดอร์ (base และ complete) แต่ละโมดูลเรียกว่า "โมดูล"

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

c2273e7835c0841a.png

รอจนกว่า Android Studio จะจัดทำดัชนีและสร้างโปรเจ็กต์เสร็จสิ้นก่อนที่จะเปลี่ยนแปลงโค้ด ซึ่งจะช่วยให้ Android Studio ดึงคอมโพเนนต์ที่จำเป็นทั้งหมดได้

หากได้รับข้อความแจ้งว่า โหลดซ้ำเพื่อให้การเปลี่ยนภาษามีผล หรือข้อความที่คล้ายกัน ให้เลือกใช่

ทำความเข้าใจโปรเจ็กต์เริ่มต้น

คุณได้ตั้งค่าและพร้อมขอตำแหน่งในแอปแล้ว ใช้โมดูล base เป็นจุดเริ่มต้น ในแต่ละขั้นตอน ให้เพิ่มโค้ดลงในโมดูล base เมื่อใช้งาน Codelab นี้เสร็จสิ้นแล้ว โค้ดในโมดูล base ควรตรงกับเนื้อหาของโมดูล complete คุณสามารถใช้โมดูล complete เพื่อตรวจสอบงานหรือเพื่อใช้อ้างอิงหากพบปัญหา

องค์ประกอบหลักมีดังต่อไปนี้

  • MainActivity — UI สำหรับผู้ใช้ที่อนุญาตให้แอปเข้าถึงตำแหน่งของอุปกรณ์
  • LocationService — บริการที่สมัครรับและยกเลิกการสมัครรับอีเมลเกี่ยวกับการเปลี่ยนแปลงตำแหน่ง และโปรโมตตัวเองเป็นบริการที่ทำงานอยู่เบื้องหน้า (พร้อมการแจ้งเตือน) หากผู้ใช้ออกจากกิจกรรมของแอป คุณเพิ่มรหัสสถานที่ตั้งที่นี่
  • Util - เพิ่มฟังก์ชันส่วนขยายสำหรับคลาส Location และบันทึกตำแหน่งใน SharedPreferences (ชั้นข้อมูลแบบง่าย)

การตั้งค่าโปรแกรมจำลอง

ดูข้อมูลเกี่ยวกับการตั้งค่าโปรแกรมจำลองของ Android ได้ที่เรียกใช้โปรแกรมจำลอง

เรียกใช้โปรเจ็กต์เริ่มต้น

เรียกใช้แอป

  1. เชื่อมต่ออุปกรณ์ Android กับคอมพิวเตอร์หรือเริ่มโปรแกรมจําลอง (ตรวจสอบว่าอุปกรณ์ใช้ Android 10 ขึ้นไป)
  2. ในแถบเครื่องมือ ให้เลือกการกำหนดค่า base จากตัวเลือกแบบเลื่อนลง แล้วคลิกเรียกใช้

99600e9d44527ab.png

  1. โปรดสังเกตว่าแอปต่อไปนี้ปรากฏบนอุปกรณ์ของคุณ

99bf1dae46f99af3.png

คุณอาจสังเกตเห็นว่าไม่มีข้อมูลตำแหน่งปรากฏในหน้าจอเอาต์พุต เนื่องจากคุณยังไม่ได้เพิ่มรหัสสถานที่ตั้ง

3. กำลังเพิ่มสถานที่

แนวคิด

จุดมุ่งเน้นของ Codelab นี้คือแสดงวิธีรับการอัปเดตตำแหน่ง ซึ่งท้ายที่สุดแล้วจะรองรับ Android 10 และ Android 11

อย่างไรก็ตาม ก่อนที่คุณจะเริ่มต้นเขียนโค้ด คุณควรตรวจสอบหลักการเบื้องต้นก่อน

ประเภทของการเข้าถึงตำแหน่ง

คุณอาจจำตัวเลือก 4 ข้อที่แตกต่างกันสำหรับการเข้าถึงตำแหน่งได้ตั้งแต่ต้นของ Codelab ลองดูความหมายของคำเหล่านี้

  • อนุญาตขณะใช้แอปเท่านั้น
  • ตัวเลือกนี้เป็นตัวเลือกที่แนะนำสำหรับแอปส่วนใหญ่ หรือที่เรียกว่า "ขณะใช้งาน" หรือ "เบื้องหน้าเท่านั้น" ตัวเลือกนี้เพิ่มเข้ามาใน Android 10 และอนุญาตให้นักพัฒนาแอปดึงข้อมูลตำแหน่งได้ขณะที่มีการใช้งานแอปเท่านั้น ระบบจะถือว่าแอปทำงานอยู่หากเงื่อนไขข้อใดข้อหนึ่งต่อไปนี้เป็นจริง
  • กิจกรรมจะปรากฏขึ้น
  • บริการที่ทำงานอยู่เบื้องหน้ากำลังทำงานพร้อมการแจ้งเตือนต่อเนื่อง
  • ครั้งเดียวเท่านั้น
  • สิ่งที่เพิ่มใน Android 11 จะเหมือนกับการอนุญาตขณะมีการใช้แอปเท่านั้น แต่เป็นเวลาที่จำกัด ดูข้อมูลเพิ่มเติมได้ที่สิทธิ์แบบครั้งเดียว
  • ปฏิเสธ
  • ตัวเลือกนี้จะป้องกันการเข้าถึงข้อมูลตำแหน่ง
  • อนุญาตตลอด
  • ตัวเลือกนี้จะอนุญาตให้เข้าถึงตำแหน่งตลอดเวลา แต่ต้องได้รับสิทธิ์เพิ่มเติมสำหรับ Android 10 ขึ้นไป นอกจากนี้คุณต้องตรวจสอบว่า Use Case ที่ถูกต้องและปฏิบัติตามนโยบายตำแหน่ง ตัวเลือกนี้ไม่รวมใน Codelab นี้เนื่องจากเป็นกรณีการใช้งานที่พบไม่บ่อย อย่างไรก็ตาม หากคุณมี Use Case ที่ถูกต้องและต้องการทําความเข้าใจวิธีจัดการตําแหน่งตลอดเวลาอย่างถูกต้อง รวมถึงการเข้าถึงตําแหน่งในเบื้องหลัง ให้ดูตัวอย่าง LocationUpdatesBackgroundKotlin

บริการ บริการที่ทำงานอยู่เบื้องหน้า และการเชื่อมโยง

หากต้องการรองรับการอัปเดตตําแหน่งแบบอนุญาตขณะใช้แอปอยู่เท่านั้นอย่างเต็มรูปแบบ คุณต้องพิจารณาเมื่อผู้ใช้ออกจากแอปของคุณ หากต้องการรับข้อมูลอัปเดตต่อในสถานการณ์นั้น คุณต้องสร้างเบื้องหน้า Service และเชื่อมโยงกับ Notification

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

เนื่องจาก Codelab นี้มุ่งเน้นการรับอัปเดตตำแหน่งเท่านั้น คุณจึงค้นหาโค้ดทั้งหมดที่ต้องใช้ได้ในชั้นเรียน ForegroundOnlyLocationService.kt คุณสามารถเรียกดูชั้นเรียนนั้นและ MainActivity.kt เพื่อดูว่าทั้ง 2 อย่างทำงานร่วมกันอย่างไร

ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของบริการและภาพรวมของบริการขอบเขต

สิทธิ์

หากต้องการรับการอัปเดตตำแหน่งจาก NETWORK_PROVIDER หรือ GPS_PROVIDER คุณต้องขอสิทธิ์ของผู้ใช้โดยประกาศสิทธิ์ ACCESS_COARSE_LOCATION หรือ ACCESS_FINE_LOCATION ตามลำดับในไฟล์ Manifest ของ Android หากไม่มีสิทธิ์เหล่านี้ แอปจะไม่สามารถขอสิทธิ์เข้าถึงตำแหน่งระหว่างรันไทม์ได้

สิทธิ์ดังกล่าวครอบคลุมกรณีเพียงครั้งเดียวเท่านั้นและอนุญาตขณะมีการใช้แอปเท่านั้น เมื่อมีการใช้แอปของคุณในอุปกรณ์ที่ใช้ Android 10 ขึ้นไป

ตำแหน่ง

แอปของคุณเข้าถึงชุดบริการตำแหน่งที่รองรับผ่านคลาสในแพ็กเกจ com.google.android.gms.location ได้

ดูที่คลาสหลักๆ:

  • FusedLocationProviderClient
  • ส่วนนี้เป็นองค์ประกอบหลักของเฟรมเวิร์กตำแหน่ง เมื่อสร้างแล้ว คุณจะใช้ข้อมูลดังกล่าวเพื่อขออัปเดตตำแหน่งและรับตำแหน่งที่ทราบล่าสุดได้
  • LocationRequest
  • นี่คือออบเจ็กต์ข้อมูลที่มีพารามิเตอร์คุณภาพของการบริการสำหรับคำขอ (ช่วงเวลาสำหรับการอัปเดต ลำดับความสำคัญ และความแม่นยำ) ระบบจะส่งข้อมูลนี้ไปยัง FusedLocationProviderClient เมื่อคุณขออัปเดตตำแหน่ง
  • LocationCallback
  • ซึ่งใช้สำหรับรับการแจ้งเตือนเมื่อตำแหน่งของอุปกรณ์มีการเปลี่ยนแปลงหรือไม่สามารถระบุได้อีกต่อไป ซึ่งผ่าน LocationResult ซึ่งคุณจะรับ Location เพื่อบันทึกไว้ในฐานข้อมูลได้

ตอนนี้คุณเข้าใจเบื้องต้นแล้วว่ากำลังทำอะไรอยู่ ก็มาเริ่มเขียนโค้ดกันเลย

4. เพิ่มฟีเจอร์ตำแหน่ง

Codelab นี้จะเน้นที่ตัวเลือกตำแหน่งที่พบได้ทั่วไป อันได้แก่ อนุญาตขณะมีการใช้แอปเท่านั้น

หากต้องการรับการอัปเดตตำแหน่ง แอปของคุณต้องมีกิจกรรมที่มองเห็นได้หรือบริการที่ทำงานอยู่เบื้องหน้า (พร้อมการแจ้งเตือน)

สิทธิ์

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

สิทธิ์ที่ไฮไลต์ไว้มีดังนี้ (ไม่ต้องดำเนินการใดๆ ในส่วนนี้)

  1. ประกาศสิทธิ์ที่คุณใช้ใน AndroidManifest.xml
  2. ก่อนพยายามเข้าถึงข้อมูลตำแหน่ง ให้ตรวจสอบว่าผู้ใช้ได้ให้สิทธิ์แอปของคุณในการทำเช่นนั้นหรือไม่ หากแอปยังไม่ได้รับสิทธิ์ ให้ขอสิทธิ์เข้าถึง
  3. จัดการตัวเลือกสิทธิ์ของผู้ใช้ (ดูรหัสนี้ได้ใน MainActivity.kt)

หากค้นหา TODO: Step 1.0, Review Permissions ใน AndroidManifest.xml หรือ MainActivity.kt คุณจะเห็นโค้ดทั้งหมดที่เขียนไว้สำหรับสิทธิ์

ดูข้อมูลเพิ่มเติมได้ที่ภาพรวมของสิทธิ์

ทีนี้ก็เริ่มเขียนโค้ดสถานที่เลย

ตรวจสอบตัวแปรหลักที่จำเป็นสำหรับการอัปเดตตำแหน่ง

ในโมดูล base ให้ค้นหา TODO: Step 1.1, Review variables ใน

ForegroundOnlyLocationService.kt ไฟล์

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

// TODO: Step 1.1, Review variables (no changes).
// FusedLocationProviderClient - Main class for receiving location updates.
private lateinit var fusedLocationProviderClient: FusedLocationProviderClient

// LocationRequest - Requirements for the location updates, i.e., how often you
// should receive updates, the priority, etc.
private lateinit var locationRequest: LocationRequest

// LocationCallback - Called when FusedLocationProviderClient has a new Location.
private lateinit var locationCallback: LocationCallback

// Used only for local storage of the last known location. Usually, this would be saved to your
// database, but because this is a simplified sample without a full database, we only need the
// last location to create a Notification if the user navigates away from the app.
private var currentLocation: Location? = null

ตรวจสอบการเริ่มต้น FusedLocationProviderClient

ในโมดูล base ให้ค้นหา TODO: Step 1.2, Review the FusedLocationProviderClient ในไฟล์ ForegroundOnlyLocationService.kt โค้ดของคุณควรมีลักษณะดังนี้

// TODO: Step 1.2, Review the FusedLocationProviderClient.
fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this)

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

เริ่มต้น LocationRequest

  1. ในโมดูล base ให้ค้นหา TODO: Step 1.3, Create a LocationRequest ในไฟล์ ForegroundOnlyLocationService.kt
  2. ใส่รหัสต่อไปนี้หลังความคิดเห็น

โค้ดการเริ่มต้น LocationRequest จะเพิ่มคุณภาพเพิ่มเติมของพารามิเตอร์บริการที่คุณต้องการสำหรับคำขอ (ช่วงเวลา เวลารอสูงสุด และลำดับความสำคัญ)

// TODO: Step 1.3, Create a LocationRequest.
locationRequest = LocationRequest.create().apply {
   // Sets the desired interval for active location updates. This interval is inexact. You
   // may not receive updates at all if no location sources are available, or you may
   // receive them less frequently than requested. You may also receive updates more
   // frequently than requested if other applications are requesting location at a more
   // frequent interval.
   //
   // IMPORTANT NOTE: Apps running on Android 8.0 and higher devices (regardless of
   // targetSdkVersion) may receive updates less frequently than this interval when the app
   // is no longer in the foreground.
   interval = TimeUnit.SECONDS.toMillis(60)

   // Sets the fastest rate for active location updates. This interval is exact, and your
   // application will never receive updates more frequently than this value.
   fastestInterval = TimeUnit.SECONDS.toMillis(30)

   // Sets the maximum time when batched location updates are delivered. Updates may be
   // delivered sooner than this interval.
   maxWaitTime = TimeUnit.MINUTES.toMillis(2)

   priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
  1. อ่านความคิดเห็นเพื่อทำความเข้าใจวิธีการทำงานของแต่ละความคิดเห็น

เริ่มต้น LocationCallback

  1. ในโมดูล base ให้ค้นหา TODO: Step 1.4, Initialize the LocationCallback ในไฟล์ ForegroundOnlyLocationService.kt
  2. ใส่รหัสต่อไปนี้หลังความคิดเห็น
// TODO: Step 1.4, Initialize the LocationCallback.
locationCallback = object : LocationCallback() {
    override fun onLocationResult(locationResult: LocationResult) {
        super.onLocationResult(locationResult)

        // Normally, you want to save a new location to a database. We are simplifying
        // things a bit and just saving it as a local variable, as we only need it again
        // if a Notification is created (when the user navigates away from app).
        currentLocation = locationResult.lastLocation

        // Notify our Activity that a new location was added. Again, if this was a
        // production app, the Activity would be listening for changes to a database
        // with new locations, but we are simplifying things a bit to focus on just
        // learning the location side of things.
        val intent = Intent(ACTION_FOREGROUND_ONLY_LOCATION_BROADCAST)
        intent.putExtra(EXTRA_LOCATION, currentLocation)
        LocalBroadcastManager.getInstance(applicationContext).sendBroadcast(intent)

        // Updates notification content if this service is running as a foreground
        // service.
        if (serviceRunningInForeground) {
            notificationManager.notify(
                NOTIFICATION_ID,
                generateNotification(currentLocation))
        }
    }
}

LocationCallback ที่คุณสร้างที่นี่จะเป็น Callback ที่ FusedLocationProviderClient จะโทรเมื่อมีการอัปเดตตำแหน่งใหม่

ใน Callback คุณจะได้รับตำแหน่งล่าสุดโดยใช้ออบเจ็กต์ LocationResult ก่อน หลังจากนั้น คุณต้องแจ้ง Activity เกี่ยวกับตำแหน่งใหม่โดยใช้การออกอากาศในท้องถิ่น (หากทำงานอยู่) หรืออัปเดต Notification หากบริการนี้ทำงานอยู่เบื้องหน้า Service

  1. อ่านความคิดเห็นเพื่อทำความเข้าใจสิ่งที่แต่ละส่วนทำ

สมัครรับข้อมูลการเปลี่ยนแปลงสถานที่

ในตอนนี้คุณเริ่มต้นทุกอย่างแล้ว คุณต้องแจ้งให้ FusedLocationProviderClient ทราบว่าคุณต้องการรับข้อมูลอัปเดต

  1. ในโมดูล base ให้ค้นหา Step 1.5, Subscribe to location changes ในไฟล์ ForegroundOnlyLocationService.kt
  2. ใส่รหัสต่อไปนี้หลังความคิดเห็น
// TODO: Step 1.5, Subscribe to location changes.
fusedLocationProviderClient.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())

สายที่โทรผ่าน requestLocationUpdates() จะช่วยให้ FusedLocationProviderClient ทราบว่าคุณต้องการรับข้อมูลอัปเดตตำแหน่ง

คุณอาจจะจำ LocationRequest และ LocationCallback ที่กำหนดไว้ก่อนหน้านี้ได้ พารามิเตอร์ดังกล่าวช่วยให้ FusedLocationProviderClient ทราบพารามิเตอร์คุณภาพของการบริการสำหรับคำขอของคุณและสิ่งที่ควรเรียกใช้เมื่อมีการอัปเดต สุดท้าย ออบเจ็กต์ Looper ระบุเทรดสำหรับ Callback

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

ยกเลิกการสมัครรับการเปลี่ยนแปลงสถานที่

เมื่อแอปไม่จำเป็นต้องเข้าถึงข้อมูลตำแหน่งอีกต่อไป คุณต้องยกเลิกการสมัครรับการอัปเดตตำแหน่ง

  1. ในโมดูล base ให้ค้นหา TODO: Step 1.6, Unsubscribe to location changes ในไฟล์ ForegroundOnlyLocationService.kt
  2. ใส่รหัสต่อไปนี้หลังความคิดเห็น
// TODO: Step 1.6, Unsubscribe to location changes.
val removeTask = fusedLocationProviderClient.removeLocationUpdates(locationCallback)
removeTask.addOnCompleteListener { task ->
   if (task.isSuccessful) {
       Log.d(TAG, "Location Callback removed.")
       stopSelf()
   } else {
       Log.d(TAG, "Failed to remove Location Callback.")
   }
}

เมธอด removeLocationUpdates() ตั้งค่างานเพื่อแจ้งให้ FusedLocationProviderClient ทราบว่าคุณไม่ต้องการรับข้อมูลอัปเดตตำแหน่งสำหรับ LocationCallback อีกต่อไป addOnCompleteListener() จะการเรียกกลับเมื่อเสร็จสมบูรณ์และเรียกใช้ Task

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

คุณอาจสงสัยว่าจะมีการเรียกใช้เมธอดที่มีรหัสสมัคร/ยกเลิกการสมัครเมื่อใด การแจ้งเตือนจะแสดงผลในชั้นเรียนหลักเมื่อผู้ใช้แตะปุ่ม หากต้องการดู โปรดดูที่ชั้นเรียน MainActivity.kt

เรียกใช้แอป

เรียกใช้แอปจาก Android Studio แล้วลองใช้ปุ่มตำแหน่ง

คุณควรเห็นข้อมูลตำแหน่งในหน้าจอเอาต์พุต แอปนี้มีฟังก์ชันการทำงานเต็มรูปแบบสำหรับ Android 9

2ae45c4e297e3681.png

d66089bfb532e993.png

5. รองรับ Android 10

ในส่วนนี้ คุณจะเพิ่มการรองรับ Android 10

แอปของคุณสมัครรับข้อมูลการเปลี่ยนแปลงตำแหน่งอยู่แล้ว จึงไม่ต้องทำอะไรมาก

จริงๆ แล้ว คุณเพียงแค่ระบุว่าจะใช้บริการที่ทำงานอยู่เบื้องหน้าเพื่อจุดประสงค์ในการระบุตำแหน่ง

SDK เป้าหมาย 29

  1. ในโมดูล base ให้ค้นหา TODO: Step 2.1, Target Android 10 and then Android 11. ในไฟล์ build.gradle
  2. ทำการเปลี่ยนแปลงต่อไปนี้
  3. ตั้งค่า targetSdkVersion เป็น 29

โค้ดของคุณควรมีลักษณะดังนี้

android {
   // TODO: Step 2.1, Target Android 10 and then Android 11.
   compileSdkVersion 29
   defaultConfig {
       applicationId "com.example.android.whileinuselocation"
       minSdkVersion 26
       targetSdkVersion 29
       versionCode 1
       versionName "1.0"
   }
...
}

หลังจากดำเนินการแล้ว ระบบจะขอให้คุณซิงค์โปรเจ็กต์ คลิก Sync Now

153f70847e0ec320.png

หลังจากนั้น แอปของคุณก็ใกล้จะพร้อมแสดงใน Android 10 แล้ว

เพิ่มประเภทบริการที่ทำงานอยู่เบื้องหน้า

ใน Android 10 คุณต้องระบุประเภทของบริการที่ทำงานอยู่เบื้องหน้าหากต้องการสิทธิ์เข้าถึงตำแหน่งขณะใช้งาน ในกรณีของคุณ จะมีการใช้เพื่อค้นหาข้อมูลตำแหน่ง

ในโมดูล base ให้ค้นหา TODO: 2.2, Add foreground service type ใน AndroidManifest.xml และเพิ่มโค้ดต่อไปนี้ลงในองค์ประกอบ <service>

android:foregroundServiceType="location"

โค้ดของคุณควรมีลักษณะดังนี้

<application>
   ...

   <!-- Foreground services in Android 10+ require type. -->
   <!-- TODO: 2.2, Add foreground service type. -->
   <service
       android:name="com.example.android.whileinuselocation.ForegroundOnlyLocationService"
       android:enabled="true"
       android:exported="false"
       android:foregroundServiceType="location" />
</application>

เท่านี้ก็เรียบร้อย แอปของคุณรองรับตำแหน่งของ Android 10 สำหรับ "ขณะใช้งาน" โดยทำตามแนวทางปฏิบัติแนะนำสำหรับตำแหน่งใน Android

เรียกใช้แอป

เรียกใช้แอปจาก Android Studio แล้วลองใช้ปุ่มตำแหน่ง

ทุกอย่างควรทำงานเหมือนเดิม แต่ตอนนี้ใช้งานได้ใน Android 10 แล้ว หากก่อนหน้านี้คุณไม่เคยยอมรับการอนุญาตสำหรับสถานที่ ตอนนี้คุณควรจะเห็นหน้าจอสิทธิ์แล้ว

6a1029175b467c77.png

c7c1d226e49a121.png

39a262b66a275f66.png

6. รองรับ Android 11

คุณกำหนดเป้าหมายเป็น Android 11 ในส่วนนี้

ข่าวดี คุณไม่จำเป็นต้องเปลี่ยนแปลงไฟล์ใดๆ ยกเว้นไฟล์ build.gradle

SDK เป้าหมาย 11

  1. ในโมดูล base ให้ค้นหา TODO: Step 2.1, Target SDK ในไฟล์ build.gradle
  2. ทำการเปลี่ยนแปลงต่อไปนี้
  3. compileSdkVersion ถึง 30
  4. targetSdkVersion ถึง 30

โค้ดของคุณควรมีลักษณะดังนี้

android {
   TODO: Step 2.1, Target Android 10 and then Android 11.
   compileSdkVersion 30
   defaultConfig {
       applicationId "com.example.android.whileinuselocation"
       minSdkVersion 26
       targetSdkVersion 30
       versionCode 1
       versionName "1.0"
   }
...
}

หลังจากดำเนินการแล้ว ระบบจะขอให้คุณซิงค์โปรเจ็กต์ คลิก Sync Now

153f70847e0ec320.png

หลังจากนั้น แอปจะพร้อมใช้งานสำหรับ Android 11

เรียกใช้แอป

เรียกใช้แอปจาก Android Studio แล้วลองคลิกปุ่มดังกล่าว

ทุกอย่างควรจะทำงานได้ตามปกติ แต่ตอนนี้ใช้งานได้ใน Android 11 แล้ว หากก่อนหน้านี้คุณไม่เคยยอมรับการอนุญาตสำหรับสถานที่ ตอนนี้คุณควรจะเห็นหน้าจอสิทธิ์แล้ว

73d8cc88c5877c25.png

cc98fac6e089bc4.png

7. กลยุทธ์ตำแหน่งสำหรับ Android

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

หน้านี้จะแสดงแนวทางปฏิบัติแนะนำบางส่วนที่เกี่ยวข้องกับสิทธิ์เข้าถึงตำแหน่ง ดูข้อมูลเพิ่มเติมเกี่ยวกับวิธีทำให้ผู้ใช้ของคุณ ความปลอดภัยของข้อมูล โปรดดูแนวทางปฏิบัติแนะนำเกี่ยวกับสิทธิ์ของแอป

ขอเฉพาะสิทธิ์ที่คุณต้องการ

ขอสิทธิ์เมื่อจำเป็นเท่านั้น เช่น

  • อย่าขอสิทธิ์เข้าถึงตำแหน่งเมื่อเริ่มต้นแอป เว้นแต่จะจําเป็นจริงๆ
  • หากแอปกำหนดเป้าหมายเป็น Android 10 ขึ้นไปและคุณมีบริการที่ทำงานอยู่เบื้องหน้า ให้ประกาศ foregroundServiceType เป็น "location" ในไฟล์ Manifest
  • อย่าขอสิทธิ์เข้าถึงตำแหน่งในเบื้องหลังเว้นแต่คุณจะมีกรณีการใช้งานที่ถูกต้องตามที่อธิบายไว้ในการเข้าถึงตำแหน่งของผู้ใช้ที่ปลอดภัยและโปร่งใสมากขึ้น

สนับสนุนการลดลงอย่างค่อยเป็นค่อยไปหากไม่ได้รับอนุญาต

ออกแบบแอปให้สามารถรับมือกับสถานการณ์ต่อไปนี้ได้อย่างสวยงามเพื่อให้ผู้ใช้ได้รับประสบการณ์การใช้งานที่ดี

  • แอปของคุณไม่มีสิทธิ์เข้าถึงข้อมูลตำแหน่ง
  • แอปของคุณไม่มีสิทธิ์เข้าถึงข้อมูลตำแหน่งเมื่อทำงานในเบื้องหลัง

8. ขอแสดงความยินดี

คุณได้เรียนรู้วิธีรับการอัปเดตตำแหน่งใน Android แล้ว อย่าลืมนึกถึงแนวทางปฏิบัติแนะนำด้วย

ดูข้อมูลเพิ่มเติม