本指南說明 Places Compatibility 程式庫與新版 Places SDK for Android 獨立版本之間的異動。如果您一直以來使用 Places 相容性資料庫,但不想改用新版 Places SDK for Android 獨立版本,本指南會說明如何將專案更新為使用新版 Places SDK for Android。
如要使用 Places SDK for Android 2.6.0 版以上的功能及錯誤修正方式,唯一的方法是使用 Places SDK for Android。Google 建議您盡快從相容性程式庫更新為新版 Places SDK for Android 版本。
異動內容
注意: Places SDK for Android 2.0.0 以上版本支援 AndroidX 。從這個版本開始,系統不再支援舊版支援資料庫。為了維持相容性,您必須遷移專案以使用 AndroidX。
主要異動部分如下:
新版 Places SDK for Android 會發布為靜態用戶端程式庫。在 2019 年 1 月前,您可以透過 Google Play 服務提供 Places SDK for Android。此後,我們便提供 Places 相容性程式庫,以簡化轉換至新版 Places SDK for Android 的程序。
有全新的方法 。
欄位遮罩 現在支援傳回地點詳細資料的方法。您可以使用欄位遮罩指定要傳回的地點資料類型。
我們改善了用於回報錯誤的狀態碼 。
自動完成功能現在支援工作階段符記 。
「地點選擇器」已無法使用 。
關於 Places 相容性資料庫
在 2019 年 1 月推出的獨立 Places SDK for Android 版本 1.0 中,Google 提供了相容性程式庫,協助您從 Places SDK for Android (com.google.android.gms:play-services-places
) 停用的 Google Play 服務版本遷移。
這個相容性程式庫是暫時性的,用來將以 Google Play 服務版本為目標的 API 呼叫進行重新導向並轉譯為新版獨立版本,直到開發人員能夠遷移程式碼,使用獨立 SDK 中的新名稱。針對從 1.0 版到 2.6.0 版發布的 Places SDK for Android 每個版本,我們都有相對應的對應版本 Places 相容性資料庫,以提供同等的功能。
凍結及淘汰 Places 相容性資料庫
Places SDK for Android 的所有相容性程式庫版本已於 2022 年 3 月 31 日淘汰。2.6.0 版是 Places 相容性資料庫的最後一個版本。如要使用 Places SDK for Android 2.6.0 版以上的功能及錯誤修正方式,唯一的方法是使用 Places SDK for Android。
Google 建議您改用 Places SDK for Android,以便存取 2.6.0 版以上的新功能和重大錯誤修正。
如果您目前使用相容性程式庫,請按照安裝 Places SDK for Android 一節中的步驟操作,改用 Places SDK for Android。
注意: 相容性程式庫和 Places SDK for Android 有些狀態碼和 Autocomplete
類別名稱不同。這意味著,當您轉換為 Places SDK for Android 時,可能會發生一些建構錯誤。請參閱以下章節,瞭解如何解決這些建構錯誤。
安裝用戶端程式庫
提醒: 如要使用 Places SDK for Android,您必須:
新版 Places SDK for Android 會發布為靜態用戶端程式庫。
注意: 您只能安裝 Places SDK for Android (com.google.android.libraries.places:places
) 或相容性程式庫 (com.google.android.libraries.places:places-compat
),但不能同時安裝。 使用 Maven 將 Places SDK for Android 新增至您的 Android Studio 專案:
如果您目前使用 Places 相容性程式庫 :
在 dependencies
區段中,取代以下這行:
implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'
切換至這一行,即可改用 Places SDK for Android:
implementation 'com.google.android.libraries.places:places:3.0.0'
如果您目前使用 Places SDK for Android 的 Play 服務版本 :
在 dependencies
區段中,取代以下這行:
implementation 'com.google.android.gms:play-services-places:X.Y.Z '
切換至這一行,即可改用 Places SDK for Android:
implementation 'com.google.android.libraries.places:places:3.0.0'
同步處理您的 Gradle 專案。
請將應用程式專案的 minSdkVersion
設為 16 以上。
更新「Google 技術提供」的素材資源:
@drawable/powered_by_google_light // OLD
@drawable/places_powered_by_google_light // NEW
@drawable/powered_by_google_dark // OLD
@drawable/places_powered_by_google_dark // NEW
建構您的應用程式。如果您因為轉換到 Places SDK for Android 而發現任何建構錯誤,請參閱以下各節,瞭解如何解決這些錯誤。
初始化新的 Places SDK 用戶端
初始化新的 Places SDK 用戶端,如以下範例所示:
// Add an import statement for the client library.
import com.google.android.libraries.places.api.Places;
...
// Initialize Places.
Places.initialize(getApplicationContext(), apiKey);
// Create a new Places client instance.
PlacesClient placesClient = Places.createClient(this);
狀態碼
每秒查詢次數限制錯誤的狀態碼已變更。每秒查詢次數限制錯誤會透過 PlaceStatusCodes.OVER_QUERY_LIMIT
傳回。沒有其他的 PPD 限制。
已新增下列狀態碼:
新方法
新版 Places SDK for Android 推出了專為一致性而設計的全新方法。所有新方法都會遵循以下規定:
端點不再使用 get
動詞。
要求和回應物件的名稱會與對應的用戶端方法共用。
要求物件現在有建構工具;所需的參數會以要求建構工具的參數的形式傳遞。
緩衝區已不再使用。
本節介紹新的方法,並向您說明這些方法的運作方式。
根據 ID 擷取地點
使用 fetchPlace()
取得特定地點的詳細資料。fetchPlace()
的運作方式與 getPlaceById()
類似。
擷取地點的步驟如下:
呼叫 fetchPlace()
,傳遞指定地點 ID 的 FetchPlaceRequest
物件,以及指定要傳回地點資料的 fields 清單。
// Define a Place ID.
String placeId = "INSERT_PLACE_ID_HERE";
// Specify the fields to return.
List<Place.Field> placeFields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
// Construct a request object, passing the place ID and fields array.
FetchPlaceRequest request = FetchPlaceRequest.builder(placeId, placeFields)
.build();
呼叫 addOnSuccessListener()
來處理 FetchPlaceResponse
。系統會傳回單一的 Place
結果。
// Add a listener to handle the response.
placesClient.fetchPlace(request).addOnSuccessListener((response) -> {
Place place = response.getPlace();
Log.i(TAG, "Place found: " + place.getName());
}).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
int statusCode = apiException.getStatusCode();
// Handle error with given status code.
Log.e(TAG, "Place not found: " + exception.getMessage());
}
});
擷取地點相片
使用 fetchPhoto()
取得地點相片。fetchPhoto()
會傳回特定地點的相片。要求相片的模式已簡化。您現在可以直接透過 Place
物件要求 PhotoMetadata
,不再需要再提出要求。相片的寬度或高度上限為 1600 像素。fetchPhoto()
函式與 getPhoto()
類似。
請按照下列步驟擷取地點相片:
設定 fetchPlace()
的通話。請務必在要求中加入 PHOTO_METADATAS
欄位:
List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
取得 Place 物件 (此範例使用 fetchPlace()
,但您也可以使用 findCurrentPlace()
):
FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
新增 OnSuccessListener
,從 FetchPlaceResponse
中取得的 Place
取得相片中繼資料,然後使用產生的相片中繼資料取得點陣圖和歸因文字:
placesClient.fetchPlace(placeRequest).addOnSuccessListener((response) -> {
Place place = response.getPlace();
// Get the photo metadata.
PhotoMetadata photoMetadata = place.getPhotoMetadatas().get(0);
// Get the attribution text.
String attributions = photoMetadata.getAttributions();
// Create a FetchPhotoRequest.
FetchPhotoRequest photoRequest = FetchPhotoRequest.builder(photoMetadata)
.setMaxWidth(500) // Optional.
.setMaxHeight(300) // Optional.
.build();
placesClient.fetchPhoto(photoRequest).addOnSuccessListener((fetchPhotoResponse) -> {
Bitmap bitmap = fetchPhotoResponse.getBitmap();
imageView.setImageBitmap(bitmap);
}).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
int statusCode = apiException.getStatusCode();
// Handle error with given status code.
Log.e(TAG, "Place not found: " + exception.getMessage());
}
});
});
從使用者的位置尋找地點
使用 findCurrentPlace()
找出使用者裝置目前的位置。findCurrentPlace()
會傳回 PlaceLikelihood
清單,指出使用者裝置最有可能所在的位置。findCurrentPlace()
的運作方式與 getCurrentPlace()
類似。
請按照下列步驟取得使用者裝置目前的位置:
請確認您的應用程式要求 ACCESS_FINE_LOCATION
和 ACCESS_WIFI_STATE
權限。使用者必須授予權限,才能存取目前的裝置位置資訊。詳情請參閱要求應用程式權限 一節。
建立 FindCurrentPlaceRequest
,其中包含要傳回的地點資料類型清單。
// Use fields to define the data types to return.
List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME);
// Use the builder to create a FindCurrentPlaceRequest.
FindCurrentPlaceRequest request =
FindCurrentPlaceRequest.builder(placeFields).build();
呼叫 findCurrentPlace 並處理回應,先檢查使用者是否已授權使用其裝置的位置。
// Call findCurrentPlace and handle the response (first check that the user has granted permission).
if (ContextCompat.checkSelfPermission(this, ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
placesClient.findCurrentPlace(request).addOnSuccessListener(((response) -> {
for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
Log.i(TAG, String.format("Place '%s' has likelihood: %f",
placeLikelihood.getPlace().getName(),
placeLikelihood.getLikelihood()));
textView.append(String.format("Place '%s' has likelihood: %f\n",
placeLikelihood.getPlace().getName(),
placeLikelihood.getLikelihood()));
}
})).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.e(TAG, "Place not found: " + apiException.getStatusCode());
}
});
} else {
// A local method to request required permissions;
// See https://developer.android.com/training/permissions/requesting
getLocationPermission();
}
重要事項! findCurrentPlace()
不支援下列欄位:Place.Field.ADDRESS_COMPONENTS
、Place.Field.OPENING_HOURS
、Place.Field.PHONE_NUMBER
和 Place.Field.WEBSITE_URI
。
查看自動完成預測
使用 findAutocompletePredictions()
來傳回使用者的搜尋查詢。findAutocompletePredictions()
的運作方式與 getAutocompletePredictions()
類似。
下例示範如何呼叫 findAutocompletePredictions()
:
// Create a new token for the autocomplete session. Pass this to FindAutocompletePredictionsRequest,
// and once again when the user makes a selection (for example when calling fetchPlace()).
AutocompleteSessionToken token = AutocompleteSessionToken.newInstance();
// Create a RectangularBounds object.
RectangularBounds bounds = RectangularBounds.newInstance(
new LatLng(-33.880490, 151.184363),
new LatLng(-33.858754, 151.229596));
// Use the builder to create a FindAutocompletePredictionsRequest.
FindAutocompletePredictionsRequest request = FindAutocompletePredictionsRequest.builder()
// Call either setLocationBias() OR setLocationRestriction().
.setLocationBias(bounds)
//.setLocationRestriction(bounds)
.setCountry("au")
.setTypesFilter(Arrays.asList(PlaceTypes.ADDRESS))
.setSessionToken(token)
.setQuery(query)
.build();
placesClient.findAutocompletePredictions(request).addOnSuccessListener((response) -> {
for (AutocompletePrediction prediction : response.getAutocompletePredictions()) {
Log.i(TAG, prediction.getPlaceId());
Log.i(TAG, prediction.getPrimaryText(null).toString());
}
}).addOnFailureListener((exception) -> {
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.e(TAG, "Place not found: " + apiException.getStatusCode());
}
});
工作階段符記
為求計費,工作階段符記會將使用者搜尋的查詢和選取階段分組為不同的工作階段。建議您在所有自動完成工作階段使用工作階段符記。工作階段會在使用者開始輸入查詢時開始,並在使用者選取地點時結束。每個工作階段都可以有多個查詢,然後再選取一個位置。工作階段結束後,憑證就不再有效;您的應用程式必須為各個工作階段產生新的權杖。
室外面具
在傳回地點詳細資料的方法中,您必須指定要每個要求傳回的地點資料類型類型。這有助於確保您只要求實際使用 (並付費) 的資料。
如要指定要傳回的資料類型,請在 FetchPlaceRequest
中傳遞 Place.Field
陣列,如以下範例所示:
// Include address, ID, and phone number.
List<Place.Field> placeFields = Arrays.asList(Place.Field.ADDRESS,
Place.Field.ID,
Place.Field.PHONE_NUMBER);
您可以使用下列一或多個欄位:
Place.Field.ADDRESS
Place.Field.ID
Place.Field.LAT_LNG
Place.Field.NAME
Place.Field.OPENING_HOURS
Place.Field.PHONE_NUMBER
Place.Field.PHOTO_METADATAS
Place.Field.PLUS_CODE
Place.Field.PRICE_LEVEL
Place.Field.RATING
Place.Field.TYPES
Place.Field.USER_RATINGS_TOTAL
Place.Field.VIEWPORT
Place.Field.WEBSITE_URI
重要事項! findCurrentPlace()
不支援下列欄位:Place.Field.ADDRESS_COMPONENTS
、Place.Field.OPENING_HOURS
、Place.Field.PHONE_NUMBER
和 Place.Field.WEBSITE_URI
。
進一步瞭解地點資料 SKU 。
Place Picker 和 Autocomplete 更新
本節說明 Places 小工具 (Place Picker 和 Autocomplete) 的變更。
程式輔助自動完成功能
我們針對自動完成功能 進行了以下變更:
PlaceAutocomplete
已重新命名為 Autocomplete
。
PlaceAutocomplete.getPlace
已重新命名為 Autocomplete.getPlaceFromIntent
。
PlaceAutocomplete.getStatus
已重新命名為 Autocomplete.getStatusFromIntent
。
PlaceAutocomplete.RESULT_ERROR
已重新命名為 AutocompleteActivity.RESULT_ERROR
(「自動完成」片段的錯誤處理方式「未」變更)。
地點挑選器
「地點挑選程式」已於 2019 年 1 月 29 日淘汰。這項功能已於 2019 年 7 月 29 日停用繼續使用之後就會收到錯誤訊息。新的 SDK 不支援「地點挑選程式」。
自動完成小工具已更新:
已從所有類別中移除 Place
前置字串。
新增對工作階段符記的支援。這個小工具會在背景自動管理憑證。
新增對欄位遮罩的支援,讓您在使用者選取項目後,選擇要傳回的地點類型資料類型。
以下各節說明如何將自動完成小工具新增至專案。
嵌入 AutocompleteFragment
若要新增自動完成片段,請按照下列步驟進行:
在活動的 XML 版面配置中新增片段,如以下範例所示。
<fragment
android:id="@+id/autocomplete_fragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:name=
"com.google.android.libraries.places.widget.AutocompleteSupportFragment"
/>
如要將自動完成小工具新增至活動,請按照下列步驟操作:
初始化 Places
,並傳遞應用程式結構定義和 API 金鑰。
初始化 AutocompleteSupportFragment
。
呼叫 setPlaceFields()
表示您想要取得的地點資料類型。
新增 PlaceSelectionListener
以處理結果,並處理可能發生的任何錯誤。
以下範例說明如何在活動中加入自動完成小工具:
/**
* Initialize Places. For simplicity, the API key is hard-coded. In a production
* environment we recommend using a secure mechanism to manage API keys.
*/
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "YOUR_API_KEY");
}
// Initialize the AutocompleteSupportFragment.
AutocompleteSupportFragment autocompleteFragment = (AutocompleteSupportFragment)
getSupportFragmentManager().findFragmentById(R.id.autocomplete_fragment);
autocompleteFragment.setPlaceFields(Arrays.asList(Place.Field.ID, Place.Field.NAME));
autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
@Override
public void onPlaceSelected(Place place) {
// TODO: Get info about the selected place.
Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
}
@Override
public void onError(Status status) {
// TODO: Handle the error.
Log.i(TAG, "An error occurred: " + status);
}
});
使用意圖啟動自動完成活動
初始化 Places
,並傳遞應用程式結構定義和 API 金鑰
使用 Autocomplete.IntentBuilder
建立意圖,並傳送所需的 PlaceAutocomplete
模式 (全螢幕或重疊)。意圖必須呼叫 startActivityForResult
,並傳入可識別意圖的要求代碼。
覆寫 onActivityResult
回呼以接收所選地點。
下列範例說明如何使用意圖啟動自動完成功能,然後處理結果:
/**
* Initialize Places. For simplicity, the API key is hard-coded. In a production
* environment we recommend using a secure mechanism to manage API keys.
*/
if (!Places.isInitialized()) {
Places.initialize(getApplicationContext(), "YOUR_API_KEY");
}
...
// Set the fields to specify which types of place data to return.
List<Place.Field> fields = Arrays.asList(Place.Field.ID, Place.Field.NAME);
// Start the autocomplete intent.
Intent intent = new Autocomplete.IntentBuilder(
AutocompleteActivityMode.FULLSCREEN, fields)
.build(this);
startActivityForResult(intent, AUTOCOMPLETE_REQUEST_CODE);
...
/**
* Override the activity's onActivityResult(), check the request code, and
* do something with the returned place data (in this example its place name and place ID).
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == AUTOCOMPLETE_REQUEST_CODE) {
if (resultCode == RESULT_OK) {
Place place = Autocomplete.getPlaceFromIntent(data);
Log.i(TAG, "Place: " + place.getName() + ", " + place.getId());
} else if (resultCode == AutocompleteActivity.RESULT_ERROR) {
// TODO: Handle the error.
Status status = Autocomplete.getStatusFromIntent(data);
Log.i(TAG, status.getStatusMessage());
} else if (resultCode == RESULT_CANCELED) {
// The user canceled the operation.
}
}
}
「地點挑選器」已無法使用
「地點挑選程式」已於 2019 年 1 月 29 日淘汰。這項功能已於 2019 年 7 月 29 日停用繼續使用之後就會收到錯誤訊息。新的 SDK 不支援「地點挑選程式」。