Hướng dẫn sử dụng Google Maps Android API
Công ty Vĩnh Cửu tuyển dụng lập trình viên Java

1- Cài đặt Google Map API

Trước hết phải đảm bảo rằng Android Studio của bạn đã cài đặt Google APIGoogle Play Service. Bạn cần phải kiểm tra và cài đặt nếu cần.
Kiểm tra xem Google API đã được cài đặt chưa.
Các gói "Google *** System Image" cũng cần được cài đặt.
Tiếp tục bạn cần kéo thanh cuộn xuống để kiểm tra Google Play Service đã được cài đặt chưa.

2- Sử dụng Google System Image cho thiết bị mô phỏng

Sau khi cài đặt xong các gói thư viện như ở bước trên, nếu bạn chạy ứng dụng Google Map trên thiết bị mô phỏng bạn cần cấu hình sử dụng Google System Image.

3- Đăng ký Google Map API

Ứng dụng của bạn có thành phần bản đồ, dữ liệu bản đồ nằm tại trung tâm dữ liệu của Google, vì vậy ứng dụng của bạn liên tục truy xuất dữ liệu bản đồ thông qua một dịch vụ.
Mặc dù dữ liệu bản đồ Google được cung cấp miễn phí tuy nhiên không phải việc truy xuất nó một cách tùy tiện, bạn cần có một API Key, nó giống như một giấy giới thiệu (Credentials) để truy cập dữ liệu bản đồ.
Bạn cần phải đăng ký một Google Map API Key, việc này hoàn toàn miễn phí. Bạn có thể xem tại:

4- Ví dụ với Google Map

Android Studio hỗ trợ bạn tạo một project với Google Map một cách dễ dàng và nhanh chóng:
Tuy nhiên ở đây tôi sẽ tạo một project từ đầu sau đó kéo thả Google Map vào màn hình, có lẽ điều đó là tốt hơn nếu bạn muốn hiểu biết cặn kẽ các vấn đề. OK, trên Android Studio tạo mới một project có tên MyGoogleMap.
Một project rỗng đã được tạo ra:

MapFragment & SupportMapFragment:

MapFragment & SupportMapFragment là các fragment được xây dựng sẵn, nó có sẵn thành phần GoogleMap, bạn cần phải kéo thả một trong 2 fragment này vào màn hình thiết kế của bạn. SupportMapFragment có nhiều tính năng được hỗ trợ hơn.
Nếu trên cửa sổ lựa chọn Fragments không có thành phần MapFragmentSupportMapFragment. Bạn cần phải cấu hình file build.gradle (Module:app):
Bạn cần một vài cấu hình cho file build.gradle (Module:app):
Thêm vào thư viện phụ thuộc:
compile 'com.google.android.gms:play-services:8.1.0'
Chú ý rằng: Mặc dù Google Play Services có phiên bản 8.3.0 nhưng chưa chắc rằng bạn sẽ chạy được nó vì một vài lý do, vì vậy bạn có thể sử dụng phiên bản 8.1.0, hãy sử dụng phiên bản này để test trước khi bạn có thể sử dụng các phiên bản mới hơn.
Sau khi khai báo thư viện phụ thuộc, bạn cần phải biên dịch lại toàn bộ project.
Trở lại màn hình thiết kế. Bạn có 2 lựa chọn sử dụng MapFragment hoặc SupportMapFragment. Chúng đều là các fragment có thành phần GoogleMap. Trong đó SupportMapFragment có nhiều tính năng được hỗ trợ hơn. Chọn SupportMapFragment.
Kéo cho Fragment chiếm đầy màn hình.
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="org.o7planning.mygooglemap.MainActivity">

    <fragment
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:name="com.google.android.gms.maps.SupportMapFragment"
        android:id="@+id/fragment"
        android:layout_alignParentRight="true"
        android:layout_alignParentEnd="true"
        android:layout_alignParentTop="true"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentBottom="true" />

</RelativeLayout>
MainActivity.java
package org.o7planning.mygooglemap;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

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

Google Map API Key

GoogleMap trên Android sẽ sử dụng một dịch vụ để lấy dữ liệu bản đồ từ Google và hiển thị chúng. Ở phần trên bạn đã đăng ký một Google Map API Key, bạn cần phải khai báo Key này trong AndroidManifest.xml.
<meta-data
    android:name="com.google.android.maps.v2.API_KEY"
    android:value="Your API KEY" />
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.o7planning.mygooglemap">


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- Enter your GoogleMap Android API Key -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="Your ANDROID API Key" />


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
Bây giờ bạn có thể chạy ứng dụng:

5- Tùy biến Google MAP

Chúng ta tiếp tục với ví dụ ở trên. Bạn cần code ứng dụng để lấy được vị trí hiện thời của bạn và sử dụng Marker để dánh dấu vị trí trên bản đồ.
Bạn cần một vài cấu hình trên AndroidManifest.xml cho phép xem vị trí, kết nối mạng, và kế nối Internet. Thêm vào AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.o7planning.mygooglemap">

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

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">

        <!-- Enter your GoogleMap Android API Key -->
        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="Your Android API Key" />


        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>
MainActivity.java
package org.o7planning.mygooglemap;

import android.Manifest;
import android.app.ProgressDialog;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

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.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.Marker;
import com.google.android.gms.maps.model.MarkerOptions;

public class MainActivity extends AppCompatActivity implements LocationListener {

   private GoogleMap myMap;
   private ProgressDialog myProgress;

   private static final String MYTAG = "MYTAG";
 
   // Mã yêu cầu uhỏi người dùng cho phép xem vị trí hiện tại của họ (***).
   // Giá trị mã 8bit (value < 256).
   public static final int REQUEST_ID_ACCESS_COURSE_FINE_LOCATION = 100;


   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
 
       // Tạo Progress Bar
       myProgress = new ProgressDialog(this);
       myProgress.setTitle("Map Loading ...");
       myProgress.setMessage("Please wait...");
       myProgress.setCancelable(true);
 
       // Hiển thị Progress Bar
       myProgress.show();


       SupportMapFragment mapFragment
               = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);

 
       // Sét đặt sự kiện thời điểm GoogleMap đã sẵn sàng.
       mapFragment.getMapAsync(new OnMapReadyCallback() {

           @Override
           public void onMapReady(GoogleMap googleMap) {
               onMyMapReady(googleMap);
           }
       });

   }

   private void onMyMapReady(GoogleMap googleMap) {
 
       // Lấy đối tượng Google Map ra:
       myMap = googleMap;
 
       // Thiết lập sự kiện đã tải Map thành công
       myMap.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {

           @Override
           public void onMapLoaded() {
 
               // Đã tải thành công thì tắt Dialog Progress đi
               myProgress.dismiss();

               // Hiển thị vị trí người dùng.
               askPermissionsAndShowMyLocation();
           }
       });
       myMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
       myMap.getUiSettings().setZoomControlsEnabled(true);
       myMap.setMyLocationEnabled(true);
   }


   private void askPermissionsAndShowMyLocation() {

 
       // Với API >= 23, bạn phải hỏi người dùng cho phép xem vị trí của họ.
       if (Build.VERSION.SDK_INT >= 23) {
           int accessCoarsePermission
                   = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION);
           int accessFinePermission
                   = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);


           if (accessCoarsePermission != PackageManager.PERMISSION_GRANTED
                   || accessFinePermission != PackageManager.PERMISSION_GRANTED) {
 
               // Các quyền cần người dùng cho phép.
               String[] permissions = new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                       Manifest.permission.ACCESS_FINE_LOCATION};
       
               // Hiển thị một Dialog hỏi người dùng cho phép các quyền trên.
               ActivityCompat.requestPermissions(this, permissions,
                       REQUEST_ID_ACCESS_COURSE_FINE_LOCATION);

               return;
           }
       }
 
       // Hiển thị vị trí hiện thời trên bản đồ.
       this.showMyLocation();
   }
 
 
   // Khi người dùng trả lời yêu cầu cấp quyền (cho phép hoặc từ chối).
   @Override
   public void onRequestPermissionsResult(int requestCode,
                                          String permissions[], int[] grantResults) {

       super.onRequestPermissionsResult(requestCode, permissions, grantResults);
       //
       switch (requestCode) {
           case REQUEST_ID_ACCESS_COURSE_FINE_LOCATION: {

         
               // Chú ý: Nếu yêu cầu bị bỏ qua, mảng kết quả là rỗng.
               if (grantResults.length > 1
                       && grantResults[0] == PackageManager.PERMISSION_GRANTED
                       && grantResults[1] == PackageManager.PERMISSION_GRANTED) {

                   Toast.makeText(this, "Permission granted!", Toast.LENGTH_LONG).show();
 
                   // Hiển thị vị trí hiện thời trên bản đồ.
                   this.showMyLocation();
               }
               // Hủy bỏ hoặc từ chối.
               else {
                   Toast.makeText(this, "Permission denied!", Toast.LENGTH_LONG).show();
               }
               break;
           }
       }
   }
 
   // Tìm một nhà cung cấp vị trị hiện thời đang được mở.
   private String getEnabledLocationProvider() {
       LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

 
       // Tiêu chí để tìm một nhà cung cấp vị trí.
       Criteria criteria = new Criteria();
 
       // Tìm một nhà cung vị trí hiện thời tốt nhất theo tiêu chí trên.
       // ==> "gps", "network",...
       String bestProvider = locationManager.getBestProvider(criteria, true);

       boolean enabled = locationManager.isProviderEnabled(bestProvider);

       if (!enabled) {
           Toast.makeText(this, "No location provider enabled!", Toast.LENGTH_LONG).show();
           Log.i(MYTAG, "No location provider enabled!");
           return null;
       }
       return bestProvider;
   }
 
   // Chỉ gọi phương thức này khi đã có quyền xem vị trí người dùng.
   private void showMyLocation() {

       LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

       String locationProvider = this.getEnabledLocationProvider();

       if (locationProvider == null) {
           return;
       }

       // Millisecond
       final long MIN_TIME_BW_UPDATES = 1000;
       // Met
       final float MIN_DISTANCE_CHANGE_FOR_UPDATES = 1;

       Location myLocation = null;
       try {
 
           // Đoạn code nay cần người dùng cho phép (Hỏi ở trên ***).
           locationManager.requestLocationUpdates(
                   locationProvider,
                   MIN_TIME_BW_UPDATES,
                   MIN_DISTANCE_CHANGE_FOR_UPDATES, (LocationListener) this);
 
           // Lấy ra vị trí.
           myLocation = locationManager
                   .getLastKnownLocation(locationProvider);
       } 
       // Với Android API >= 23 phải catch SecurityException.
       catch (SecurityException e) {
           Toast.makeText(this, "Show My Location Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
           Log.e(MYTAG, "Show My Location Error:" + e.getMessage());
           e.printStackTrace();
           return;
       }

       if (myLocation != null) {

           LatLng latLng = new LatLng(myLocation.getLatitude(), myLocation.getLongitude());
           myMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 13));

           CameraPosition cameraPosition = new CameraPosition.Builder()
                   .target(latLng)             // Sets the center of the map to location user
                   .zoom(15)                   // Sets the zoom
                   .bearing(90)                // Sets the orientation of the camera to east
                   .tilt(40)                   // Sets the tilt of the camera to 30 degrees
                   .build();                   // Creates a CameraPosition from the builder
           myMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
 
           // Thêm Marker cho Map:
           MarkerOptions option = new MarkerOptions();
           option.title("My Location");
           option.snippet("....");
           option.position(latLng);
           Marker currentMarker = myMap.addMarker(option);
           currentMarker.showInfoWindow();
       } else {
           Toast.makeText(this, "Location not found!", Toast.LENGTH_LONG).show();
           Log.i(MYTAG, "Location not found");
       }


   }


   @Override
   public void onLocationChanged(Location location) {

   }

   @Override
   public void onStatusChanged(String provider, int status, Bundle extras) {

   }

   @Override
   public void onProviderEnabled(String provider) {

   }

   @Override
   public void onProviderDisabled(String provider) {

   }

}
Chạy ứng dụng của bạn:
Nếu bạn chạy ứng dụng GoogleMap trên thiết bị mô phỏng và locationManager.getLastKnownLocation luôn trả về null. Bạn cần fix lỗi này theo hướng dẫn tại phụ lục phía dưới đây:
-
Nếu người dùng đã cho phép một số quyền cho ứng dụng, trong lần chạy ứng dụng lần sau Android sẽ không yêu cầu người dùng cấp quyền đó nữa. Bạn có thể cấu hình để loại bỏ những quyền đã cấp cho ứng dụng. Xem hướng dẫn tại:

6- Phụ lục: Fix lỗi không tìm thấy vị trí

Trong một số tình huống không tìm thấy vị trí khi bạn đang làm việc với thiết bị mô phỏng, có thể nguyên nhân do telnet lỗi, bạn cần fix lỗi này.

Bước 1:

Đảm bảo rằng "Telnet Client" đã được mở.

Bước 2:

Chạy ứng dụng Google Map của bạn trên thiết bị mô phỏng.

Bước 3:

5554 là cổng của thiết bị mô  phỏng. Trên CMD gõ lệnh:
telnet localhost 5554
Nhập tiếp lệnh:
geo fix 12 45
Không tắt cửa sổ mô phỏng, tắt ứng dụng bản đồ ( MyGoogleMap), và mở lại ứng dụng này trên điện thoại mô phỏng.