Di chuyển sang ứng dụng SDK Địa điểm mới

Hướng dẫn này giải thích những thay đổi giữa các Địa điểm thư viện về khả năng tương thích và phiên bản độc lập mới của SDK Địa điểm dành cho Android. Nếu bạn đang sử dụng thư viện Khả năng tương thích với Địa điểm thay vì chuyển sang phiên bản độc lập mới của SDK Địa điểm dành cho Android, hướng dẫn này sẽ cho bạn biết cách cập nhật các dự án của bạn để sử dụng phiên bản mới của SDK Địa điểm dành cho Android.

Cách duy nhất để truy cập vào các tính năng và bản sửa lỗi trong SDK địa điểm dành cho Android ở trên Phiên bản 2.6.0 sẽ sử dụng SDK Địa điểm dành cho Android. Bạn nên cập nhật từ thư viện tương thích lên SDK Địa điểm dành cho Android càng sớm càng tốt.

Điều gì đã thay đổi?

Sau đây là các lĩnh vực thay đổi chính:

  • Phiên bản mới của SDK địa điểm dành cho Android được phân phối làm thư viện ứng dụng tĩnh. Trước tháng 1 năm 2019, SDK Địa điểm dành cho Android đã được cung cấp thông qua Dịch vụ Google Play. Kể từ đó, việc mở rộng Địa điểm thư viện khả năng tương thích được cung cấp để dễ dàng chuyển đổi sang SDK Địa điểm dành cho Android.
  • Hiện có các phương thức hoàn toàn mới.
  • Mặt nạ trường hiện được hỗ trợ cho các phương thức trả về địa điểm chi tiết. Bạn có thể sử dụng mặt nạ trường để chỉ định loại dữ liệu địa điểm nào cần lợi nhuận.
  • Chúng tôi đã cải thiện mã trạng thái dùng để báo cáo lỗi.
  • Tính năng tự động hoàn thành hiện hỗ trợ mã thông báo phiên.
  • Bộ chọn địa điểm không còn hoạt động nữa.

Giới thiệu về thư viện Khả năng tương thích với Địa điểm

Vào tháng 1 năm 2019, cùng với việc phát hành Phiên bản 1.0 của SDK Địa điểm độc lập dành cho Android, Google đã cung cấp một thư viện về khả năng tương thích để giúp bạn di chuyển từ phiên bản Dịch vụ Google Play đã ngừng hoạt động của SDK Địa điểm dành cho Android (com.google.android.gms:play-services-places).

Thư viện về khả năng tương thích này được cung cấp tạm thời để chuyển hướng và dịch Lệnh gọi API nhắm đến phiên bản Dịch vụ Google Play đến phiên bản độc lập mới cho đến khi nhà phát triển có thể di chuyển mã của họ để sử dụng tên mới trong SDK độc lập. Đối với mỗi phiên bản SDK địa điểm dành cho Android đã được phát hành từ Phiên bản 1.0 đến Phiên bản 2.6.0, một phiên bản tương ứng của thư viện Khả năng tương thích với Địa điểm đã được phát hành để cung cấp phiên bản tương đương của Google.

Đóng băng và ngừng sử dụng thư viện Khả năng tương thích của Google Địa điểm

Tất cả phiên bản của thư viện tương thích cho SDK Địa điểm dành cho Android sẽ không được dùng nữa kể từ ngày 31 tháng 3 năm 2022. Phiên bản 2.6.0 là phiên bản cuối cùng của Thư viện về khả năng tương thích với địa điểm. Cách duy nhất để truy cập vào các tính năng và bản sửa lỗi trong Địa điểm SDK dành cho Android ở trên Phiên bản 2.6.0 sẽ sử dụng SDK địa điểm dành cho Android.

Google khuyên bạn nên di chuyển sang SDK Địa điểm dành cho Android để truy cập các tính năng mới và các bản sửa lỗi quan trọng cho những bản phát hành trên Phiên bản 2.6.0. Nếu bạn đang dùng thư viện tương thích, hãy làm theo các bước dưới đây trong Cài đặt SDK địa điểm dành cho Android để di chuyển SDK Địa điểm dành cho Android.

Cài đặt thư viện ứng dụng

Phiên bản mới của SDK địa điểm dành cho Android được phân phối dưới dạng thư viện ứng dụng tĩnh.

Sử dụng Maven để thêm Vị trí SDK dành cho Android vào dự án Android Studio của bạn:

  1. Nếu bạn đang sử dụng thư viện Khả năng tương thích với Địa điểm:

    1. Thay thế dòng sau trong phần dependencies:

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

      Với dòng này để chuyển sang SDK Địa điểm dành cho Android:

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

  2. Nếu bạn hiện đang sử dụng phiên bản Dịch vụ Play của SDK Địa điểm dành cho Android:

    1. Thay thế dòng sau trong phần dependencies:

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

      Với dòng này để chuyển sang SDK Địa điểm dành cho Android:

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

  3. Đồng bộ hoá dự án Gradle của bạn.

  4. Đặt minSdkVersion cho dự án ứng dụng thành 16 trở lên.

  5. Cập nhật ứng dụng "Do Google cung cấp" thành phần:

    @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. Xây dựng ứng dụng của bạn. Nếu bạn thấy bất kỳ lỗi bản dựng nào do việc chuyển đổi của bạn thành SDK Địa điểm dành cho Android, hãy xem các phần bên dưới để biết thông tin về việc giải quyết các lỗi này.

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

Khởi chạy ứng dụng SDK Địa điểm mới như trong ví dụ sau:

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

Mã trạng thái

Mã trạng thái cho các lỗi giới hạn QPS đã thay đổi. Lỗi giới hạn QPS được trả lại qua PlaceStatusCodes.OVER_QUERY_LIMIT. Không còn hạn mức QPD nào nữa.

Các mã trạng thái sau đây đã được thêm vào:

  • REQUEST_DENIED — Yêu cầu đã bị từ chối. Nguyên nhân dẫn đến sự khác biệt này có thể là:

    • Bạn chưa cung cấp khoá API.
    • Bạn đã cung cấp khoá API không hợp lệ.
    • Bạn chưa bật Places API trong bảng điều khiển Cloud.
    • Bạn đã cung cấp một khoá API có các quy tắc hạn chế không chính xác về khoá.
  • INVALID_REQUEST — Yêu cầu không hợp lệ do thiếu một phần tử hoặc yêu cầu không hợp lệ đối số.

  • NOT_FOUND – Không tìm thấy kết quả nào cho yêu cầu đã cho.

Phương thức mới

Phiên bản mới của SDK Địa điểm dành cho Android giới thiệu tính năng hoàn toàn mới được thiết kế để đảm bảo tính nhất quán. Tất cả phương thức mới tuân thủ những điều sau:

  • Điểm cuối không còn sử dụng động từ get nữa.
  • Đối tượng yêu cầu và đối tượng phản hồi có cùng tên với đối tượng tương ứng .
  • Đối tượng yêu cầu hiện có trình tạo; các tham số bắt buộc được truyền dưới dạng yêu cầu các thông số của trình tạo.
  • Vùng đệm không còn được sử dụng.

Phần này giới thiệu các phương thức mới và cho bạn biết cách hoạt động của các phương thức đó.

Tìm nạp một địa điểm theo mã nhận dạng

Sử dụng fetchPlace() để nhận thông tin chi tiết về một địa điểm cụ thể. fetchPlace() hoạt động tương tự như getPlaceById().

Hãy làm theo các bước sau để tìm nạp một địa điểm:

  1. Gọi fetchPlace(), truyền đối tượng FetchPlaceRequest chỉ định một Địa điểm Mã nhận dạng và danh sách trường chỉ định dữ liệu Địa điểm cần trả về.

    // 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. Gọi addOnSuccessListener() để xử lý FetchPlaceResponse. Một Trả về Place kết quả.

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

Tìm nạp ảnh địa điểm

Sử dụng fetchPhoto() để chụp ảnh địa điểm. fetchPhoto() trả lại ảnh cho một địa điểm. Mẫu cho việc yêu cầu ảnh đã được đơn giản hoá. Bạn hiện có thể yêu cầu PhotoMetadata trực tiếp từ đối tượng Place; không cần yêu cầu riêng nữa. Ảnh có thể có chiều rộng hoặc chiều cao tối đa là 1600px. Hàm fetchPhoto() tương tự như getPhoto().

Hãy làm theo các bước sau để tìm nạp ảnh địa điểm:

  1. Thiết lập cuộc gọi đến fetchPlace(). Hãy nhớ đưa vào Trường PHOTO_METADATAS trong yêu cầu của bạn:

    List<Place.Field> fields = Arrays.asList(Place.Field.PHOTO_METADATAS);
    
  2. Nhận một đối tượng Địa điểm (ví dụ này sử dụng fetchPlace(), nhưng bạn cũng có thể sử dụng findCurrentPlace()):

    FetchPlaceRequest placeRequest = FetchPlaceRequest.builder(placeId, fields).build();
    
  3. Thêm OnSuccessListener để lấy siêu dữ liệu ảnh từ kết quả Place trong FetchPlaceResponse, sau đó sử dụng siêu dữ liệu ảnh thu được để lấy bitmap và văn bản thuộc tính:

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

Tìm một địa điểm từ vị trí của người dùng

Sử dụng findCurrentPlace() để tìm vị trí hiện tại của thiết bị của người dùng. findCurrentPlace() trả về danh sách PlaceLikelihood cho biết những nơi mà thiết bị của người dùng có nhiều khả năng ở đó nhất. findCurrentPlace() hoạt động tương tự như getCurrentPlace()

Hãy làm theo các bước sau để nhận vị trí hiện tại của thiết bị của người dùng:

  1. Hãy đảm bảo rằng ứng dụng của bạn yêu cầu ACCESS_FINE_LOCATION và Quyền đối với ACCESS_WIFI_STATE. Người dùng phải cấp quyền để truy cập vào vị trí hiện tại của thiết bị. Xem phần Yêu cầu ứng dụng Quyền đối với chi tiết.

  2. Tạo một FindCurrentPlaceRequest, bao gồm cả danh sách các loại dữ liệu địa điểm để lợi nhuận.

      // 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. Hãy gọi findCurrentPlace và xử lý phản hồi. Trước tiên hãy kiểm tra để xác minh rằng người dùng đã cấp quyền sử dụng thông tin vị trí của thiết bị của họ.

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

Tìm cụm từ gợi ý của tính năng tự động hoàn thành

Sử dụng findAutocompletePredictions() để trả về các gợi ý địa điểm nhằm phản hồi truy vấn tìm kiếm của người dùng. findAutocompletePredictions() hoạt động tương tự như getAutocompletePredictions()

Ví dụ sau đây cho thấy cách gọi 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());
   }
});

Mã thông báo phiên

Mã thông báo phiên sẽ nhóm các giai đoạn truy vấn và lựa chọn trong quá trình tìm kiếm của người dùng thành một phiên riêng biệt cho mục đích thanh toán. Bạn nên sử dụng mã thông báo phiên cho tất cả các phiên tự động hoàn thành. Phiên bắt đầu khi người dùng bắt đầu nhập và kết thúc khi họ chọn một địa điểm. Mỗi phiên có thể có nhiều , sau đó chọn một địa điểm. Sau khi một phiên kết thúc, mã thông báo không còn hợp lệ; ứng dụng của bạn phải tạo một mã thông báo mới cho mỗi phiên hoạt động.

Mặt nạ trường

Trong các phương thức trả về thông tin chi tiết về địa điểm, bạn phải chỉ định loại địa điểm để trả về với mỗi yêu cầu. Việc này giúp đảm bảo rằng bạn chỉ yêu cầu (và trả tiền cho) dữ liệu mà bạn sẽ thực sự sử dụng.

Để chỉ định loại dữ liệu cần trả về, hãy truyền một mảng Place.Field trong FetchPlaceRequest, như trong ví dụ sau:

// Include address, ID, and phone number.
List<Place.Field> placeFields = Arrays.asList(Place.Field.ADDRESS,
                                              Place.Field.ID,
                                              Place.Field.PHONE_NUMBER);

Bạn có thể sử dụng một hoặc nhiều trường sau đây:

  • 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

Đọc thêm về SKU Dữ liệu địa điểm.

Nội dung cập nhật về Bộ chọn địa điểm và tính năng Tự động hoàn thành

Phần này giải thích những thay đổi đối với các tiện ích Địa điểm (Bộ chọn địa điểm và Tự động hoàn thành).

Tự động hoàn thành có lập trình

Đã thực hiện các thay đổi sau đây để tự động hoàn thành:

  • PlaceAutocomplete đổi tên thành Autocomplete.
    • PlaceAutocomplete.getPlace đổi tên thành Autocomplete.getPlaceFromIntent.
    • PlaceAutocomplete.getStatus đổi tên thành Autocomplete.getStatusFromIntent.
  • PlaceAutocomplete.RESULT_ERROR đổi tên thành AutocompleteActivity.RESULT_ERROR. (cách xử lý lỗi cho mảnh tự động hoàn thành chưa thay đổi).

Bộ chọn địa điểm

Bộ chọn địa điểm đã ngừng hoạt động từ ngày 29 tháng 1 năm 2019. Đã tắt tính năng này Ngày 29 tháng 7 năm 2019 sẽ không còn nữa. Nếu bạn tiếp tục sử dụng, một thông báo lỗi. SDK mới không hỗ trợ Bộ chọn địa điểm.

Tiện ích tự động hoàn thành

Các tiện ích tự động hoàn thành đã được cập nhật:

  • Tiền tố Place đã bị xoá khỏi tất cả các lớp.
  • Thêm tuỳ chọn hỗ trợ cho mã thông báo phiên. Tiện ích này quản lý mã thông báo cho bạn tự động chạy trong nền.
  • Thêm tính năng hỗ trợ cho mặt nạ trường, cho phép bạn chọn loại địa điểm dữ liệu cần trả về sau khi người dùng đưa ra lựa chọn.

Các phần sau đây cho biết cách thêm tiện ích tự động hoàn thành vào dự án của bạn.

Nhúng một AutocompleteFragment

Để thêm một mảnh tự động hoàn thành, hãy làm theo các bước sau:

  1. Thêm một mảnh vào bố cục XML của hoạt động, như minh hoạ sau đây ví dụ:

    <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. Để thêm tiện ích tự động hoàn thành vào hoạt động, hãy làm theo các bước sau:

    • Khởi chạy Places, truyền ngữ cảnh ứng dụng và khoá API.
    • Khởi động AutocompleteSupportFragment.
    • Gọi setPlaceFields() để cho biết loại dữ liệu địa điểm mà bạn muốn để có được tài khoản.
    • Thêm PlaceSelectionListener để thực hiện tác vụ nào đó với kết quả, cũng như xử lý mọi lỗi có thể xảy ra.

    Ví dụ sau đây cho thấy cách thêm một tiện ích tự động hoàn thành vào một hoạt động:

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

Sử dụng một ý định để chạy hoạt động tự động hoàn thành

  1. Khởi chạy Places, truyền ngữ cảnh ứng dụng và khoá API
  2. Sử dụng Autocomplete.IntentBuilder để tạo ý định, truyền tham số mong muốn Chế độ PlaceAutocomplete (toàn màn hình hoặc lớp phủ). Ý định phải gọi startActivityForResult, truyền vào một mã yêu cầu xác định ý định.
  3. Ghi đè lệnh gọi lại onActivityResult để nhận địa điểm đã chọn.

Ví dụ sau đây cho bạn biết cách sử dụng một ý định để chạy tính năng tự động hoàn thành, rồi xử lý kết quả:

    /**
     * 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.
            }
        }
    }

Bộ chọn địa điểm không còn hoạt động nữa

Bộ chọn địa điểm đã ngừng hoạt động từ ngày 29 tháng 1 năm 2019. Đã tắt tính năng này Ngày 29 tháng 7 năm 2019 sẽ không còn nữa. Nếu bạn tiếp tục sử dụng, một thông báo lỗi. SDK mới không hỗ trợ Bộ chọn địa điểm.