รับการอัปเดตตำแหน่งใน 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 ขึ้นไป นอกจากนี้ คุณต้องตรวจสอบว่ามีกรณีการใช้งานที่ถูกต้องและปฏิบัติตามนโยบายตำแหน่ง คุณจะไม่เห็นตัวเลือกนี้ใน Codelab นี้ เนื่องจากเป็น Use Case ที่พบได้น้อยกว่า อย่างไรก็ตาม หากคุณมี 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 ที่คุณสร้างที่นี่คือการเรียกกลับที่ FusedLocationProviderClient จะเรียกเมื่อมีการอัปเดตตำแหน่งใหม่

ในการเรียกกลับ คุณจะได้รับตำแหน่งล่าสุดก่อนโดยใช้ออบเจ็กต์ 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 จะทำให้ FusedLocationProviderClient ทราบว่าคุณต้องการรับข้อมูลอัปเดตตำแหน่ง

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

นอกจากนี้ คุณอาจสังเกตเห็นว่าโค้ดนี้อยู่ภายในคำสั่ง 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ชั้นเรียน

เรียกใช้ app

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

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

2ae45c4e297e3681.pngd66089bfb532e993.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"
   }
...
}

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

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

เรียกใช้ app

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

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

6a1029175b467c77.pngc7c1d226e49a121.png39a262b66a275f66.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"
   }
...
}

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

153f70847e0ec320.png

หลังจากนั้น แอปของคุณก็พร้อมใช้งาน Android 11 แล้ว

เรียกใช้ app

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

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

73d8cc88c5877c25.pngcc98fac6e089bc4.png

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

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

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

ขอเฉพาะสิทธิ์ที่จำเป็นเท่านั้น

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

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

รองรับการลดลงอย่างค่อยเป็นค่อยไปหากไม่ได้รับสิทธิ์

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

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

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

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

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