如何在 Android 中实现 Google 的 Places AutocompleteBar?
如果您曾经在移动设备上使用过 Google 地图或从桌面访问过,那么您肯定已经在搜索栏中输入了某个位置并选择了其中一个结果。结果可能包含地址、电话号码、评分、时间等字段。此外,如果您曾经在 google.com 上从桌面搜索过某个地点,那么您一定会得到许多搜索结果以及带有上述参数从右侧对齐。下面给出了一个示例 GIF,以了解我们将在本文中做什么。请注意,我们将使用Kotlin语言来实现这个项目。
这两个应用程序都实现了一个 API,公开称为 Places API。自动完成栏是 Places API 的一项功能,它根据用户在搜索栏中键入的词推荐位置列表。借助 Places API,我们将实现 AutocompleteBar 并获取位置信息。
分步实施
第 1 步:在 Android Studio 中创建一个新项目
要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。我们在 Kotlin 中演示了该应用程序,因此请确保在创建新项目时选择Kotlin作为主要语言。
第 2 步:获取和隐藏 API 密钥
我们的应用程序利用 Google 的 Places API 来实现自动完成栏,因此我们需要从 Google 获取 Places API 密钥。要获取 API 密钥,请参阅生成用于使用任何 Google API 的 API 密钥。隐藏 API 密钥是必不可少的,为此,请参阅如何在 Android Studio 中隐藏 API 和秘密密钥?。
第三步:在build.gradle文件中添加依赖
我们需要导入支持我们的自动完成栏实现的库。由于自动完成栏是 Places API 的一项功能,我们需要在 build.gradle 文件中附加其最新的依赖项。以下是必须添加的依赖项。
implementation ‘com.google.android.libraries.places:places:2.4.0’
第 4 步:在清单文件中添加 Internet 权限
导航到app > manifest 文件夹并记下它的以下权限。
第五步:在activity_main.xml文件中实现Autocomplete Bar片段(前端)
导航到app > res > layout > activity_main.xml并将以下代码添加到该文件中。下面是activity_main.xml文件的代码。
XML
Kotlin
package org.geeksforgeeks.myapplication
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import com.google.android.gms.common.api.Status
import com.google.android.libraries.places.api.Places
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.widget.AutocompleteSupportFragment
import com.google.android.libraries.places.widget.listener.PlaceSelectionListener
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Fetching API_KEY which we wrapped
val ai: ApplicationInfo = applicationContext.packageManager
.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
val value = ai.metaData["api_key"]
val apiKey = value.toString()
// Initializing the Places API
// with the help of our API_KEY
if (!Places.isInitialized()) {
Places.initialize(applicationContext, apiKey)
}
// Initialize Autocomplete Fragments
// from the main activity layout file
val autocompleteSupportFragment1 = supportFragmentManager.findFragmentById(R.id.autocomplete_fragment1) as AutocompleteSupportFragment?
// Information that we wish to fetch after typing
// the location and clicking on one of the options
autocompleteSupportFragment1!!.setPlaceFields(
listOf(
Place.Field.NAME,
Place.Field.ADDRESS,
Place.Field.PHONE_NUMBER,
Place.Field.LAT_LNG,
Place.Field.OPENING_HOURS,
Place.Field.RATING,
Place.Field.USER_RATINGS_TOTAL
)
)
// Display the fetched information after clicking on one of the options
autocompleteSupportFragment1.setOnPlaceSelectedListener(object : PlaceSelectionListener {
override fun onPlaceSelected(place: Place) {
// Text view where we will
// append the information that we fetch
val textView = findViewById(R.id.tv1)
// Information about the place
val name = place.name
val address = place.address
val phone = place.phoneNumber.toString()
val latlng = place.latLng
val latitude = latlng?.latitude
val longitude = latlng?.longitude
val isOpenStatus : String = if(place.isOpen == true){
"Open"
} else {
"Closed"
}
val rating = place.rating
val userRatings = place.userRatingsTotal
textView.text = "Name: $name \nAddress: $address \nPhone Number: $phone \n" +
"Latitude, Longitude: $latitude , $longitude \nIs open: $isOpenStatus \n" +
"Rating: $rating \nUser ratings: $userRatings"
}
override fun onError(status: Status) {
Toast.makeText(applicationContext,"Some error occurred", Toast.LENGTH_SHORT).show()
}
})
}
}
第 6 步:使用 MainActivity.kt(后端)
简而言之,我们所做的是:
- 获取我们在步骤 2 中存储的 API 密钥。
- 使用 API 密钥初始化 Places API。
- 在布局 (activity_main.xml) 中初始化了自动完成片段。
- 声明了我们希望从 API 获取的位置参数。
- 在选择侦听器事件上声明,当从自动完成栏结果中单击位置时,该事件会在布局的文本视图中发布参数。
onError函数是 select 监听器的一个成员函数,它会在失败时抛出一个 toast 消息“发生了一些错误”。一般原因可能是互联网不可用。下面是MainActivity.kt文件的代码。代码中添加了注释以更详细地理解代码。
科特林
package org.geeksforgeeks.myapplication
import android.content.pm.ApplicationInfo
import android.content.pm.PackageManager
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import com.google.android.gms.common.api.Status
import com.google.android.libraries.places.api.Places
import com.google.android.libraries.places.api.model.Place
import com.google.android.libraries.places.widget.AutocompleteSupportFragment
import com.google.android.libraries.places.widget.listener.PlaceSelectionListener
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Fetching API_KEY which we wrapped
val ai: ApplicationInfo = applicationContext.packageManager
.getApplicationInfo(applicationContext.packageName, PackageManager.GET_META_DATA)
val value = ai.metaData["api_key"]
val apiKey = value.toString()
// Initializing the Places API
// with the help of our API_KEY
if (!Places.isInitialized()) {
Places.initialize(applicationContext, apiKey)
}
// Initialize Autocomplete Fragments
// from the main activity layout file
val autocompleteSupportFragment1 = supportFragmentManager.findFragmentById(R.id.autocomplete_fragment1) as AutocompleteSupportFragment?
// Information that we wish to fetch after typing
// the location and clicking on one of the options
autocompleteSupportFragment1!!.setPlaceFields(
listOf(
Place.Field.NAME,
Place.Field.ADDRESS,
Place.Field.PHONE_NUMBER,
Place.Field.LAT_LNG,
Place.Field.OPENING_HOURS,
Place.Field.RATING,
Place.Field.USER_RATINGS_TOTAL
)
)
// Display the fetched information after clicking on one of the options
autocompleteSupportFragment1.setOnPlaceSelectedListener(object : PlaceSelectionListener {
override fun onPlaceSelected(place: Place) {
// Text view where we will
// append the information that we fetch
val textView = findViewById(R.id.tv1)
// Information about the place
val name = place.name
val address = place.address
val phone = place.phoneNumber.toString()
val latlng = place.latLng
val latitude = latlng?.latitude
val longitude = latlng?.longitude
val isOpenStatus : String = if(place.isOpen == true){
"Open"
} else {
"Closed"
}
val rating = place.rating
val userRatings = place.userRatingsTotal
textView.text = "Name: $name \nAddress: $address \nPhone Number: $phone \n" +
"Latitude, Longitude: $latitude , $longitude \nIs open: $isOpenStatus \n" +
"Rating: $rating \nUser ratings: $userRatings"
}
override fun onError(status: Status) {
Toast.makeText(applicationContext,"Some error occurred", Toast.LENGTH_SHORT).show()
}
})
}
}
输出:
Note: Turn the Internet (Wifi/Mobile Data) on before launching the application.