0_AsLR2XCzLLgJ8NWt

ทำแผนที่ Google Maps API จากโปรแกรม Android Studio

บทความที่ผ่านมา คงเอาใจสายมนุษย์โปรแกรมเมอร์กันไปพอหอมปากหอมคอกันแล้ว วันนี้ขอมานำเสนอ How to การทำแผนที่ในโปรแกรม Android Studio ให้ผู้มือใหม่ที่กำลังเริ่มทำ รับรองว่าง่าย ๆ และสามารถเอาไปใช้ได้จริง!!

มาเรียนรู้ และทำความเข้าใจกันก่อนว่าในการทำแผนที่ในแอปพลิเคชันต้องมีขั้นตอนอะไรกันบ้าง ไปดูกันเลยย

Android Studio คืออะไร ?

Android Studio เป็น IDE Tool จาก Google ไว้พัฒนา Android สำหรับ Android Studio เป็น IDE Tools ล่าสุดจาก Google ไว้พัฒนาโปรแกรม Android โดยเฉพาะ โดยพัฒนาจากแนวคิดพื้นฐานมาจาก IntelliJ IDEA คล้าย ๆ กับการทำงานของ Eclipse และ Android ADT Plugin

ติดตั้ง Android Studio

สามารถดาวน์โหลด Android Studio เวอร์ชั่นล่าสุดได้จากลิงก์นี้เลย (https://developer.android.com/studio/index.html)

ก่อนจะเริ่มเขียนโปรแกรมนั้นเราต้องเตรียมโปรเจกต์ของเราให้พร้อมสำหรับการใช้งาน Google Maps API เสียก่อน เนื่องจากทาง Google เองไม่ได้เปิดให้ใช้งานแบบไม่ได้ระบุที่มาที่ไปว่าเอาไปใช้ในแอปพลิเคชันไหน และที่สำคัญต้องกำหนดด้วยว่าจะใช้งาน API ใดบ้าง

1.สร้างโปรเจกต์ใน Android Studio ตั้งชื่อว่า Basic Google Map เลือกประเภทโปรเจกต์เป็น No Activity

2.เข้าไปที่ https://console.developers.google.com/ และสร้างโครงการ (หากยังไม่มี) ถ้ายังไม่มีบัญชีของ Google ให้สมัครและ Login เสียก่อน จากนั้นตั้งชื่อโครงการตามที่เราต้องการ (องค์กรจะเลือกหรือไม่เลือกก็ได้)

3.จากนั้นจะเจอหน้าไลบรารีเพื่อค้นหา API ที่เราต้องการจะใช้งาน ให้ค้นโดยใช้คีย์เวิร์ด “android” จากนั้นเลือกที่ “Google Maps Android API

กด “เปิดใช้” หลังจากนั้นจะมีปุ่มด้านขวาให้สร้าง “ข้อมูลรับรอง” กดสร้างเพื่อให้ได้ข้อมูลคีย์ จาดนั้นให้ copy คีย์​ API นี้ไว้แล้วกดเสร็จสิ้น

4.ในภาคต่อไปเราต้องใช้งาน API อื่น ๆ ที่เกี่ยวข้องอีก 3 ตัวคือ Google Places API for Android, Google Maps Directions API และ Google Maps Geocoding API ให้ทำการเปิดใช้โดยการค้นหาและกด “เปิดใช้” เช่นเดิม

กลับมาที่โปรเจกต์ของเรา

5.ให้สร้าง Activity ขึ้นมาใหม่โดยใช้แทมเพลตเป็น Google Maps Activity

เมื่อสร้างแล้วเจ้าตัว Android Studio ของเราจะทำการสร้างไฟล์ชื่อว่า google_map_api.xml ให้เราอัตโนมัติ ให้นำคีย์ API ที่เรา copy ไว้ในขั้นตอนก่อนหน้านี้มาใส่ในไฟล์นี้

*ถ้าหากเราเข้าไปดูที่ไฟล์ build.gradle (Module: app) จะเห็นได้ว่า Android Studio นั้นเพิ่ม dependency ของ google play service ที่มี Google Maps API ใส่ไว้ให้เราเรียบร้อยโดยไม่ต้องเพิ่มเอง


พร้อมแล้วสำหรับการเขียนโปรแกรมโดยใช้งาน Google Maps API

  1. แสดงแผนที่บนหน้าจอ (Map)

เปิดไฟล์​ MapsActivity.java และ activity_maps.xml จะเห็นว่า Android Studio ได้ใส่โค้ดสำหรับแสดงแผนที่ไว้ให้เราเรียบร้อยแล้ว

อธิบายเพิ่มเติม

SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
        .findFragmentById(R.id.map);
mapFragment.getMapAsync(this);

คือการไป find Fragment จาก xml เหมือนกับการ findViewById() นั่นเอง เมื่อได้ mapFragment แล้วจึงสั่ง getMapAsync() ซึ่งจะทำให้method 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));
}

ซึ่งคลาส MapsActivity นั้นได้ implements อินเตอร์เฟสชื่อว่า OnMapReadyCallback ซึ่งบังคับให้เรา Override method ชื่อว่า “onMapReady()”นั่นเอง โดยใน method นี้จะทำการปักหมุด (Marker) ที่ Latitude -34 Longitude 151 และใส่ title ชื่อ “Marker in Sydney”

และสุดท้ายสั่งให้แผนที่ขยับมุมมองไปที่ตำแหน่ง Latitude, Longitude เดียวกันโดยใช้คำสั่ง “mMap.moveCamera()

ทดสอบกันดูดีกว่า

*แนะนำให้ใช้ โปรแกรม Nox มารันแอปพลิเคชันก็ดูได้ จะได้ไม่เสียเวลาในการรันบนเครื่องจริง หรือจะรันบนโทรศัพท์ของเราเลยก็ยังได้

ถ้ารันเสร็จแล้วจะออกมาได้หน้าตาแบบนี้ แต่จะเห็นว่ายังเป็นแผนที่ ที่ยังไกลมาก และไม่ได้มีความใกล้เคียงกับสถานที่ตามที่เราต้องการ เป็นเพราะว่า ขั้นตอนต่อไปคือเพิ่มโค้ดในการส่งค่าจุดละติจูด ลองติจูด ของทั้งสองที่ไปให้ Google Map นั่นเอง

1.เพิ่มปุ่มนำทางข้างล่างจะเขียนว่า “นำทาง” หรืออะไรก็ได้ อีกปุ่มนึงก่อน เพื่อจะได้กดเรียกแผนที่ Google Map ให้ขึ้นมาแสดง

กลับไปที่โปรเจกต์ของเรา เปิดคลาส MapsActivity.java แล้วเพิ่ม method ชื่อ openGoogleMap() ดังนี้

private void openGoogleMap(LatLng src, LatLng dest) {
    String url = "http://maps.google.com/maps?saddr="+src.latitude+","+src.longitude+"&daddr="+dest.latitude+","+dest.longitude+"&mode=driving";
    Uri gmmIntentUri = Uri.parse(url);
    Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
    mapIntent.setPackage("com.google.android.apps.maps");
    startActivity(mapIntent);
}

อธิบายเพิ่มเติม

เราสามารถเปิดแอพ Google Maps โดยการ startActivity() แต่เราต้องกำหนดใน method Intent.setPackage() โดยใส่เป็นชื่อแพคเกจ หรือ ไอดีของแอพที่เราต้องการให้เปิด โดยที่แอป ๆ นั้นจะต้องอนุญาติให้เราเปิด และส่งข้อมูลไว้ด้วย

หลังจากนั้นทำการ handle event ให้กับปุ่ม “นำทาง” ของเราด้วยการเรียกใช้งาน method openGoogleMap() ซึ่งจะได้โค้ดโดยรวมดังนี้

public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, View.OnClickListener {    private GoogleMap mMap;    Button buttonNormal;
    Button buttonSatellite;
    Button buttonHybrid;
    Button buttonNavigate;
    SupportMapFragment mapFragment;    final LatLng sydney = new LatLng(-34, 151);
    final LatLng myHome = new LatLng(-34.1, 150);    @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.
        mapFragment = (SupportMapFragment) getSupportFragmentManager()
                .findFragmentById(R.id.map);
        mapFragment.getMapAsync(this);        buttonNormal = (Button) findViewById(R.id.buttonNormal);
        buttonSatellite = (Button) findViewById(R.id.buttonSatellite);
        buttonHybrid = (Button) findViewById(R.id.buttonHybrid);
        buttonNavigate = (Button) findViewById(R.id.buttonNavigate);        buttonNormal.setOnClickListener(this);
        buttonSatellite.setOnClickListener(this);
        buttonHybrid.setOnClickListener(this);
        buttonNavigate.setOnClickListener(this);
    }    @Override
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.buttonNavigate:
                openGoogleMap(myHome, sydney);
                break;
            case R.id.buttonSatellite:
                mMap.setMapType(GoogleMap.MAP_TYPE_SATELLITE);
                break;
            case R.id.buttonHybrid:
                mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
                break;
            default:
                mMap.setMapType(GoogleMap.MAP_TYPE_NORMAL);
                break;
        }        mapFragment.getMapAsync(this);
    }    private void openGoogleMap(LatLng src, LatLng dest) {
        String url = "http://maps.google.com/maps?saddr="+src.latitude+","+src.longitude+"&daddr="+dest.latitude+","+dest.longitude+"&mode=driving";
        Uri gmmIntentUri = Uri.parse(url);
        Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri);
        mapIntent.setPackage("com.google.android.apps.maps");
        startActivity(mapIntent);
    }    @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;        // Add a marker in Sydney and move the camera        mMap.addMarker(new MarkerOptions().position(sydney).title("Marker in Sydney").snippet("Hello Sydney"));
        mMap.addMarker(new MarkerOptions().position(myHome).title("My Home").snippet("Hello my home"));        LatLng center = new LatLng(-34.05, 150.5);
        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(center, 8));        mMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter() {
            @Override
            // Return null here, so that getInfoContents() is called next.
            public View getInfoWindow(Marker arg0) {
                return null;
            }            @Override
            public View getInfoContents(Marker marker) {
                // Inflate the layouts for the info window, title and snippet.
                View infoWindow = getLayoutInflater().inflate(R.layout.custom_info_contents, null);
                TextView title = ((TextView) infoWindow.findViewById(R.id.textViewName));
                title.setText(marker.getTitle());
                TextView snippet = ((TextView) infoWindow.findViewById(R.id.textViewSnippet));
                snippet.setText(marker.getSnippet());                ImageView imageView = (ImageView) infoWindow.findViewById(R.id.imageView);
                imageView.setImageResource(R.drawable.ic_city);
                if ("My Home".equals(marker.getTitle())) {
                    imageView.setImageResource(R.drawable.ic_home);
                }                return infoWindow;
            }
        });        try {
            boolean success = googleMap.setMapStyle(
                    MapStyleOptions.loadRawResourceStyle(
                            this, R.raw.style_json));            if (!success) {
                Log.e("test", "Style parsing failed.");
            }
        } catch (Resources.NotFoundException e) {
            Log.e("test", "Can't find style. Error: ", e);
        }        mMap.addPolyline(new PolylineOptions().geodesic(true)
                .add(sydney)  // Sydney
                .add(myHome));// My Home
    }
}

เสร็จแล้วลองมารันโปรแกรมดูใหม่อีกครั้ง จะได้แบบนี้

เมื่อพอกดปุ่มนำทางจะปรากฎขึ้นมาให้เราแบบนี้

ถ้าป็นแอปพลิเคชันท่องเที่ยวในแอปพลิเคชันของเรามีหลายสถานที่ ที่ต้องมีการนำทาง สามารถทำในตัวอย่างขั้นตอนด้านบนได้เลย ส่วนการเพิ่มละติจูด , ลองติจูด ให้เราไปเพิ่มในฐานข้อมูล (Database) ของเราได้เลย โดยโค้ดจะทำการดึงค่านั้น เเล้วตัว Goole maps จะแสดงผลตามที่เราได้ใส่ข้อมูลไว้ในฐานข้อมูลเลยล่ะ

เห็นว่าการทำแผนที่สำหรับใช้งานบน Android นั้นไม่ใช่เรื่องยาก เพียงแต่ต้องทำความเข้าใจในส่วนของการทำงานของ Android Studio และส่วนของการออกแบบ GUI (Constrain Layout, Liner Layout, และอื่น ๆ)

อ่านมาถึงตรงนี้แล้วต้องขอบคุณมาก ๆ ที่เข้ามาอ่านกันถึงตรงนี้ หวังว่าจะสนุกไปกับบทความ และได้ความรู้สักนิดก็ยังดี ในส่วนด้านโค้ดนั้น สามารถนำไปปรับใช้กับงานจริงได้ ทุกขั้นตอนเมื่อเกิด Error หรือ Bug สิ่งที่ควรทำคือเราต้องทำการเรียนรู้การใช้งานของแต่ละส่วน เเล้วค่อยปรับไปในแต่ละงาน จะได้สะดวกกับงานของเรามากขึ้น

ใครอยากดาวน์โหลด source code สามารถกดดาวน์โหลดได้ ที่นี่