遷移至新的 Places SDK 用戶端

本指南將說明「地點」 相容性程式庫以及新版的獨立版本 Places SDK for Android: 如果您一直使用地點介面集相容性程式庫,而不是遷移至 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 已發布 做為靜態用戶端程式庫Places SDK for Android 在 2019 年 1 月前 是使用 Google Play 服務提供的應用程式從那之後起 提供相容性程式庫,以便您順利移轉至新版 Places SDK for Android。
  • 有多種新方法可供選擇,
  • 欄位遮罩現在支援傳回地點的方法 詳細資料。您可以使用欄位遮罩,指定要匯入哪些類型的地點資料 傳回。
  • 用於回報錯誤的狀態碼已經過改善。
  • 自動完成功能現在支援工作階段符記
  • 地點挑選器已無法使用

關於地點介面集相容性程式庫

自 2019 年 1 月推出 Places SDK for Android 1.0 版後, Google 提供相容性程式庫,以便進行遷移作業 Places SDK for Android 已停用的 Google Play 服務版本 (com.google.android.gms:play-services-places)。

這個相容性程式庫是暫時供重新導向及翻譯 推出新版獨立式 Google Play 服務的 API 呼叫 版本,直到開發人員可以遷移程式碼,使用 獨立的 SDK 設定針對每個 「地點介面集」相容性程式庫現已推出, 功能。

凍結及淘汰地點介面集相容性程式庫

Places SDK for Android 所有版本程式庫 已於 2022 年 3 月 31 日淘汰。2.6.0 版是新版的 地點介面集相容性程式庫。這是存取地點介面集功能及修正錯誤的唯一方式 Android 版 SDK 2.6.0 以上版本將使用 Places SDK for Android。

Google 建議您改用 Places SDK for Android 才能使用 Android 2.6.0 版本的新功能和重大錯誤修正。 如果您目前使用相容性程式庫,請按照下列步驟操作: 如要遷移,請安裝 Places SDK for Android 一節 Places SDK for Android 的呼叫

安裝用戶端程式庫

新版 Places SDK for Android 發布為 靜態用戶端程式庫

使用 Maven 新增 Places SDK for Android 到 Android Studio 專案中:

  1. 如果您目前使用地點介面集相容性程式庫

    1. dependencies 區段中,取代下列程式碼:

          implementation 'com.google.android.libraries.places:places-compat:X.Y.Z'

      按照這行程式碼切換至 Places SDK for Android:

          implementation 'com.google.android.libraries.places:places:3.3.0'

  2. 如果你目前使用 Places SDK for Android 的 Play 服務版本

    1. dependencies 區段中,取代下列程式碼:

          implementation 'com.google.android.gms:play-services-places:X.Y.Z'

      按照這行程式碼切換至 Places SDK for Android:

          implementation 'com.google.android.libraries.places:places:3.3.0'

  3. 同步處理您的 Gradle 專案。

  4. 將應用程式專案的 minSdkVersion 設為 16 以上版本。

  5. 更新「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
    
  6. 建構應用程式。如果完成轉換作業導致發生任何建構錯誤 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);

狀態碼

QPS 限制錯誤的狀態碼已變更。目前查詢限制錯誤 透過 PlaceStatusCodes.OVER_QUERY_LIMIT 傳回。沒有其他 QPD 限制。

已新增下列狀態碼:

  • REQUEST_DENIED:要求遭拒。可能原因如下:

    • 未提供 API 金鑰。
    • 提供的 API 金鑰無效。
    • 尚未啟用 Cloud 控制台的 Places API。
    • 提供的 API 金鑰限制有誤,
  • INVALID_REQUEST:要求因遺失或無效而無效 引數。

  • NOT_FOUND:找不到與指定要求相符的結果。

新方法

新版 Places SDK for Android 推出了全新版本 這兩種方法,為一致性而設計所有新方法 必須遵守下列規範:

  • 端點不再使用 get 動詞。
  • 要求和回應物件的名稱與對應的 用戶端方法。
  • 要求物件現已有建構工具。必要參數會以請求的形式傳遞 建構工具參數
  • 系統已不再使用緩衝區。

本節將介紹新方法,並說明運作方式。

依 ID 擷取地點

使用 fetchPlace() 查看特定地點的詳細資訊。fetchPlace() 函式類似於 getPlaceById()

如要擷取地點,請按照下列步驟操作:

  1. 呼叫 fetchPlace(),並傳遞指定地點的 FetchPlaceRequest 物件 ID 和欄位清單,用於指定要傳回的地點資料。

    // 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();
    
    
  2. 呼叫 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() 會傳回地點的相片。模式 我們簡化了索取相片的程序你現在可以請款 PhotoMetadata 直接從 Place 物件存取且不再需要個別要求。 相片寬度或高度上限為 1600 像素。fetchPhoto() 函式 和 getPhoto() 類似。

如要擷取地點相片,請按照下列步驟操作:

  1. 設定 fetchPlace() 通話。請務必加入 要求中的 PHOTO_METADATAS 欄位:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. 取得 Place 物件 (本範例使用 fetchPlace(),但您也可以使用 findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. 新增 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()

請按照下列步驟取得使用者裝置的目前位置:

  1. 請確保應用程式要求 ACCESS_FINE_LOCATIONACCESS_WIFI_STATE 權限。使用者必須授予權限,才能存取自己的 目前裝置位置。請參閱要求應用程式 下列權限: 詳細資料。

  2. 建立 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();
    
  3. 呼叫 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();
      }
    
,瞭解如何調查及移除這項存取權。

尋找自動完成預測功能

使用 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());
   }
});

工作階段符記

工作階段符記會將使用者搜尋的查詢和選取階段歸入 獨立工作階段用於計費建議您在所有自動完成工作階段使用工作階段符記。工作階段是從使用者輸入 此動作就會結束,使用者選取地點時就結束了。每個時段可以有 後面接一個選取地點即可工作階段結束後 憑證已失效;因此應用程式必須為每一個 會很有幫助

欄位遮罩

在傳回 Place Details 的方法中,您必須指定地點類型 要與每次要求一起傳回的資料。這樣可確保只針對 為你實際使用的資料付費

如要指定要傳回的資料類型,請傳送 Place.Field 陣列的 FetchPlaceRequest,如以下範例所示:

// 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
,瞭解如何調查及移除這項存取權。

進一步瞭解地點資料 SKU

Place Picker 和 Autocomplete 更新

本節說明「地點」小工具 (地點挑選器與「地點」小工具) 的異動 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 Picker。

自動完成小工具

自動完成小工具已更新:

  • Place 前置字串已從所有類別中移除。
  • 開始支援工作階段權杖。小工具可管理權杖 自動在背景執行
  • 新增欄位遮罩支援功能,方便你選擇地點類型 使用者選擇完成後要傳回的資料。

以下各節說明如何在專案中新增 Autocomplete 小工具。

嵌入 AutocompleteFragment

如要新增自動完成片段,請按照下列步驟操作:

  1. 將片段新增至活動的 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"
      />
    
  2. 如要在活動中新增 Autocomplete 小工具,請按照下列步驟操作:

    • 初始化 Places,傳遞應用程式結構定義和您的 API 金鑰。
    • 初始化 AutocompleteSupportFragment
    • 呼叫 setPlaceFields() 來表示需要的地點資料類型 。
    • 新增 PlaceSelectionListener,以便對結果執行某些操作 來處理可能發生的任何錯誤。

    以下範例說明如何將 Autocomplete 小工具新增至活動:

    /**
     * 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);
        }
    });
    

使用意圖啟動 Autocomplete 活動

  1. 初始化 Places,並傳遞應用程式結構定義和 API 金鑰
  2. 使用 Autocomplete.IntentBuilder 建立意圖,並傳遞所需的 PlaceAutocomplete 模式 (全螢幕或重疊)。意圖必須呼叫 startActivityForResult,請傳入要求代碼,以便識別 意圖。
  3. 覆寫 onActivityResult 回呼以接收所選地點。

以下範例說明如何使用意圖啟動 Autocomplete。 然後處理結果:

    /**
     * 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 不支援 Place Picker。