Bắt đầu với SDK địa điểm dành cho Android (Kotlin)

1. Trước khi bắt đầu

Lớp học lập trình này hướng dẫn bạn cách tích hợp SDK địa điểm cho Android với ứng dụng của bạn và sử dụng từng tính năng của SDK địa điểm.

Ứng dụng minh họa địa điểm

Điều kiện tiên quyết

  • Có kiến thức cơ bản về Kotlin và phát triển Android

Kiến thức bạn sẽ học được

  • Cách cài đặt SDK địa điểm cho Android bằng Tiện ích Kotlin.
  • Cách tải thông tin chi tiết về địa điểm cho một địa điểm cụ thể.
  • Cách thêm tiện ích Tự động hoàn thành địa điểm vào ứng dụng của bạn.
  • Cách tải Địa điểm hiện tại dựa trên vị trí hiện được báo cáo của thiết bị.

Bạn cần có

Để hoàn thành lớp học lập trình này, bạn cần có các tài khoản, dịch vụ và công cụ sau:

2. Bắt đầu thiết lập

Đối với bước bật bên dưới, hãy bật API Địa điểm.

Thiết lập Nền tảng Google Maps

Nếu bạn chưa có tài khoản Google Cloud Platform và một dự án đã bật tính năng thanh toán, vui lòng xem hướng dẫn Bắt đầu sử dụng Google Maps Platform để tạo tài khoản thanh toán và một dự án.

  1. Trong Cloud Console, hãy nhấp vào trình đơn thả xuống dự án và chọn dự án mà bạn muốn sử dụng cho lớp học lập trình này.

  1. Bật API và SDK của Nền tảng Google Maps bắt buộc cho lớp học lập trình này trong Google Cloud Marketplace. Để làm như vậy, hãy làm theo các bước trong video này hoặc tài liệu này.
  2. Tạo khoá API trong trang Thông tin xác thực của Cloud Console. Bạn có thể làm theo các bước trong video này hoặc tài liệu này. Tất cả các yêu cầu gửi đến Google Maps Platform đều yêu cầu khóa API.

3. Bắt đầu nhanh

Để bắt đầu nhanh nhất có thể, hãy tải mã dành cho người mới bắt đầu xuống để theo dõi lớp học lập trình này. Bạn có thể chuyển sang giải pháp này, nhưng nếu muốn làm theo tất cả các bước để tự xây dựng giải pháp, hãy đọc tiếp.

  1. Sao chép kho lưu trữ nếu bạn đã cài đặt git.
git clone https://github.com/googlemaps/codelab-places-101-android.git

Ngoài ra, hãy nhấp vào nút này để tải mã nguồn xuống.

  1. Sau khi tải mã xuống, hãy mở dự án tìm thấy trong thư mục /starter trong Android Studio. Dự án này bao gồm cấu trúc tệp cơ bản mà bạn cần hoàn thành lớp học lập trình. Mọi công việc bạn cần làm đều nằm trong thư mục /starter.

Nếu bạn muốn xem mã giải pháp đầy đủ đang chạy, bạn có thể xem mã đã hoàn tất trong thư mục /solution.

4. Cài đặt SDK địa điểm cho Android

Trong phần này, bạn thêm SDK địa điểm dành cho Android vào các phần phụ thuộc của ứng dụng.

Thêm khóa API của bạn

Cung cấp khóa API mà bạn đã tạo trước đó cho ứng dụng để SDK địa điểm dành cho Android có thể liên kết khóa của bạn với ứng dụng của bạn.

  1. Mở tệp có tên local.properties trong thư mục gốc của dự án (cùng cấp với gradle.propertiessettings.gradle).
  2. Xác định khoá mới GOOGLE_MAPS_API_KEY, đặt giá trị của khoá này thành khoá API mà bạn đã tạo.

local.properties

GOOGLE_MAPS_API_KEY=YOUR_KEY_HERE

Xin lưu ý rằng local.properties được liệt kê trong tệp .gitignore trong kho lưu trữ Git. Điều này là do khóa API của bạn được coi là thông tin nhạy cảm và không nên kiểm tra nguồn kiểm soát nguồn, nếu có thể.

  1. Tiếp theo, để hiển thị khóa API của bạn để ứng dụng có thể sử dụng trên toàn bộ ứng dụng, hãy thêm trình bổ trợ Bí mật Gradle cho Android vào tệp build.gradle của ứng dụng, nằm trong thư mục app/ và thêm dòng sau vào khối plugins:

build.gradle cấp ứng dụng

plugins {
    // ...
    id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
}
  1. Sửa đổi tệp build.gradle cấp dự án để bao gồm đường dẫn lớp sau:

build.gradle cấp dự án

buildscript {
    dependencies {
        // ...
        classpath "com.google.android.libraries.mapsplatform.secrets-gradle-plugin:secrets-gradle-plugin:2.0.1"
    }
}

Plugin này làm cho các khóa bạn đã xác định trong tệp local.properties có sẵn dưới dạng biến bản dựng trong tệp kê khai Android và dưới dạng biến trong lớp BuildConfig do Gradle tạo vào thời điểm xây dựng. Việc sử dụng trình bổ trợ này sẽ xóa mã nguyên mẫu mà sẽ cần thiết để đọc các thuộc tính khỏi local.properties để có thể truy cập mã trong suốt ứng dụng của bạn.

Thêm SDK địa điểm cho phần phụ thuộc Android

  1. Bây giờ, bạn có thể truy cập vào khóa API bên trong ứng dụng, hãy thêm SDK địa điểm dành cho phần phụ thuộc Android vào tệp build.gradle của ứng dụng.

Trong dự án dành cho người mới bắt đầu đi kèm với lớp học lập trình này, phần phụ thuộc này đã được thêm vào cho bạn.

build.gradle cấp ứng dụng

dependencies {
   // Dependency to include Places SDK for Android
   implementation 'com.google.android.libraries.places:places:2.6.0'
}
  1. Chạy ứng dụng.

Đến đây, bạn sẽ thấy một ứng dụng chưa có màn hình nào. Tiếp tục điền ba màn hình minh họa trên màn hình này.

5. Cài đặt Địa điểm Android KTX

Đối với các ứng dụng Kotlin sử dụng một hoặc nhiều SDK Android nền tảng Google Maps, thư viện tiện ích Kotlin (KTX) cho phép bạn tận dụng các tính năng về ngôn ngữ Kotlin, chẳng hạn như coroutine, thuộc tính/hàm mở rộng và nhiều tính năng khác. Mỗi SDK của Google Maps có một thư viện KTX tương ứng như được hiển thị dưới đây:

Sơ đồ KTX của nền tảng Google Maps

Trong nhiệm vụ này, hãy sử dụng thư viện Địa điểm KTX trên Android để sử dụng các tính năng ngôn ngữ dành riêng cho Kotlin trong ứng dụng của bạn.

Thêm phần phụ thuộc KTX trên Android

Để tận dụng các tính năng dành riêng cho Kotlin, hãy thêm thư viện KTX tương ứng cho SDK này trong tệp build.gradle cấp ứng dụng của bạn.

build.gradle

dependencies {
    // ...

    // Places SDK for Android KTX Library
    implementation 'com.google.maps.android:places-ktx:2.0.0'
}

6. Khởi chạy Ứng dụng Địa điểm

Khởi chạy SDK địa điểm cho phạm vi ứng dụng

Trong tệp DemoApplication.kt của thư mục app/src/main/java/com/google/codelabs/maps/placesdemo, hãy khởi chạy SDK địa điểm cho Android. Dán các dòng bên dưới vào cuối hàm onCreate:

        // Initialize the SDK with the Google Maps Platform API key
        Places.initialize(this, BuildConfig.GOOGLE_MAPS_API_KEY)

Khi bạn tạo ứng dụng, Trình bổ trợ Gradle cho Android cung cấp khóa API trong tệp local.properties của bạn dưới dạng BuildConfig.GOOGLE_MAPS_API_KEY.

Thêm tệp ứng dụng vào tệp kê khai

Vì bạn đã mở rộng Application với DemoApplication, nên bạn cần cập nhật tệp kê khai. Thêm thuộc tính android:name vào phần tử application trong tệp AndroidManifest.xml nằm trong app/src/main:

    <application
        android:name=".DemoApplication"
        ...
    </application>

Mã này trỏ đến tệp kê khai ứng dụng tới lớp DemoApplication trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/.

7. Tìm nạp thông tin chi tiết về địa điểm

Tạo màn hình Chi tiết

Bố cục activity_details.xml không có LinearLayout trống sẽ có trong thư mục app/src/main/res/layout/. Điền bố cục tuyến tính bằng cách thêm mã sau vào giữa dấu ngoặc <LinearLayout>.

    <com.google.android.material.textfield.TextInputLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <com.google.android.material.textfield.TextInputEditText
            android:id="@+id/details_input"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:hint="@string/details_input_hint"
            android:text="@string/details_input_default" />

    </com.google.android.material.textfield.TextInputLayout>

    <Button
        android:id="@+id/details_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/button_details" />

    <TextView
        android:id="@+id/details_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:textIsSelectable="true" />

Mã này sẽ thêm một trường nhập văn bản để người dùng có thể nhập bất kỳ Mã địa điểm nào hoặc sử dụng giá trị mặc định được cung cấp, một nút để bắt đầu yêu cầu Thông tin chi tiết về địa điểm và một Chế độ xem văn bản để hiển thị thông tin từ phản hồi. Các chuỗi liên kết được xác định cho bạn trong tệp src/main/res/values/strings.xml.

Tạo một hoạt động chi tiết

  1. Tạo một tệp DetailsActivity.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/ và liên kết tệp đó với bố cục bạn vừa tạo. Dán mã này vào tệp:
class DetailsActivity : AppCompatActivity() {
    private lateinit var placesClient: PlacesClient
    private lateinit var detailsButton: Button
    private lateinit var detailsInput: TextInputEditText
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_details)

        // Set up view objects
        detailsInput = findViewById(R.id.details_input)
        detailsButton = findViewById(R.id.details_button)
        responseView = findViewById(R.id.details_response_content)

    }
}
  1. Tạo Ứng dụng địa điểm để sử dụng với hoạt động này. Dán mã này sau khi đối tượng chế độ xem được thiết lập trong hàm onCreate.
        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)
  1. Sau khi Ứng dụng địa điểm được thiết lập, hãy đính kèm một trình xử lý lượt nhấp vào nút này. Dán mã này sau khi tạo Ứng dụng địa điểm trong hàm onCreate.
        // Upon button click, fetch and display the Place Details
        detailsButton.setOnClickListener {
            val placeId = detailsInput.text.toString()
            val placeFields = listOf(
                Place.Field.NAME,
                Place.Field.ID,
                Place.Field.LAT_LNG,
                Place.Field.ADDRESS
            )
            lifecycleScope.launch {
                try {
                    val response = placesClient.awaitFetchPlace(placeId, placeFields)
                    responseView.text = response.prettyPrint()
                } catch (e: Exception) {
                    e.printStackTrace()
                    responseView.text = e.message
                }
            }
        }

Mã này truy xuất mã địa điểm đã được nhập vào trường nhập dữ liệu, xác định những trường cần yêu cầu cho địa điểm, tạo FetchPlaceRequest, bắt đầu nhiệm vụ và lắng nghe thành công hoặc không thành công. Nếu yêu cầu thành công, hàm sẽ điền chi tiết được yêu cầu vào Chế độ xem văn bản.

  1. Chuyển đổi FetchPlaceResponse thành văn bản bằng cách xác định hàm mở rộng. Tệp StringUtil.kt được cung cấp để đơn giản hóa việc chuyển đổi các phản hồi của SDK địa điểm thành các chuỗi mà con người có thể đọc được.

Ở cuối tệp DetailsActivity.kt, hãy xác định một hàm để chuyển đổi đối tượng phản hồi của tính năng Tìm nạp địa điểm thành một chuỗi.

fun FetchPlaceResponse.prettyPrint(): String {
    return StringUtil.stringify(this, false)
}

Thêm hoạt động Chi tiết vào tệp kê khai

Thêm phần tử <activity> cho DetailsActivity làm phần tử con của phần tử <application> trong tệp AndroidManifest.xml nằm trong app/src/main:

        <activity android:name=".DetailsActivity" />

Thêm hoạt động Chi tiết vào trình đơn minh họa

Mô-đun Demo trống được cung cấp để liệt kê các bản minh họa hiện có trên màn hình chính. Bây giờ, bạn đã tạo hoạt động Chi tiết địa điểm, hãy thêm hoạt động đó vào tệp Demo.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/ với mã này:

    DETAILS_FRAGMENT_DEMO(
        R.string.details_demo_title,
        R.string.details_demo_description,
        DetailsActivity::class.java
    ),

Các chuỗi liên kết được xác định trong tệp src/main/res/values/strings.xml.

Hãy kiểm tra MainActivity.kt và quan sát thấy chế độ xem này tạo một Chế độ xem danh sách được điền bằng cách lặp lại nội dung của mô-đun Demo. Nếu người dùng nhấn vào một mục trong danh sách, thì trình nghe lượt nhấp sẽ mở hoạt động được liên kết.

Chạy ứng dụng

  1. Chạy ứng dụng. Lần này, bạn sẽ thấy một mục trong danh sách trình bày Chi tiết địa điểm.
  2. Nhấn vào văn bản Thông tin chi tiết về địa điểm. Bạn sẽ thấy chế độ xem mình đã tạo bằng trường nhập dữ liệu và nút.
  3. Nhấn vào nút "GET CHI TIẾT". Nếu bạn đã sử dụng mã địa điểm mặc định, thì bạn sẽ thấy tên địa điểm, địa chỉ và tọa độ bản đồ hiển thị, như minh họa trong Hình 1.

Hoạt động chi tiết về địa điểm kèm theo phản hồi

Hình 1. Hoạt động chi tiết về địa điểm được phản hồi hiển thị.

8. Thêm tính năng tự động hoàn thành địa điểm

Tạo màn hình Tự động hoàn thành

Bố cục activity_autocomplete.xml không có LinearLayout trống được cung cấp trong thư mục app/src/main/res/layout/. Điền vào bố cục tuyến tính bằng cách thêm mã này vào giữa dấu ngoặc <LinearLayout>.

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/autocomplete_fragment"
        android:background="@android:color/white"
        android:name="com.google.android.libraries.places.widget.AutocompleteSupportFragment"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/autocomplete_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:textIsSelectable="true" />

Mã này sẽ thêm một tiện ích AutocompleteSupportFragment và một Chế độ xem văn bản để hiện thông tin trong phản hồi. Các chuỗi liên kết được xác định trong tệp src/main/res/values/strings.xml.

Tạo hoạt động Tự động hoàn thành

  1. Tạo một tệp AutocompleteActivity.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/ và xác định tệp đó bằng mã sau:
class AutocompleteActivity : AppCompatActivity() {
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_autocomplete)

        // Set up view objects
        responseView = findViewById(R.id.autocomplete_response_content)
        val autocompleteFragment =
            supportFragmentManager.findFragmentById(R.id.autocomplete_fragment)
                    as AutocompleteSupportFragment
    }
}

Mã này liên kết hoạt động với các chế độ xem và AutocompleteSupportFramgent mà bạn đã xác định trong tệp bố cục.

  1. Tiếp theo, hãy xác định điều gì sẽ xảy ra khi người dùng chọn một trong các cụm từ gợi ý có tính năng Tự động hoàn thành địa điểm. Thêm mã này vào cuối hàm onCreate:
        // Specify the types of place data to return.
        autocompleteFragment.setPlaceFields(listOf(Place.Field.NAME, Place.Field.ID, Place.Field.LAT_LNG, Place.Field.ADDRESS))

        // Listen to place selection events
        lifecycleScope.launchWhenCreated {
            autocompleteFragment.placeSelectionEvents().collect { event ->
                when (event) {
                    is PlaceSelectionSuccess -> {
                        val place = event.place
                        responseView.text = StringUtil.stringifyAutocompleteWidget(place, false)
                    }
                    is PlaceSelectionError -> Toast.makeText(
                        this@AutocompleteActivity,
                        "Failed to get place '${event.status.statusMessage}'",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            }

Mã này xác định những trường cần yêu cầu cho địa điểm, theo dõi một sự kiện lựa chọn địa điểm, và theo dõi sự thành công hoặc không thành công. Nếu yêu cầu thành công, hàm sẽ điền thông tin chi tiết về địa điểm vào Chế độ xem văn bản. Hãy lưu ý rằng tính năng Tự động hoàn thành địa điểm trả về một đối tượng Địa điểm; không cần phải thực hiện yêu cầu Chi tiết về địa điểm riêng biệt khi sử dụng tiện ích Tự động hoàn thành địa điểm.

Thêm hoạt động Tự động hoàn thành vào tệp kê khai

Thêm phần tử <activity> cho AutocompleteActivity làm phần tử con của phần tử <application> trong tệp AndroidManifest.xml nằm trong app/src/main:

        <activity android:name=".AutocompleteActivity" />

Thêm hoạt động Tự động hoàn thành vào trình đơn minh họa

Cũng giống như trước, hãy thêm bản minh họa về tính năng Tự động hoàn thành của địa điểm vào màn hình chính bằng cách thêm bản minh họa đó vào danh sách trong mô-đun Demo. Bây giờ, bạn đã tạo hoạt động Tự động hoàn thành địa điểm, hãy thêm hoạt động đó vào tệp Demo.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/. Dán mã này ngay sau mục DETAILS_FRAGMENT_DEMO:

    AUTOCOMPLETE_FRAGMENT_DEMO(
        R.string.autocomplete_fragment_demo_title,
        R.string.autocomplete_fragment_demo_description,
        AutocompleteActivity::class.java
    ),

Các chuỗi liên kết được xác định trong tệp src/main/res/values/strings.xml.

Chạy ứng dụng

  1. Chạy ứng dụng. Lần này, bạn sẽ thấy hai mục trong danh sách trên màn hình chính.
  2. Nhấn vào hàng Tự động hoàn thành địa điểm. Bạn sẽ thấy cửa sổ bật lên nhập Thông tin tự động hoàn thành như hình 2.
  3. Bắt đầu nhập tên của một địa điểm. Đây có thể là tên cơ sở, địa chỉ hoặc khu vực địa lý. Cụm từ gợi ý phải xuất hiện khi bạn nhập.
  4. Chọn một trong các cụm từ gợi ý. Các dự đoán sẽ biến mất và Chế độ xem văn bản giờ đây sẽ hiển thị chi tiết về địa điểm đã chọn như minh họa trong Hình 3.

Hoạt động tự động hoàn thành sau khi người dùng nhấn vào trường nhập dữ liệu

Hình 2. Hoạt động tự động hoàn thành sau khi người dùng nhấn vào trường nhập dữ liệu.

Hoạt động tự động hoàn thành sau khi người dùng nhập và chọn &ldquo;Niagara Falls&rdquo;

Hình 3. Hoạt động tự động hoàn thành hiển thị Chi tiết địa điểm sau khi người dùng nhập và chọn "Niagara Falls".

9. Nhận vị trí hiện tại của thiết bị

Tạo màn hình Địa điểm hiện tại

Bố cục activity_current.xml không có LinearLayout đã được cung cấp trong thư mục app/src/main/res/layout/. Điền bố cục tuyến tính bằng cách thêm mã sau vào giữa dấu ngoặc <LinearLayout>.

    <Button
        android:id="@+id/current_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/current_button" />

    <TextView
        android:id="@+id/current_response_content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="16dp"
        android:scrollbars = "vertical"
        android:textIsSelectable="true" />

Tạo hoạt động cho Địa điểm hiện tại

  1. Tạo một tệp CurrentActivity.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/ và xác định tệp đó bằng mã này:
class CurrentPlaceActivity : AppCompatActivity() {
    private lateinit var placesClient: PlacesClient
    private lateinit var currentButton: Button
    private lateinit var responseView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_current)

        // Retrieve a PlacesClient (previously initialized - see DemoApplication)
        placesClient = Places.createClient(this)

        // Set view objects
        currentButton = findViewById(R.id.current_button)
        responseView = findViewById(R.id.current_response_content)


        // Set listener for initiating Current Place
        currentButton.setOnClickListener {
            checkPermissionThenFindCurrentPlace()
        }
    }
}

Mã này liên kết hoạt động với các chế độ xem bạn đã xác định trong tệp bố cục. Thao tác này cũng thêm một trình xử lý lượt nhấp vào nút này để gọi hàm checkPermissionThenFindCurrentPlace khi nút được nhấp vào.

  1. Hãy xác định checkPermissionThenFindCurrentPlace() để kiểm tra quyền truy cập thông tin vị trí chính xác và yêu cầu quyền nếu quyền này chưa được cấp. Dán mã này sau hàm onCreate.
    /**
     * Checks that the user has granted permission for fine or coarse location.
     * If granted, finds current Place.
     * If not yet granted, launches the permission request.
     * See https://developer.android.com/training/permissions/requesting
     */
    private fun checkPermissionThenFindCurrentPlace() {
        when {
            (ContextCompat.checkSelfPermission(
                this,
                ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(
                this,
                ACCESS_COARSE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED) -> {
                // You can use the API that requires the permission.
                findCurrentPlace()
            }
            shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)
            -> {
                Log.d(TAG, "Showing permission rationale dialog")
                // TODO: In an educational UI, explain to the user why your app requires this
                // permission for a specific feature to behave as expected. In this UI,
                // include a "cancel" or "no thanks" button that allows the user to
                // continue using your app without granting the permission.
            }
            else -> {
                // Ask for both the ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions.
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(
                        Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_COARSE_LOCATION
                    ),
                    PERMISSION_REQUEST_CODE
                )
            }
        }
    }

    companion object {
        private val TAG = "CurrentPlaceActivity"
        private const val PERMISSION_REQUEST_CODE = 9
    }
  1. Khi nhánh else của hàm checkPermissionThenFindCurrentPlace gọi requestPermissions, ứng dụng sẽ hiển thị hộp thoại yêu cầu cấp quyền cho người dùng. Nếu người dùng đang chạy một thiết bị chạy hệ điều hành thấp hơn Android 12, thì người dùng chỉ có thể cấp quyền truy cập thông tin vị trí chính xác (chính xác). Nếu người dùng đang sử dụng thiết bị chạy Android 12 trở lên, thì họ sẽ được cung cấp tùy chọn cung cấp vị trí gần đúng (xấu) thay vì vị trí chính xác (mạnh), như minh họa trong Hình 4.

Yêu cầu sự cho phép của người dùng trên một thiết bị chạy Android 12 trở lên

Hình 4. Yêu cầu sự cho phép của người dùng trên một thiết bị chạy Android 12 trở lên sẽ có tùy chọn cấp vị trí chính xác hoặc gần đúng.

Sau khi người dùng phản hồi hộp thoại quyền của hệ thống, hệ thống sẽ gọi việc triển khai onRequestPermissionsResult của ứng dụng. Hệ thống sẽ chuyển thông tin phản hồi của người dùng đến hộp thoại quyền, cũng như mã yêu cầu mà bạn đã xác định. Ghi đè onRequestPermissionResult để xử lý mã yêu cầu cho các quyền vị trí liên quan đến hoạt động Địa điểm hiện tại này bằng cách dán mã sau đây vào bên dưới checkPermissionThenFindCurrentPlace.

    @SuppressLint("MissingPermission")
    override fun onRequestPermissionsResult(
        requestCode: Int,
        permissions: Array<String>, grantResults: IntArray
    ) {
        if (requestCode != PERMISSION_REQUEST_CODE) {
            super.onRequestPermissionsResult(
                requestCode,
                permissions,
                grantResults
            )
            return
        } else if (permissions.toList().zip(grantResults.toList())
                .firstOrNull { (permission, grantResult) ->
                    grantResult == PackageManager.PERMISSION_GRANTED && (permission == ACCESS_FINE_LOCATION || permission == ACCESS_COARSE_LOCATION)
                } != null
        )
            // At least one location permission has been granted, so proceed with Find Current Place
            findCurrentPlace()
    }
  1. Sau khi được cấp quyền, hàm findCurrentPlace sẽ chạy. Xác định hàm bằng mã này sau hàm onRequestPermissionsResult.
    /**
     * Fetches a list of [PlaceLikelihood] instances that represent the Places the user is
     * most
     * likely to be at currently.
     */
    @RequiresPermission(anyOf = [ACCESS_COARSE_LOCATION, ACCESS_FINE_LOCATION])
    private fun findCurrentPlace() {
        // Use fields to define the data types to return.
        val placeFields: List<Place.Field> =
            listOf(Place.Field.NAME, Place.Field.ID, Place.Field.ADDRESS, Place.Field.LAT_LNG)

        // Use the builder to create a FindCurrentPlaceRequest.
        val request: FindCurrentPlaceRequest = FindCurrentPlaceRequest.newInstance(placeFields)

        // Call findCurrentPlace and handle the response (first check that the user has granted permission).
        if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED ||
            ContextCompat.checkSelfPermission(this, ACCESS_COARSE_LOCATION) ==
            PackageManager.PERMISSION_GRANTED
        ) {
            // Retrieve likely places based on the device's current location
            lifecycleScope.launch {
                try {
                    val response = placesClient.awaitFindCurrentPlace(placeFields)
                    responseView.text = response.prettyPrint()

                    // Enable scrolling on the long list of likely places
                    val movementMethod = ScrollingMovementMethod()
                    responseView.movementMethod = movementMethod
                } catch (e: Exception) {
                    e.printStackTrace()
                    responseView.text = e.message
                }
            }
        } else {
            Log.d(TAG, "LOCATION permission not granted")
            checkPermissionThenFindCurrentPlace()

        }
    }

Mã này xác định những trường cần yêu cầu cho các địa điểm có thể, tạo FindCurrentPlaceRequest, bắt đầu việc cần làm và điền các Chế độ xem văn bản bằng các thông tin chi tiết được yêu cầu.

  1. Chuyển đổi FindCurrentPlaceResponse thành văn bản bằng cách xác định hàm mở rộng. Tệp StringUtil.kt được cung cấp để đơn giản hóa việc chuyển đổi các phản hồi của SDK địa điểm thành các chuỗi mà con người có thể đọc được.

Ở cuối tệp CurrentPlaceActivity.kt, hãy xác định một hàm để chuyển đổi đối tượng phản hồi của Địa điểm hiện tại thành một chuỗi.

fun FindCurrentPlaceResponse.prettyPrint(): String {
    return StringUtil.stringify(this, false)
}

Thêm hoạt động của Địa điểm hiện tại vào tệp kê khai

Thêm phần tử <activity> cho CurrentPlaceActivity làm phần tử con của phần tử <application> trong tệp AndroidManifest.xml nằm trong app/src/main:

        <activity android:name=".CurrentPlaceActivity" />

Thêm hoạt động của Địa điểm hiện tại vào trình đơn minh họa

Cũng như trước đây, hãy thêm bản minh họa Địa điểm hiện tại vào màn hình chính bằng cách thêm bản minh họa đó vào danh sách trong mô-đun Demo. Bây giờ, bạn đã tạo một hoạt động cho Địa điểm hiện tại, hãy thêm hoạt động đó vào tệp Demo.kt trong thư mục src/main/java/com/google/codelabs/maps/placesdemo/. Dán mã này ngay sau mục AUTOCOMPLETE_FRAGMENT_DEMO:

    CURRENT_FRAGMENT_DEMO(
        R.string.current_demo_title,
        R.string.current_demo_description,
        CurrentPlaceActivity::class.java
    ),

Các chuỗi liên kết được xác định trong tệp src/main/res/values/strings.xml.

Chạy ứng dụng

  1. Chạy ứng dụng. Lần này, bạn sẽ thấy ba mục trong danh sách trên màn hình chính.
  2. Nhấn vào hàng Địa điểm hiện tại. Bạn sẽ thấy một nút trên màn hình.
  3. Nhấn vào nút. Nếu trước đây bạn chưa cấp quyền truy cập thông tin vị trí cho ứng dụng này, thì yêu cầu cấp quyền sẽ bật lên.
  4. Cấp cho ứng dụng quyền truy cập vào thông tin vị trí của thiết bị.
  5. Nhấn vào nút này một lần nữa. Lần này, một danh sách gồm tối đa 20 địa điểm lân cận và khả năng của các địa điểm đó sẽ xuất hiện, như được minh họa trong Hình 5.

Đang hiển thị các kết quả phù hợp với địa điểm hiện tại cho vị trí được báo cáo cho thiết bị và thiết bị

Hình 5. Đang hiển thị các kết quả có thể khớp với Địa điểm hiện tại cho vị trí được báo cáo của thiết bị.

10. Xin chúc mừng

Bạn đã tạo thành công một ứng dụng Android với SDK Địa điểm dành cho Android.

Những điều bạn đã học được

Nội dung tiếp theo là gì?

  • Khám phá hoặc phân phối kho lưu trữ android-places-demos của GitHub với các mẫu và bản minh họa để có thêm ý tưởng.
  • Tìm hiểu từ các lớp học lập trình khác về Kotlin để xây dựng các ứng dụng Android với Nền tảng Google Maps.
  • Hãy giúp chúng tôi tạo nội dung mà bạn thấy hữu ích nhất bằng cách trả lời câu hỏi sau:

Bạn muốn xem những lớp học lập trình nào khác?

Hình ảnh dữ liệu trên bản đồ Tìm hiểu thêm về cách tùy chỉnh kiểu bản đồ của tôi Xây dựng hoạt động tương tác 3D trong bản đồ

Lớp học lập trình mà bạn muốn không được liệt kê? Yêu cầu phát hành vấn đề mới tại đây.