Google Place API là một trong những hàng trăm API tuyệt vời mà Google cung cấp cho nhà phát triển phần mềm, với thông tin chi tiết về hơn 100 triệu địa điểm.
Google Place API gồm có 3 công cụ: Place Picker, Place Autocomplete, Place Details:

  • Place Picker cho phép người dùng tìm kiếm các địa điểm xung quanh vị trí hiện tại của họ.
  • Place Autocomplete giúp người dùng dễ dàng nhập tên địa điểm và địa chỉ, tự động hoàn thành các truy vấn của người dùng khi họ nhập.
  • Place Detail cho phép người dùng lấy thông tin chi tiết về một địa điểm như địa chỉ, số điện thoại, trang web, hình ảnh,…

Trong khuôn khổ bài viết này ta sẽ nghiên cứu về Place Autocomplete.

Lấy API key

Nhập tên Project và click create:

  • Tạo key mới:

  • Click Restric key

  • Nhập SHA1 và tên package, sau đó lưu lại.

  • Nếu bạn phát hành ứng dụng của mình lên google play thì hãy tạo thêm key release trước khi publish nhé.

Kích hoạt Google Place API

Vẫn trên trang https://console.developers.google.com , click vào Enable API and Service.

Sau đó tìm đến Google Place API và kích hoạt, như vậy API đã sẵn sàng để sử dụng.

Giới hạn sử dụng API

Sẽ không cần quan tâm nếu mục đích của bạn chỉ là nghiên cứu tìm hiểu về Google Place API , Google Place API cho phép sử dụng free với 1000 request/24 giờ, nếu quá số lượng này ứng dụng sẽ bị crash, để có thể có số lượng request lớn hơn, ta cần trả phí để sử dụng.

Cài đặt Android Project

Sau khi đã tạo một project mới trên Android studio, mở file build.gradle để implement thư viện Google place :

implementation 'com.google.android.gms:play-services-places:11.8.0'

Trong file Manifest, ta khai báo Permission Internet :

<uses-permission android:name="android.permission.INTERNET"/>

và API key đã tạo trước đó:

<application>
  ...
  <meta-data
      android:name="com.google.android.geo.API_KEY"
      android:value="YOUR_API_KEY"/>
</application>

Tiếp theo ta sẽ thêm Autocomplete vào ứng dụng, ta có thể thực hiện theo 2 cách:

  • Thêm autocomplete widget vào ứng dụng.
  • Get place predictions programmatically.

Instantiate the Places API clients

Để có thể sử dụng Google Place API từ ứng dụng ta cần truy cập vào Places APIs. Google Place API cung cấp 2 interface chính:

  • GeoDataClient cung cấp truy cập vào cơ sở dữ liệu của Google về địa điểm địa phương và business information.
  • PlaceDetectionClient cung cấp truy cập nhanh đến vị trí hiện tại của thiết bị và cung cấp cơ hội để báo cáo vị trí của thiết bị ở một địa điểm cụ thể.
import com.google.android.gms.location.places.GeoDataClient;
import com.google.android.gms.location.places.Places;
import com.google.android.gms.location.places.PlaceDetectionClient;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

public class MainActivity extends FragmentActivity {
    protected GeoDataClient mGeoDataClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Construct a GeoDataClient.
        mGeoDataClient = Places.getGeoDataClient(this, null);

        // Construct a PlaceDetectionClient.
        mPlaceDetectionClient = Places.getPlaceDetectionClient(this, null);

        // TODO: Start using the Places API.
    }
}

Thêm autocomplete widget

Autocomplete widget là một hộp thoại tìm kiếm có chức năng tự động hoàn thành. Khi người dùng nhập các cụm từ tìm kiếm, nó sẽ hiển thị danh sách các địa điểm được dự đoán để lựa chọn. Khi người dùng thực hiện lựa chọn, một địa điểm sẽ được trả về, sau đó ứng dụng có thể sử dụng để nhận thông tin chi tiết về địa điểm đã chọn.

Có hai lựa chọn để thêm tiện ích tự động điền vào ứng dụng:

  • Nhúng một PlaceAutocompleteFragment.
  • Sử dụng intent để chạy activity autocomplete.

Nhúng một PlaceAutocompleteFragment

  • Đầu tiên, ta thêm PlaceAutocompleteFragment vào activity. Thêm đoạn code sau vào file layout:
<fragment
  android:id="@+id/place_autocomplete_fragment"
  android:layout_width="match_parent"
  android:layout_height="wrap_content"
  android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment"
  />
  • Tiếp theo thêm PlaceSelectionListener.
    PlaceSeclectionListener xử lý trả về một địa điểm phản hồi sự lựa chọn của người dùng:
PlaceAutocompleteFragment autocompleteFragment = (PlaceAutocompleteFragment)
getFragmentManager().findFragmentById(R.id.place_autocomplete_fragment);

autocompleteFragment.setOnPlaceSelectedListener(new PlaceSelectionListener() {
   @Override
   public void onPlaceSelected(Place place) {
       // TODO: Get info about the selected place.
       Log.i(TAG, "Place: " + place.getName());
   }

   @Override
   public void onError(Status status) {
       // TODO: Handle the error.
       Log.i(TAG, "An error occurred: " + status);
   }
 });

Sử dụng intent để chạy activity autocomplete.

  • Sử dụng PlaceAutocomplete.IntentBuilder để tạo một intent khởi chạy autocomplete widget:
int PLACE_AUTOCOMPLETE_REQUEST_CODE = 1;
...
try {
    Intent intent =
            new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
                    .build(this);
    startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
} catch (GooglePlayServicesRepairableException e) {
    // TODO: Handle the error.
} catch (GooglePlayServicesNotAvailableException e) {
    // TODO: Handle the error.
}

Khi sử dụng intent để chạy autocomplete widget, ta có 2 lựa chọn chế độ hiển thị widget: overlay hoặc full-screen.

Mode Overlay:

Mode Full-screen:

  • Để nhận được notification khi người dùng đã chọn một đia điểm, ta override phương thức onActivityResult(), kiểm tra request code truyền vào:
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE) {
        if (resultCode == RESULT_OK) {
            Place place = PlaceAutocomplete.getPlace(this, data);
            Log.i(TAG, "Place: " + place.getName());
        } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
            Status status = PlaceAutocomplete.getStatus(this, data);
            // TODO: Handle the error.
            Log.i(TAG, status.getStatusMessage());

        } else if (resultCode == RESULT_CANCELED) {
            // The user canceled the operation.
        }
    }
}

Giới hạn kết quả trả về

Ta có thể cài đặt autocomplete widget để giới hạn kết quả trả về, chẳng hạn trong một khu vực địa lý, hoặc trả về theo một hoặc nhiều loại địa điểm.

Giới hạn theo khu vực xác định
Để set giới hạn theo khu vực xác định ta gọi phương thức setBoundBias (), phương thức này giới hạn khu vực xác định dựa trên 2 tọa độ qua đối tượng LatLngBounds:

autocompleteFragment.setBoundsBias(new LatLngBounds(
    new LatLng(-33.880490, 151.184363),
    new LatLng(-33.858754, 151.229596)));

Lọc kết quả trả về theo loại địa điểm
Để lọc kết quả trả về theo loại địa điểm ta sử dụng AutocompleteFilter.Builder để tạo một AutocompleteFilter. goi phương thức setTypeFilter() để set kiểu địa điểm được lọc theo. Sau đó, truyền filter vào fragment:

AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
        .setTypeFilter(AutocompleteFilter.TYPE_FILTER_ADDRESS)
        .build();

autocompleteFragment.setFilter(typeFilter);

hoặc truyền vào intent:

AutocompleteFilter typeFilter = new AutocompleteFilter.Builder()
        .setTypeFilter(AutocompleteFilter.TYPE_FILTER_ADDRESS)
        .build();

Intent intent =
        new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_FULLSCREEN)
                .setFilter(typeFilter)
                .build(this);

Có các loại filter như:

  • TYPE_FILTER_NONE – Một bộ lọc rỗng; tất cả các kết quả được trả lại.

  • TYPE_FILTER_GEOCODE – Trả về chỉ các kết quả mã hóa địa lý chứ không chỉ là các doanh nghiệp. Sử dụng yêu cầu này để xác định lại kết quả khi mà vị trí được chỉ định có thể không xác định.

  • TYPE_FILTER_ADDRESS – Trả lại kết quả tự động hoàn thành với địa chỉ chính xác. Sử dụng loại này khi ta biết người dùng đang tìm kiếm một địa chỉ được chỉ định đầy đủ.

  • TYPE_FILTER_ESTABLISHMENT – Trả về chỉ những địa điểm là doanh nghiệp.

  • TYPE_FILTER_REGIONS – Chỉ trả lại những địa điểm phù hợp với một trong các loại sau:
    – Địa phương
    – Địa vị địa phương
    – Mã bưu điện
    – Quốc gia
    – Administrative_area_level_1
    – Administrative_area_level_2

  • TYPE_FILTER_CITIES – Trả về chỉ các kết quả phù hợp với địa phương hoặc administrative_area_level_3.

Get place predictions programmatically

Ta có thể custom giao diện tìm kiếm thay thế cho UI của Autocomplete Widget. Để thực hiện việc này, ứng dụng phải có dự đoán vị trí theo chương trình. Ứng dụng có thể nhận được danh sách tên địa điểm dự đoán và / hoặc địa chỉ từ dịch vụ Autocomplete bằng cách gọi GeoDataClient.getAutocompletePredictions (), truyền các thông số sau:

  • Required: Một chuỗi truy vấn có chứa text được gõ bởi người dùng.
  • Required: Đối tượng LatLngBounds, biasing kết quả đến một khu vực cụ thể được chỉ định bởi vĩ độ và kinh độ.
  • Optional: Bộ lọc Tự động hoàn thành chứa một tập hợp các loại địa điểm được sử dụng để giới hạn kết quả đến một hoặc nhiều loại địa điểm.
    Code:
Task<AutocompletePredictionBufferResponse> results =
      mGeoDataClient.getAutocompletePredictions(constraint.toString(), mBounds,
          mPlaceFilter);

API trả về một AutocompletePredictionBufferResponse trong một Task. AutocompletePredictionBufferResponse chứa một danh sách các đối tượng AutocompletePrediction đối tượng đại diện cho các vị trí dự đoán. Bộ đệm có thể để trống, nếu không có vị trí nào tương ứng với truy vấn và tiêu chí lọc.

Đối với mỗi vị trí dự đoán, ta có thể gọi các phương thức sau để lấy ra chi tiết địa điểm:

  • getFullText (CharacterStyle matchStyle) trả về full text của mô tả địa điểm. Đây là sự kết hợp của văn bản chính và phụ. Ví dụ: “Tháp Eiffel, Đại lộ Anatole Pháp, Paris, Pháp”. Ngoài ra, phương thức này cho phép làm nổi bật các phần của mô tả phù hợp với tìm kiếm với một phong cách bạn chọn, sử dụng CharacterStyle. Thông số CharacterStyle là tùy chọn. Đặt nó thành null nếu không cần bất kỳ sự nổi bật nào.
  • getPrimaryText (CharacterStyle matchStyle) trả về văn bản chính mô tả một nơi. Đây thường là tên của địa điểm. Ví dụ: “Tháp Eiffel” và “123 Pitt Street”.
  • getSecondaryText (CharacterStyle matchStyle) trả lại văn bản phụ của một mô tả địa điểm. Điều này hữu ích, ví dụ, như là một dòng thứ hai khi hiển thị dự đoán tự động hoàn thành. Ví dụ: “Đại lộ Anatole Pháp, Paris, Pháp”, và “Sydney, New South Wales”.
  • getPlaceId () trả về ID vị trí của vị trí dự đoán. ID nơi là bộ nhận dạng văn bản xác định duy nhất một địa điểm mà bạn có thể sử dụng để lấy đối tượng Địa điểm một lần nữa sau đó.
  • getPlaceTypes () trả về danh sách các loại địa điểm liên kết với địa điểm này.

Tài liệu tham khảo

https://developers.google.com/places/android-api/start