Thông tin về lớp học lập trình này
1. Trước khi bắt đầu
Tìm hiểu cách sử dụng Nền tảng Google Maps và SDK địa điểm dành cho Android để trình bày cho người dùng của bạn danh sách các địa điểm để xác định vị trí hiện tại của họ.
Điều kiện tiên quyết
- Kỹ năng Java cơ bản
Bạn sẽ thực hiện
- Thêm bản đồ vào ứng dụng Android.
- Sử dụng quyền truy cập thông tin vị trí để xác định vị trí địa lý của người dùng.
- Tìm nạp địa điểm gần vị trí hiện tại của người dùng.
- Trình bày các địa điểm có thể cho người dùng để xác định vị trí hiện tại của họ.
Sản phẩm bạn sẽ tạo ra
Bạn tạo ứng dụng Android của mình từ đầu, nhưng bạn có thể tải mã mẫu xuống để so sánh khi gỡ lỗi. Tải mã mẫu từ GitHub hoặc nếu bạn đã thiết lập Git để sử dụng dòng lệnh, hãy nhập những thông tin sau:
git clone https://github.com/googlecodelabs/current-place-picker-android.git
Nếu bạn gặp phải bất kỳ vấn đề nào (lỗi mã, lỗi ngữ pháp, từ ngữ không rõ ràng hoặc các vấn đề khác) khi tham gia lớp học lập trình này, vui lòng báo cáo vấn đề qua đường liên kết Báo cáo lỗi ở góc dưới bên trái của lớp học lập trình.
2. Bắt đầu
Trước khi bắt đầu lớp học lập trình này, bạn cần thiết lập các mục sau:
Android Studio
Tải Android Studio xuống từ https://developer.android.com/studio.
Nếu bạn đã có Android Studio, hãy nhớ cài đặt phiên bản mới nhất bằng cách nhấp vào Android Studio > Kiểm tra bản cập nhật....
Phòng thí nghiệm này được viết bằng Android Studio 3.4.
SDK Android
Trong Android Studio, bạn có thể định cấu hình các SDK mong muốn bằng Trình quản lý SDK. Phòng thí nghiệm này sử dụng SDK Android Q.
- Trên màn hình chào mừng của Android Studio, nhấp vào Định cấu hình > Trình quản lý SDK.
- Chọn hộp đánh dấu SDK mà bạn muốn, sau đó nhấp vào Áp dụng.
Nếu bạn chưa có SDK, thì quá trình này sẽ bắt đầu tải SDK xuống máy của bạn.
Dịch vụ Google Play
Từ trình quản lý SDK, bạn cũng cần cài đặt Dịch vụ Google Play.
- Nhấp vào thẻ Công cụ SDK rồi chọn hộp đánh dấu Dịch vụ Google Play.
Hãy cập nhật nếu trạng thái là Đã có bản cập nhật.
3. Chuẩn bị trình mô phỏng
Để chạy ứng dụng này, bạn có thể kết nối thiết bị của riêng mình hoặc sử dụng Trình mô phỏng Android.
Nếu bạn sử dụng thiết bị của riêng mình, hãy chuyển đến phần Hướng dẫn thực về thiết bị: Cập nhật Dịch vụ Google Play ở cuối trang này.
Thêm trình mô phỏng
- Trên màn hình chào mừng của Android Studio, nhấp vào Định cấu hình > Trình quản lý thiết bị ảo Android.
Thao tác này sẽ mở hộp thoại Trình quản lý thiết bị ảo Android.
- Nhấp vào Tạo thiết bị ảo... để mở danh sách thiết bị mà bạn có thể chọn.
- Chọn một thiết bị có biểu tượng Play
trong cột Cửa hàng Play và nhấp vào Tiếp theo.
Bạn sẽ thấy một tập hợp hình ảnh hệ thống mà bạn có thể cài đặt. Nếu phần Q nhắm mục tiêu Android 9.+ (Google Play) có từ Tải xuống bên cạnh, hãy nhấp vào Tải xuống.
- Nhấp vào Tiếp theo để đặt tên cho thiết bị ảo, rồi nhấp vào Hoàn tất.
Bạn sẽ quay lại danh sách Thiết bị ảo của mình.
- Nhấp vào biểu tượng Bắt đầu
bên cạnh thiết bị mới:
Sau vài phút, trình mô phỏng sẽ mở ra.
Hướng dẫn về trình mô phỏng – cập nhật Dịch vụ Google Play
- Sau khi trình mô phỏng chạy, hãy nhấp vào biểu tượng ... trong thanh điều hướng xuất hiện**.**
Thao tác này sẽ mở hộp thoại Kiểm soát mở rộng.
- Nhấp vào Google Play trong trình đơn.
Nếu có bản cập nhật, hãy nhấp vào Cập nhật.
- Đăng nhập vào trình mô phỏng bằng Tài khoản Google.
Bạn có thể sử dụng tài khoản của mình hoặc tạo tài khoản mới mà không mất phí để tách biệt hoạt động thử nghiệm với thông tin cá nhân của mình.
Sau đó, Google Play sẽ mở ra Dịch vụ Google Play.
- Nhấp vào Cập nhật để tải phiên bản Dịch vụ Google Play mới nhất.
Nếu bạn được yêu cầu hoàn tất việc thiết lập tài khoản và thêm tùy chọn thanh toán, hãy nhấp vào Bỏ qua.
Đặt vị trí trong trình mô phỏng
- Sau khi trình mô phỏng chạy, hãy nhập "maps" vào thanh tìm kiếm trên màn hình chính để hiển thị biểu tượng ứng dụng Google Maps.
- Nhấp vào biểu tượng để mở.
Bạn sẽ thấy một bản đồ mặc định.
- Ở dưới cùng bên phải của bản đồ, hãy nhấp vào Vị trí của bạn
.
Bạn cần cấp cho điện thoại quyền sử dụng thông tin vị trí.
- Nhấp vào ... để mở trình đơn Kiểm soát mở rộng.
- Nhấp vào tab Vị trí.
- Nhập vĩ độ và kinh độ.
Hãy nhập mọi thứ bạn thích ở đây, nhưng hãy đảm bảo rằng bạn ở khu vực có nhiều địa điểm.
(Sử dụng Latitude 20.7818 và Kinh độ -156.4624 cho thị trấn Kihei trên Maui ở Hawaii để sao chép kết quả từ lớp học lập trình này.)
- Nhấp vào Gửi và bản đồ sẽ cập nhật thông tin vị trí này.
Bạn đã sẵn sàng chạy ứng dụng của mình và thử nghiệm ứng dụng dựa trên vị trí.
Hướng dẫn sử dụng thiết bị thực — cập nhật Dịch vụ Google Play
Nếu bạn đang sử dụng thiết bị Android thực, hãy làm như sau:
- Sử dụng thanh tìm kiếm trên màn hình chính để tìm kiếm và mở Dịch vụ Google Play.
- Nhấp vào Chi tiết khác.
Nếu có, hãy nhấp vào Cập nhật.
4. Tạo giao diện ứng dụng với hoạt động trên Google Maps
- Trên màn hình chào mừng của Android Studio, hãy chọn Bắt đầu dự án Android Studio mới.
- Trên thẻ Điện thoại và máy tính bảng, hãy chọn Hoạt động trên Google Maps.
Hộp thoại Định cấu hình dự án sẽ mở ra. Đây là nơi bạn đặt tên cho ứng dụng của mình và tạo gói dựa trên miền của bạn.
Dưới đây là các tùy chọn cài đặt cho một ứng dụng có tên là Địa điểm hiện tại, tương ứng với gói com.google.codelab.currentplace
.
- Chọn Java làm ngôn ngữ và chọn Sử dụng cấu phần phần mềm androidx*.
Giữ các chế độ cài đặt mặc định còn lại.
- Nhấp vào Finish (Hoàn tất).
5. Thêm các phần phụ thuộc Dịch vụ của Google vào tệp bản dựng Gradle
Để truy cập các quyền truy cập thông tin vị trí trong Android, bạn cần có API Vị trí và Nhận dạng hoạt động trên Google từ Dịch vụ Google Play. Để biết thêm thông tin về cách thêm API này và các API Dịch vụ Google Play khác, hãy xem phần Thiết lập Dịch vụ Google Play.
Dự án Android Studio thường có 2 tệp build.gradle
. Một là dành cho dự án tổng thể và một là dành cho ứng dụng. Nếu có trình khám phá Dự án Android Studio ở chế độ xem Android, bạn sẽ thấy cả hai dự án trong thư mục Gradle Scripts
. Bạn cần chỉnh sửa tệp build.gradle (Module: app)
để thêm các dịch vụ của Google.
- Thêm hai dòng vào phần
dependencies
để thêm các dịch vụ của Google cho vị trí và API địa điểm (mã mẫu trong bối cảnh).
build.gradle (Mô-đun: ứng dụng)
plugins {
id 'com.android.application'
}
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.google.codelab.currentplace"
minSdkVersion 19
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'com.google.android.gms:play-services-maps:16.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
implementation 'com.google.android.gms:play-services-location:16.0.0'
implementation 'com.google.android.libraries.places:places:1.1.0'
}
6. Bật API Google Maps Platform và nhận khóa API
Đối với bước bật sau đây , bạn cần bật SDK Maps cho Android và API địa điểm.
Thiết lập Nền tảng Google Maps
Nếu bạn chưa có tài khoản Google Cloud Platform và một dự án đã bật tính năng thanh toán, vui lòng xem hướng dẫn Bắt đầu sử dụng Google Maps Platform để tạo tài khoản thanh toán và một dự án.
- Trong Cloud Console, hãy nhấp vào trình đơn thả xuống dự án và chọn dự án mà bạn muốn sử dụng cho lớp học lập trình này.
- Bật API và SDK của Nền tảng Google Maps bắt buộc cho lớp học lập trình này trong Google Cloud Marketplace. Để làm như vậy, hãy làm theo các bước trong video này hoặc tài liệu này.
- Tạo khoá API trong trang Thông tin xác thực của Cloud Console. Bạn có thể làm theo các bước trong video này hoặc tài liệu này. Tất cả các yêu cầu gửi đến Google Maps Platform đều yêu cầu khóa API.
Sao chép khoá API mà bạn vừa tạo. Quay lại Android Studio và tìm tệp google_maps_api.xml
trong phần Android > app > res > value.
Thay thế YOUR_KEY_HERE
bằng khóa API mà bạn đã sao chép.
Ứng dụng của bạn hiện đã được định cấu hình.
7. Chỉnh sửa tệp bố cục
- Trong trình khám phá dự án, hãy mở tệp
activity_maps.xml
trong Android >app
>res
>layout
.
- Bạn sẽ thấy giao diện người dùng cơ bản mở ở bên phải màn hình, với các thẻ ở dưới cùng cho phép bạn chọn trình chỉnh sửa Thiết kế hoặc Văn bản cho bố cục của mình. Chọn Văn bản và thay thế toàn bộ nội dung của tệp bố cục bằng tiêu chí sau:
activity_maps.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:orientation="vertical">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:minHeight="?attr/actionBarSize"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:titleTextColor="@android:color/white"
android:background="@color/colorPrimary" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<fragment
android:id="@+id/map"
android:name="com.google.android.gms.maps.SupportMapFragment"
android:layout_width="match_parent"
android:layout_height="349dp"
tools:context=".MapsActivity" />
<ListView
android:id="@+id/listPlaces"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Bạn sẽ thấy giao diện người dùng như sau:
8. Thiết lập thanh ứng dụng
Để người dùng có thể nhấp vào nút khi họ muốn chọn địa điểm hiện tại của mình, hãy thêm thanh ứng dụng có biểu tượng tìm địa điểm hiện tại của người dùng và hiển thị các địa điểm có thể ở gần đó. Giao diện đó sẽ giống như sau:
Trên điện thoại, chỉ có biểu tượng hiển thị. Trên một máy tính bảng có thêm không gian, văn bản cũng được bao gồm.
Tạo biểu tượng
- Trong trình khám phá dự án, hãy nhấp vào Android và gt; app, sau đó nhấp chuột phải vào thư mục res rồi chọn New > Image Asset.
Asset Studio mở ra.
- Trong trình đơn Loại biểu tượng, hãy nhấp vào Biểu tượng thanh hành động và thanh.
- Đặt tên cho tài sản của bạn
ic_geolocate
. - Chọn Clip Art làm loại tài sản**.**
- Nhấp vào hình đồ họa bên cạnh Nghệ thuật đoạn video.
Thao tác này sẽ mở cửa sổ Chọn biểu tượng.
- Chọn một biểu tượng.
Bạn có thể sử dụng thanh tìm kiếm để tìm biểu tượng liên quan đến ý định của mình.
- Tìm kiếm
location
và chọn một biểu tượng liên quan đến vị trí.
Biểu tượng vị trí của tôi giống với biểu tượng dùng trong ứng dụng Google Maps khi người dùng muốn gắn máy ảnh vào vị trí hiện tại.
- Nhấp vào OK > Tiếp theo > Hoàn tất,rồi xác nhận có một thư mục mới có tên là
drawable
chứa các tệp biểu tượng mới của bạn.
Thêm tài nguyên chuỗi
- Trong trình khám phá dự án, hãy nhấp vào Android > app > res > values và mở tệp
strings.xml
. - Thêm các dòng sau sau
<string name="title_activity_maps">Map</string>
:
strings.xml
<string name="action_geolocate">Pick Place</string>
<string name="default_info_title">Default Location</string>
<string name="default_info_snippet">No places found, because location permission is disabled.</string>
Dòng đầu tiên được sử dụng trong thanh ứng dụng khi có khoảng trống để bao gồm nhãn văn bản bên cạnh biểu tượng. Những số khác được dùng cho các điểm đánh dấu mà bạn thêm vào bản đồ.
Bây giờ, mã trong tệp sẽ như sau:
<resources>
<string name="app_name">Current Place</string>
<string name="title_activity_maps">Map</string>
<string name="action_geolocate">Pick Place</string>
<string name="default_info_title">Default Location</string>
<string name="default_info_snippet">No places found, because location permission is disabled.</string>
</resources>
Thêm thanh ứng dụng
- Trong trình khám phá dự án, hãy nhấp vào Android và gt; app, rồi nhấp chuột phải vào thư mục
res
rồi chọn New > Directory để tạo một thư mục con mới trongapp/src/main/res
. - Đặt tên cho thư mục là
menu
. - Nhấp chuột phải vào thư mục
menu
rồi chọn New > File. - Đặt tên
menu.xml
cho tệp. - Dán mã này:
menu.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<!-- "Locate me", should appear as action button if possible -->
<item
android:id="@+id/action_geolocate"
android:icon="@drawable/ic_geolocate"
android:title="@string/action_geolocate"
app:showAsAction="always|withText" />
</menu>
Cập nhật kiểu thanh ứng dụng
- Trong trình khám phá dự án, hãy mở rộng Android >
app
>res
>values
rồi mở tệpstyles.xml
bên trong. - Trong thẻ
<style>
, hãy chỉnh sửa thuộc tính mẹ thành"Theme.AppCompat.NoActionBar"
. - Hãy lưu ý đến thuộc tính
name
mà bạn sử dụng trong bước tiếp theo.
styles.xml
<style name="AppTheme" parent="Theme.AppCompat.NoActionBar">
Cập nhật giao diện ứng dụng trong AndroidManifest.xml
- Nhấp vào Android >
app
>manifests
và mở tệpAndroidManifest.xml
. - Tìm dòng
android:theme
và chỉnh sửa hoặc xác nhận giá trị thành@style/AppTheme
.
AndroidManifest.xml
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
Bây giờ, bạn đã sẵn sàng bắt đầu lập trình!
9. Khởi chạy ứng dụng
- Trong trình khám phá dự án, hãy tìm tệp
MapsActivity.java
.
Phần này nằm trong thư mục tương ứng với gói mà bạn đã tạo cho ứng dụng của mình ở bước 1.
- Mở tệp và bạn &trong trình chỉnh sửa mã Java.
Nhập SDK địa điểm và các phần phụ thuộc khác
Thêm các dòng này ở đầu MapsActivity.java
, thay thế các câu lệnh nhập hiện có.
Các quy tắc này bao gồm các lần nhập hiện có và thêm nhiều lần nhập được sử dụng trong mã trong lớp học lập trình này.
MapsActivity.java
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import com.google.android.gms.common.api.ApiException;
import com.google.android.gms.location.FusedLocationProviderClient;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.OnMapReadyCallback;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.gms.tasks.Task;
import com.google.android.libraries.places.api.Places;
import com.google.android.libraries.places.api.model.Place;
import com.google.android.libraries.places.api.model.PlaceLikelihood;
import com.google.android.libraries.places.api.net.FindCurrentPlaceRequest;
import com.google.android.libraries.places.api.net.FindCurrentPlaceResponse;
import com.google.android.libraries.places.api.net.PlacesClient;
import java.util.Arrays;
import java.util.List;
Cập nhật chữ ký của lớp học
API Địa điểm sử dụng các thành phần AndroidX để hỗ trợ khả năng tương thích ngược. Do đó, bạn cần xác định API này để mở rộng AppCompatActivity
. Thay thế tiện ích FragmentActivity
được xác định theo mặc định cho một hoạt động trên bản đồ.
public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback {
Thêm biến lớp
Tiếp theo, hãy khai báo các biến lớp được dùng trong các phương thức lớp khác nhau. Các thành phần này bao gồm các thành phần trên giao diện người dùng và mã trạng thái. Các giá trị này phải ngay bên dưới phần khai báo biến cho GoogleMap mMap
.
// New variables for Current Place picker
private static final String TAG = "MapsActivity";
ListView lstPlaces;
private PlacesClient mPlacesClient;
private FusedLocationProviderClient mFusedLocationProviderClient;
// The geographical location where the device is currently located. That is, the last-known
// location retrieved by the Fused Location Provider.
private Location mLastKnownLocation;
// A default location (Sydney, Australia) and default zoom to use when location permission is
// not granted.
private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085);
private static final int DEFAULT_ZOOM = 15;
private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1;
private boolean mLocationPermissionGranted;
// Used for selecting the Current Place.
private static final int M_MAX_ENTRIES = 5;
private String[] mLikelyPlaceNames;
private String[] mLikelyPlaceAddresses;
private String[] mLikelyPlaceAttributions;
private LatLng[] mLikelyPlaceLatLngs;
Cập nhật phương thức onCreate
Bạn cần cập nhật phương thức onCreate
để xử lý quyền của người dùng trong thời gian chạy đối với các dịch vụ vị trí, thiết lập các thành phần giao diện người dùng và tạo ứng dụng API địa điểm.
Thêm các dòng mã sau liên quan đến thanh công cụ hành động, thiết lập chế độ xem và ứng dụng Địa điểm vào cuối phương thức onCreate()
hiện tại.
MapsActivity.java onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_maps);
// Obtain the SupportMapFragment and get notified when the map is ready to be used.
SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
.findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
//
// PASTE THE LINES BELOW THIS COMMENT
//
// Set up the action toolbar
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
// Set up the views
lstPlaces = (ListView) findViewById(R.id.listPlaces);
// Initialize the Places client
String apiKey = getString(R.string.google_maps_key);
Places.initialize(getApplicationContext(), apiKey);
mPlacesClient = Places.createClient(this);
mFusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
}
Thêm mã cho trình đơn thanh ứng dụng
Hai phương thức này thêm trình đơn thanh ứng dụng (với một mục duy nhất, biểu tượng Chọn địa điểm) và xử lý việc người dùng nhấp vào biểu tượng.
Hãy sao chép hai phương thức này vào tệp của bạn sau phương thức onCreate
.
MapsActivity.java onCreateOptionsMenu() và onOptionsItemSelected()
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_geolocate:
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Present the current place picker
// pickCurrentPlace();
return true;
default:
// If we got here, the user's action was not recognized.
// Invoke the superclass to handle it.
return super.onOptionsItemSelected(item);
}
}
Thử nghiệm
- Từ Android Studio, nhấp vào Chạy hoặc Chạy trình đơn > Chạy ‘ứng dụng\39;.
- Bạn được yêu cầu chọn mục tiêu triển khai. Trình mô phỏng đang chạy sẽ xuất hiện trong danh sách này. Hãy chọn biến thể này và Android Studio sẽ triển khai ứng dụng tới trình mô phỏng cho bạn.
Sau vài phút, ứng dụng sẽ chạy. Bạn thấy bản đồ tập trung ở Sydney, Úc, với một nút và danh sách địa điểm chưa xuất hiện.
Tâm điểm của bản đồ sẽ không di chuyển đến vị trí của người dùng trừ khi bạn yêu cầu quyền truy cập vị trí của thiết bị.
10. Yêu cầu và xử lý quyền truy cập thông tin vị trí
Yêu cầu quyền truy cập thông tin vị trí sau khi bản đồ sẵn sàng
- Xác định một phương thức có tên là
getLocationPermission
yêu cầu quyền của người dùng.
Dán mã này bên dưới phương thức onOptionsSelected
mà bạn vừa tạo.
MapsActivity.java getLocationPermission()
private void getLocationPermission() {
/*
* Request location permission, so that we can get the location of the
* device. The result of the permission request is handled by a callback,
* onRequestPermissionsResult.
*/
mLocationPermissionGranted = false;
if (ContextCompat.checkSelfPermission(this.getApplicationContext(),
android.Manifest.permission.ACCESS_FINE_LOCATION)
== PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
} else {
ActivityCompat.requestPermissions(this,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
}
}
- Thêm hai dòng vào cuối phương thức
onMapReady
hiện tại để bật các tùy chọn điều khiển thu phóng và yêu cầu người dùng cấp quyền truy cập thông tin vị trí.
MapsActivity.java onMapReady()
@Override
public void onMapReady(GoogleMap googleMap) {
mMap = googleMap;
// Add a marker in Sydney and move the camera
LatLng sydney = new LatLng(-34, 151);
mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney"));
mMap.moveCamera(CameraUpdateFactory.newLatLng(sydney));
//
// PASTE THE LINES BELOW THIS COMMENT
//
// Enable the zoom controls for the map
mMap.getUiSettings().setZoomControlsEnabled(true);
// Prompt the user for permission.
getLocationPermission();
}
Xử lý kết quả từ quyền được yêu cầu
Khi người dùng trả lời hộp thoại yêu cầu, lệnh gọi lại này sẽ do Android gọi.
Dán mã này sau phương thức getLocationPermission()
:
MapsActivity.java onRequestPermissionResult()
/**
* Handles the result of the request for location permissions
*/
@Override
public void onRequestPermissionsResult(int requestCode,
@NonNull String permissions[],
@NonNull int[] grantResults) {
mLocationPermissionGranted = false;
switch (requestCode) {
case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
mLocationPermissionGranted = true;
}
}
}
}
11. Tìm vị trí hiện tại và tìm nạp địa điểm có thể
Khi người dùng nhấp vào Chọn địa điểm trong thanh ứng dụng, ứng dụng sẽ gọi phương thức pickCurrentPlace()
để gọi phương thức getDeviceLocation()
mà bạn đã xác định trước đó. Phương thức getDeviceLocation
gọi một phương thức khác, getCurrentPlaceLikelihoods,
sau khi truy xuất vị trí mới nhất của thiết bị.
Gọi API FindCurrentPlace và xử lý phản hồi
getCurrentPlaceLikelihoods
tạo một findCurrentPlaceRequest
và gọi tác vụ API Địa điểm findCurrentPlace
. Nếu việc cần làm đó thành công, hệ thống sẽ trả về thông báo findCurrentPlaceResponse
chứa danh sách đối tượng placeLikelihood
. Mỗi mục trong số này có một số thuộc tính, bao gồm tên và địa chỉ của địa điểm, và xác suất có khả năng bạn đang ở địa điểm đó (giá trị kép từ 0 đến 1). Phương thức này xử lý phản hồi bằng cách tạo danh sách thông tin chi tiết về địa điểm từ placeLikelihoods
.
Mã này sẽ lặp lại qua 5 địa điểm có nhiều khả năng nhất và thêm những địa điểm có khả năng thu thập dữ liệu lớn hơn 0 vào danh sách mà sau đó mã này sẽ hiển thị. Nếu bạn muốn hiển thị nhiều hơn hoặc ít hơn 5, hãy chỉnh sửa hằng số M_MAX_ENTRIES
.
Dán mã này sau phương thức onMapReady
.
MapsActivity.java getCurrentPlaceLikeliturs()
private void getCurrentPlaceLikelihoods() {
// Use fields to define the data types to return.
List<Place.Field> placeFields = Arrays.asList(Place.Field.NAME, Place.Field.ADDRESS,
Place.Field.LAT_LNG);
// Get the likely places - that is, the businesses and other points of interest that
// are the best match for the device's current location.
@SuppressWarnings("MissingPermission") final FindCurrentPlaceRequest request =
FindCurrentPlaceRequest.builder(placeFields).build();
Task<FindCurrentPlaceResponse> placeResponse = mPlacesClient.findCurrentPlace(request);
placeResponse.addOnCompleteListener(this,
new OnCompleteListener<FindCurrentPlaceResponse>() {
@Override
public void onComplete(@NonNull Task<FindCurrentPlaceResponse> task) {
if (task.isSuccessful()) {
FindCurrentPlaceResponse response = task.getResult();
// Set the count, handling cases where less than 5 entries are returned.
int count;
if (response.getPlaceLikelihoods().size() < M_MAX_ENTRIES) {
count = response.getPlaceLikelihoods().size();
} else {
count = M_MAX_ENTRIES;
}
int i = 0;
mLikelyPlaceNames = new String[count];
mLikelyPlaceAddresses = new String[count];
mLikelyPlaceAttributions = new String[count];
mLikelyPlaceLatLngs = new LatLng[count];
for (PlaceLikelihood placeLikelihood : response.getPlaceLikelihoods()) {
Place currPlace = placeLikelihood.getPlace();
mLikelyPlaceNames[i] = currPlace.getName();
mLikelyPlaceAddresses[i] = currPlace.getAddress();
mLikelyPlaceAttributions[i] = (currPlace.getAttributions() == null) ?
null : TextUtils.join(" ", currPlace.getAttributions());
mLikelyPlaceLatLngs[i] = currPlace.getLatLng();
String currLatLng = (mLikelyPlaceLatLngs[i] == null) ?
"" : mLikelyPlaceLatLngs[i].toString();
Log.i(TAG, String.format("Place " + currPlace.getName()
+ " has likelihood: " + placeLikelihood.getLikelihood()
+ " at " + currLatLng));
i++;
if (i > (count - 1)) {
break;
}
}
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Populate the ListView
// fillPlacesList();
} else {
Exception exception = task.getException();
if (exception instanceof ApiException) {
ApiException apiException = (ApiException) exception;
Log.e(TAG, "Place not found: " + apiException.getStatusCode());
}
}
}
});
}
Di chuyển máy ảnh bản đồ đến vị trí hiện tại của thiết bị
Nếu người dùng cấp quyền, ứng dụng sẽ tìm nạp vị trí mới nhất của người dùng và di chuyển máy ảnh để căn giữa vị trí đó.
Nếu người dùng từ chối cấp quyền, ứng dụng sẽ chỉ di chuyển máy ảnh đến vị trí mặc định được xác định giữa các hằng số ở đầu trang này (trong mã mẫu, đó là Sydney, Úc).
Dán mã này sau phương thức getPlaceLikelihoods()
:
MapsActivity.java getDeviceLocation()
private void getDeviceLocation() {
/*
* Get the best and most recent location of the device, which may be null in rare
* cases when a location is not available.
*/
try {
if (mLocationPermissionGranted) {
Task<Location> locationResult = mFusedLocationProviderClient.getLastLocation();
locationResult.addOnCompleteListener(this, new OnCompleteListener<Location>() {
@Override
public void onComplete(@NonNull Task<Location> task) {
if (task.isSuccessful()) {
// Set the map's camera position to the current location of the device.
mLastKnownLocation = task.getResult();
Log.d(TAG, "Latitude: " + mLastKnownLocation.getLatitude());
Log.d(TAG, "Longitude: " + mLastKnownLocation.getLongitude());
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(
new LatLng(mLastKnownLocation.getLatitude(),
mLastKnownLocation.getLongitude()), DEFAULT_ZOOM));
} else {
Log.d(TAG, "Current location is null. Using defaults.");
Log.e(TAG, "Exception: %s", task.getException());
mMap.moveCamera(CameraUpdateFactory
.newLatLngZoom(mDefaultLocation, DEFAULT_ZOOM));
}
getCurrentPlaceLikelihoods();
}
});
}
} catch (SecurityException e) {
Log.e("Exception: %s", e.getMessage());
}
}
Kiểm tra quyền truy cập thông tin vị trí khi người dùng nhấp vào Chọn địa điểm
Khi người dùng nhấn vào Chọn địa điểm, phương thức này sẽ kiểm tra quyền truy cập thông tin vị trí và nhắc người dùng cấp quyền nếu địa điểm đó chưa được cấp.
Nếu người dùng đã cấp quyền, thì phương thức này sẽ gọi getDeviceLocation
để bắt đầu quy trình nhận các địa điểm có khả năng hiện có.
- Thêm phương thức này sau
getDeviceLocation()
:
MapsActivity.java pickCurrentPlace()
private void pickCurrentPlace() {
if (mMap == null) {
return;
}
if (mLocationPermissionGranted) {
getDeviceLocation();
} else {
// The user has not granted permission.
Log.i(TAG, "The user did not grant location permission.");
// Add a default marker, because the user hasn't selected a place.
mMap.addMarker(new MarkerOptions()
.title(getString(R.string.default_info_title))
.position(mDefaultLocation)
.snippet(getString(R.string.default_info_snippet)));
// Prompt the user for permission.
getLocationPermission();
}
}
- Giờ đây,
pickCurrentPlace
đã được xác định, hãy tìm dòng trongonOptionsItemSelected()
gọipickCurrentPlace
và hủy nhận xét.
MapsActivity.java onOptionItemSelected()
case R.id.action_geolocate:
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Present the Current Place picker
pickCurrentPlace();
return true;
Thử nghiệm
Nếu bạn chạy ứng dụng ngay bây giờ và nhấn vào Chọn địa điểm, ứng dụng sẽ nhắc nhắc quyền truy cập thông tin vị trí.
- Nếu bạn cho phép, tùy chọn đó sẽ được lưu và bạn sẽ không nhận được lời nhắc. Nếu từ chối cấp quyền thì bạn sẽ được nhắc vào lần tiếp theo nhấn vào nút.
- Mặc dù
getPlaceLikelihoods
đã tìm nạp những địa điểm hiện có, nhưngListView
chưa hiển thị những địa điểm đó. Trong Android Studio, bạn có thể nhấp vào ⌘6 để kiểm tra nhật ký trong Logcat cho các câu lệnh được gắn thẻ MapsActivity để xác minh rằng các phương pháp mới của bạn đang hoạt động đúng. - Nếu bạn đã cấp quyền thì nhật ký bao gồm một câu lệnh cho
Latitude:
và một câu lệnh choLongitude:
cho biết vị trí phát hiện được của thiết bị. Nếu bạn đã sử dụng Google Maps và trình đơn mở rộng của trình mô phỏng trước đó để chỉ định vị trí cho trình mô phỏng, thì các câu lệnh này sẽ hiển thị vị trí đó. - Nếu cuộc gọi đến
findCurrentPlace
được thực hiện thành công, nhật ký bao gồm 5 tuyên bố in tên và vị trí của 5 địa điểm có nhiều khả năng nhất.
12. Điền bộ chọn Địa điểm hiện tại
Thiết lập trình xử lý cho các địa điểm đã chọn
Hãy suy nghĩ về những gì chúng ta muốn xảy ra khi người dùng nhấp vào một mục trong ListView
. Để xác nhận lựa chọn của người dùng về địa điểm hiện tại của họ, bạn có thể thêm một điểm đánh dấu vào bản đồ tại địa điểm đó. Nếu người dùng nhấp vào điểm đánh dấu đó, một cửa sổ thông tin sẽ bật lên hiển thị tên và địa chỉ của địa điểm.
Dán trình xử lý lượt nhấp này sau phương thức pickCurrentPlace
.
MapsActivity.java ListClickedHandler
private AdapterView.OnItemClickListener listClickedHandler = new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView parent, View v, int position, long id) {
// position will give us the index of which place was selected in the array
LatLng markerLatLng = mLikelyPlaceLatLngs[position];
String markerSnippet = mLikelyPlaceAddresses[position];
if (mLikelyPlaceAttributions[position] != null) {
markerSnippet = markerSnippet + "\n" + mLikelyPlaceAttributions[position];
}
// Add a marker for the selected place, with an info window
// showing information about that place.
mMap.addMarker(new MarkerOptions()
.title(mLikelyPlaceNames[position])
.position(markerLatLng)
.snippet(markerSnippet));
// Position the map's camera at the location of the marker.
mMap.moveCamera(CameraUpdateFactory.newLatLng(markerLatLng));
}
};
Điền Chế độ xem danh sách
Bây giờ, bạn đã có danh sách các địa điểm có nhiều khả năng nhất mà người dùng hiện đang ghé thăm, bạn có thể hiển thị các tùy chọn đó cho người dùng trong ListView
. bạn cũng có thể đặt trình xử lý lượt nhấp ListView
để sử dụng trình xử lý lượt nhấp mà bạn vừa xác định.
Dán phương thức này sau trình xử lý lượt nhấp:
MapsActivity.javafill PlacesList()
private void fillPlacesList() {
// Set up an ArrayAdapter to convert likely places into TextViews to populate the ListView
ArrayAdapter<String> placesAdapter =
new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mLikelyPlaceNames);
lstPlaces.setAdapter(placesAdapter);
lstPlaces.setOnItemClickListener(listClickedHandler);
}
Giờ đây, fillPlacesList
đã được xác định, hãy tìm đường kẻ ở cuối findPlaceLikelihoods
gọi fillPlacesList
và hủy nhận xét.
MapsActivity.javafillPlaceLikeliancys()
// COMMENTED OUT UNTIL WE DEFINE THE METHOD
// Populate the ListView
fillPlacesList();
Đó là tất cả mã cần thiết cho bộ chọn Địa điểm hiện tại!
13. Chạy ứng dụng
Thử chọn địa điểm
- Chạy lại ứng dụng.
Lần này khi bạn nhấn vào Chọn địa điểm, ứng dụng sẽ điền sẵn các danh sách có địa điểm được đặt tên gần với vị trí. Gần vị trí này trên Maui là những địa điểm như Ululani\39;s Hawaiian Shave Ice và Sugar Beach Bake Shop. Vì có nhiều địa điểm rất gần với tọa độ vị trí, nên đây là danh sách các địa điểm mà bạn có thể ghé thăm.
- Nhấp vào tên địa điểm trong
ListView
.
Bạn sẽ thấy một điểm đánh dấu được thêm vào bản đồ.
- Nhấn vào điểm đánh dấu.
Bạn có thể xem Thông tin chi tiết về địa điểm.
Thử nghiệm một vị trí khác
Nếu bạn muốn thay đổi vị trí của mình và đang sử dụng trình mô phỏng, vị trí thiết bị sẽ không tự động cập nhật khi bạn cập nhật tọa độ vị trí trong trình đơn mở rộng của trình mô phỏng.
Để thực hiện việc này, hãy làm theo các bước sau để sử dụng ứng dụng Google Maps gốc để buộc cập nhật vị trí của trình mô phỏng:
- Mở Google Maps.
- Nhấn vào ... > Vị trí để thay đổi vĩ độ và kinh độ thành các tọa độ mới, sau đó nhấn vào Gửi.
- Ví dụ: bạn có thể sử dụng Vĩ độ: 49.2768 và Kinh độ: -123.1142 để đặt vị trí thành trung tâm thành phố Vancouver, Canada.
- Xác minh rằng Google Maps đã căn cứ vào tọa độ mới của bạn. Bạn có thể cần nhấn vào nút Vị trí của tôi trong ứng dụng Google Maps để yêu cầu tính năng gần đây.
- Quay lại ứng dụng Địa điểm hiện tại và nhấn vào Chọn địa điểm để tải bản đồ trên tọa độ mới và xem danh sách mới về các địa điểm hiện có.
Và vậy là bạn đã xong! Bạn đã tạo một ứng dụng đơn giản để kiểm tra các địa điểm tại vị trí hiện tại và cung cấp cho bạn khả năng địa điểm nào bạn đang ở. Chúc bạn học vui!
Bây giờ, hãy tiếp tục và chạy ứng dụng có các sửa đổi bạn đã thực hiện để hoàn tất bước thưởng này!
14. Các bước tiếp theo
Để ngăn chặn hành vi lấy cắp khóa API, bạn cần bảo mật để chỉ ứng dụng Android của bạn mới có thể sử dụng khóa này. Nếu không bị hạn chế, bất kỳ ai có khóa của bạn có thể sử dụng khóa đó để gọi API Google Maps Platform và khiến bạn bị tính phí.
Nhận chứng chỉ SHA-1 của bạn
Bạn cần vào lúc khác khi hạn chế khoá API. Sau đây là nhóm hướng dẫn về cách lấy chứng chỉ gỡ lỗi.
Đối với Linux hoặc macOS, hãy mở cửa sổ dòng lệnh rồi nhập các thông tin sau:
keytool -list -v -keystore ~/.android/debug.keystore -alias androiddebugkey -storepass android -keypass android
Đối với Windows Vista và Windows 7, hãy chạy lệnh sau:
keytool -list -v -keystore "%USERPROFILE%\.android\debug.keystore" -alias androiddebugkey -storepass android -keypass android
Bạn sẽ thấy kết quả xuất ra có dạng như sau:
Alias name: androiddebugkey Creation date: Jan 01, 2013 Entry type: PrivateKeyEntry Certificate chain length: 1 Certificate[1]: Owner: CN=Android Debug, O=Android, C=US Issuer: CN=Android Debug, O=Android, C=US Serial number: 4aa9b300 Valid from: Mon Jan 01 08:04:04 UTC 2013 until: Mon Jan 01 18:04:04 PST 2033 Certificate fingerprints: MD5: AE:9F:95:D0:A6:86:89:BC:A8:70:BA:34:FF:6A:AC:F9 SHA1: BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75 Signature algorithm name: SHA1withRSA Version: 3
Dòng bắt đầu SHA1 chứa chứng chỉ SHA-1 của chứng chỉ. Vân tay là chuỗi 20 số thập lục phân có 2 chữ số phân cách bằng dấu hai chấm.
Khi bạn đã sẵn sàng phát hành ứng dụng, hãy sử dụng hướng dẫn trong tài liệu này để truy xuất chứng chỉ phát hành của bạn.
Thêm các quy định hạn chế cho khoá API
- Trong Cloud Console, hãy chuyển đến API & Dịch vụ > Thông tin xác thực.
Khóa mà bạn đã sử dụng cho ứng dụng này phải được liệt kê trong Khóa API.
- Hãy nhấp vào
để chỉnh sửa các chế độ cài đặt quan trọng.
- Trên trang khóa API, sau khi Hạn chế khóa, hãy đặt Hạn chế ứng dụng bằng cách làm như sau:
- Chọn Ứng dụng Android rồi làm theo hướng dẫn.
- Nhấp vào Thêm mặt hàng.
- Nhập tên gói và vân tay số của chứng chỉ SHA-1 (truy xuất trong phần trước).
Ví dụ:
com.google.codelab.currentplace
BB:0D:AC:74:D3:21:E1:43:07:71:9B:62:90:AF:A1:66:6E:44:5D:75s
- Để tăng cường bảo vệ, hãy đặt các quy định hạn chế về API bằng cách làm như sau.
- Sau khi hạn chế API, hãy chọn Hạn chế khoá.
- Chọn SDK Maps dành cho Android và API Địa điểm.
- Nhấp vào Xong rồi Lưu.
15. Xin chúc mừng
Bạn đã tạo một ứng dụng đơn giản để kiểm tra các địa điểm có nhiều khả năng nhất tại vị trí hiện tại và thêm điểm đánh dấu vào bản đồ cho địa điểm mà người dùng chọn.
Tìm hiểu thêm
- Để đẩy mạnh sự phát triển của bạn, hãy tận dụng SDK Maps cho Thư viện tiện ích Android. Các tiện ích này giúp bạn thực hiện một số công việc phổ biến nhất cho các ứng dụng bằng Google Maps Platform.
- Để xem thêm các mẫu mã minh họa hầu hết các tính năng của SDK nền tảng Google Maps dành cho Android, hãy lưu trữ bản sao cho SDK Maps dành cho Android mẫu và Bản minh họa SDK địa điểm cho Android.
- Để tìm hiểu cách xử lý các quyền đối với vị trí ba trạng thái trong Android Q, hãy hoàn thành lớp học lập trình Nhận thông tin cập nhật vị trí trong Android bằng Kotlin.