Thursday, December 19, 2019

Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2

Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2
Aplikasi Pencarian Tempat Terdekat dengan Google Maps
السَّلاَمُ عَلَيْكُمْ وَرَحْمَةُ اللهِ وَبَرَكَاتُه sobat 48😁. Kali ini saya akan membagikan sebuah artikel yang membahas tentang Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2 menggunakan Android Studio. Mungkin sudah ada beberapa yang membagikan tutorial serupa, tetapi hanya untuk pencarian Masjid (Masjid Detector) atau pencarian Rumah Sakit saja. Tapi untuk yang saya buat kali ini ada 10 Tempat yang bisa kalian temukan dalam radius 5KM (5 Kilometer). Selain itu, lokasi yang muncul bisa kalian klik dan arahkan ke aplikasi Google Maps.

Sebelum memulai ke langkah-langkah untuk membuat aplikasi ini, ada baiknya kalian buat terlebih dahulu API KEY pada Google Cloud Platform. Login dengan akun Google kalian lalu buka menu Console, pilih API & Layanan. Setelah itu kalian pilih menu AKTIFKAN API DAN LAYANAN. Kemudian aktifkan API KEY Maps dan Place.
Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2
Google Cloud Platform
Jika kalian ingin SOURCE CODE sample aplikasi ini, silahkan download di GITHUB saya DISINI. Tetapi jika kalian ingin tahu cara mengaplikasikannya, silahkan lanjut baca artikel ini sampai selesai.

Untuk kalian yang ingin mencoba membuat aplikasi ini dengan tutorial versi video, berikut saya berikan Videonya:

Jangan lupa subscribe Channel Youtube saya juga ya Azhar Rivaldi, karena disana ada banyak tutorial-tutorial untuk membuat aplikasi lainnya. Oke langsung saja tanpa basa-basi lagi kita langsung ke langkah pertama :

1. Buat project baru di Android Studio dengan cara klik File ⇒ Project Baru. Ketika diminta untuk memilih Default Activity, pilih Empty Activity dan klik next. Untuk minSDK, disini saya set API 21 ya.

2. Tambahkan library Google Play Service di build.gradle :


dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.cardview:cardview:1.0.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test:runner:1.2.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'com.google.android.gms:play-services-maps:17.0.0'
}

3. Ubah MainActivity.java dan activity_main.xml menjadi seperti ini :


package com.azhar.mapdirection;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.pm.PackageManager;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ProgressBar;
import android.widget.Spinner;

import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

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

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;

public class MainActivity extends AppCompatActivity implements LocationListener {

    GoogleMap mGoogleMap;
    ProgressBar pbMap;
    Spinner spWisata;
    String [] sWisata = {"mosque", "restaurant", "atm", "bank", "school"
            , "hospital", "laundry", "university", "post_office", "police"};
    String xWisata;

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

        spWisata.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
            public void onItemSelected(AdapterView parent, View view, int pos, long id) {
                Object itemDB = parent.getItemAtPosition(pos);
                xWisata = itemDB.toString();
                SupportMapFragment fragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.fMap);
                fragment.getMapAsync(new OnMapReadyCallback() {
                    @Override
                    public void onMapReady(GoogleMap googleMap) {
                        mGoogleMap = googleMap;
                        initMap();
                    }
                });
                startProg();
            }

            public void onNothingSelected(AdapterView parent) { }
        });
    }

    private void setID(){
        pbMap = findViewById(R.id.pbMap);
        spWisata = findViewById(R.id.spWisata);
        ArrayAdapter adpWisata = new ArrayAdapter(this, android.R.layout.simple_spinner_item, sWisata);
        adpWisata.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        spWisata.setAdapter(adpWisata);
    }

    private void stopProg() {
        pbMap.setVisibility(View.GONE);
    }

    private void startProg() {
        pbMap.setVisibility(View.VISIBLE);
    }

    private void initMap() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED &&
                ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 115);
            return;
        }

        if (mGoogleMap != null) {
            startProg();
            mGoogleMap.setMyLocationEnabled(true);

            LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            Criteria criteria = new Criteria();
            String provider = locationManager.getBestProvider(criteria, true);
            Location location = locationManager.getLastKnownLocation(provider);

            if (location != null) {
                onLocationChanged(location);
            } else
                stopProg();
            locationManager.requestLocationUpdates(provider, 20000, 0, this);
        }
    }

    @Override
    public void onLocationChanged(Location location) {
        double mLatitude = location.getLatitude();
        double mLongitude = location.getLongitude();
        LatLng latLng = new LatLng(mLatitude, mLongitude);
        mGoogleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));
        mGoogleMap.animateCamera(CameraUpdateFactory.zoomTo(12));

        String sb = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?" +
                "location=" + mLatitude + "," + mLongitude +
                "&radius=20000" +
                "&types=" + xWisata +
                "&key=" + getResources().getString(R.string.google_maps_key);
        new MainActivity.PlacesTask().execute(sb);
        stopProg();
    }

    @SuppressLint("StaticFieldLeak")
    private class PlacesTask extends AsyncTask {
        @Override
        protected String doInBackground(String... url) {
            String data = null;
            try {
                data = downloadUrl(url[0]);
            } catch (Exception e) {
                stopProg();
                e.printStackTrace();
            }
            return data;
        }

        @Override
        protected void onPostExecute(String result) {
            new MainActivity.ParserTask().execute(result);
        }
    }

    private String downloadUrl(String strUrl) {
        String data = "";
        InputStream iStream;
        HttpURLConnection urlConnection;
        try {
            URL url = new URL(strUrl);
            urlConnection = (HttpURLConnection) url.openConnection();
            urlConnection.connect();

            iStream = urlConnection.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(iStream));
            StringBuilder sb = new StringBuilder();

            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }

            data = sb.toString();
            br.close();
            iStream.close();
            urlConnection.disconnect();
        } catch (Exception e) {
            e.printStackTrace();
        }

        return data;
    }

    @SuppressLint("StaticFieldLeak")
    private class ParserTask extends AsyncTask>> {
        JSONObject jObject;
        @Override
        protected List> doInBackground(String... jsonData) {
            List> places = null;
            ParserPlace parserPlace = new ParserPlace();
            try {
                jObject = new JSONObject(jsonData[0]);
                places = parserPlace.parse(jObject);
            } catch (Exception e) {
                stopProg();
                e.printStackTrace();
            }
            return places;
        }

        @Override
        protected void onPostExecute(List> list) {
            mGoogleMap.clear();
            for (int i = 0; i < list.size(); i++) {
                MarkerOptions markerOptions = new MarkerOptions();
                HashMap hmPlace = list.get(i);
                BitmapDescriptor pinDrop = BitmapDescriptorFactory.fromResource(R.drawable.ic_pin);

                double lat = Double.parseDouble(hmPlace.get("lat"));
                double lng = Double.parseDouble(hmPlace.get("lng"));
                String nama = hmPlace.get("place_name");
                String namaJln = hmPlace.get("vicinity");
                LatLng latLng = new LatLng(lat, lng);

                markerOptions.icon(pinDrop);
                markerOptions.position(latLng);
                markerOptions.title(nama + " : " + namaJln);
                mGoogleMap.addMarker(markerOptions);
            }
            stopProg();
        }
    }

    @Override
    public void onStatusChanged(String s, int i, Bundle bundle) { }
    @Override
    public void onProviderEnabled(String s) { }
    @Override
    public void onProviderDisabled(String s) { }

}



<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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">

    <RelativeLayout
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <fragment
            android:id="@+id/fMap"
            class="com.google.android.gms.maps.SupportMapFragment"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_above="@+id/cvWisata"/>

        <androidx.cardview.widget.CardView
            android:id="@+id/cvWisata"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignParentBottom="true"
            android:layout_margin="20dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:orientation="vertical"
                android:padding="5dp">

                <TextView
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginBottom="5dp"
                    android:text="Tempat Wisata"
                    android:textColor="@android:color/black"
                    android:textSize="14sp" />

                <Spinner
                    android:id="@+id/spWisata"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:textSize="10sp" />

            </LinearLayout>

        </androidx.cardview.widget.CardView>

    </RelativeLayout>


    <ProgressBar
        android:id="@+id/pbMap"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_centerHorizontal="true"
        android:visibility="gone"
        android:layout_gravity="center" />

</androidx.coordinatorlayout.widget.CoordinatorLayout>

3. Ubah isi Android Manifest.xml menjadi seperti ini :



<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.azhar.mapdirection">

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

    <application
        android:usesCleartextTraffic="true"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:largeHeap="true"
        android:theme="@style/AppTheme"
        tools:ignore="AllowBackup,GoogleAppIndexingWarning,UnusedAttribute">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <meta-data
            android:name="com.google.android.maps.v2.API_KEY"
            android:value="@string/google_maps_key" />

        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />

    </application>

</manifest>

4. Terakhir buat ParserPlace.java untuk Generate JSON Place :


package com.azhar.mapdirection;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class ParserPlace {

    public List> parse(JSONObject jObject) {

        JSONArray jPlaces = null;
        try {
            jPlaces = jObject.getJSONArray("results");
        } catch (JSONException e) {
            e.printStackTrace();
        }
        return getPlaces(jPlaces);
    }

    private List> getPlaces(JSONArray jPlaces) {
        int placesCount = jPlaces.length();
        List> placesList = new ArrayList>();
        HashMap place = null;

        for (int i = 0; i < placesCount; i++) {
            try {
                place = getPlace((JSONObject) jPlaces.get(i));
                placesList.add(place);

            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        return placesList;
    }

    private HashMap getPlace(JSONObject jPlace) {

        HashMap place = new HashMap();
        String placeName = "-NA-";
        String vicinity = "-NA-";
        String latitude = "";
        String longitude = "";

        try {
            // extract nama
            if (!jPlace.isNull("name")) {
                placeName = jPlace.getString("name");
            }

            // extract nama jalan
            if (!jPlace.isNull("vicinity")) {
                vicinity = jPlace.getString("vicinity");
            }

            latitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lat");
            longitude = jPlace.getJSONObject("geometry").getJSONObject("location").getString("lng");

            place.put("place_name", placeName);
            place.put("vicinity", vicinity);
            place.put("lat", latitude);
            place.put("lng", longitude);

        } catch (JSONException e) {
            e.printStackTrace();
        }
        return place;
    }

}

5. Selesai dan kalian Run. Jika kalian mengikuti langkah-langkah diatas dengan baik, pasti aplikasi yang kalian buat akan berjalan sebagaimana mestinya. Namun jika mengalami Error, silahkan berikan komentar dan kita diskusikan bersama.

Untuk hasilnya seperti berikut :
Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2
Aplikasi Pencarian Tempat Terdekat
Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2
Aplikasi Pencarian Tempat Terdekat
Demikian informasi yang saya bagikan untuk kalian. Jangan lupa bagikan artikel ini ke teman-teman kalian agar ikut membaca Tutorial Membuat Aplikasi Pencarian Tempat Terdekat dengan Google Maps API V2 ini. Subscribe juga blog Rivaldi 48 ini agar kalian mendapatkan notifikasi saat Admin update artikel terbaru. Semoga kalian lebih nyaman dan mudah dalam mengakses Blog Rivaldi 48 dimanapun kalian berada. Terima Kasih. Follow Instagram Admin @azhardvls_

51 comments

  1. file php nya diupload gak mas ?

    ReplyDelete
  2. bang bisa bantu dengan video tdk? saya beneran awam dan agak bingung kalau dengan penjelasan tulisan

    ReplyDelete
  3. kok eror ya bang (ERROR: The processing instruction target matching "[xX][mM][lL]" is not allowed.)

    ReplyDelete
  4. kalau import project dari eclipse, trouble saya selalu di method getmap nya itu gimana yaa?
    udah dipakein onmapreadycallback tetep gamau, udah tambah modul xml google maps api pake api key nya juga gamau

    ReplyDelete
    Replies
    1. maaf saya bukan user eclips gan, jadi saya kurang tahu..

      Delete
    2. gan, saya sudah jalanain project tempat pelayanan kesehatannya yang full kotlin itu..
      masalah sudah saya solve satu persatu, nah masalah yang terakhir pas mau didebug ke hape selalu error duplicat class itu kenapa ya gan..

      Delete
    3. saya kurang tahu gan, coba cek sourcenya ada yg typo mungkin

      Delete
  5. saya sudah follow instagram nya mas, di acc dong :D

    ReplyDelete
  6. mau tanya dong mas com.google.android.gms.version yang value nya diambil dari mana ya kodenya itu

    ReplyDelete
    Replies
    1. biasakan baca artikelnya pelan2 ya. itu harus import library. di awal langakahnya sudah saya kasih tau

      Delete
  7. Replies
    1. itu ada di source codenya, link ada di paragraf ketiga sebelum video

      Delete
  8. padahal udah jelas di string / android manifest

    ReplyDelete
  9. bang gua udah coba tapi lokasi nya kadang muncul kadang nga bang, kenapa yaa?

    ReplyDelete
    Replies
    1. kayaknya dari source codenya gan, nanti saya perbaiki ya

      Delete
    2. Di yang mananya yak bang? Biar saya mau perbaiki juga ini aplikasi yang udah saya bikin ini. Mohon respon nya bang

      Delete
  10. Bang mau nanya, pas di run kok blank aja ya bang mapnya itu gimana solusinya bang?

    ReplyDelete
    Replies
    1. lah kamu udah bikin api key belum buat di android manifestnya?

      Delete
  11. kalo diberi backend user management gimana gan jadi usernya bisa nambah lokasi baru dengan validasi admin

    ReplyDelete
  12. mas ini pake kotlin yaa bukan java?

    ReplyDelete
  13. Bang, saat mau mencari bank, ATM dll. Kok gak muncul ya lokasinya?

    ReplyDelete
  14. bang pas mencet mosque ko ga muncul apa-apa ya ? sama aja kya ga mencet

    ReplyDelete
    Replies
    1. ya di debug, jalan apa ngga fungsi spinnernya. udah bikin api key apa belum

      Delete
  15. Terimakasih kak atas artikel gis nya
    Perkenalkan nama saya sofian sabudin dari kampus ISB atma luhur.

    ReplyDelete
  16. bang mau nanya kenapa muncul Cannot parse result path string:

    ReplyDelete
  17. bang mau tanya ini pake google maps api yg versi lama ya?

    ReplyDelete
  18. Kak mau tanya. Saya udah coba projectnya, dirun udah muncul maps sama spinner. Tapi waktu milih salah satu spinner ngga muncul lokasinya. Itu salahnya dimana ya, Kak?

    ReplyDelete
  19. bang aku error di "app:layout_behavior" itu gimana ya?
    mohon pencerahannya

    ReplyDelete
  20. Bng maaf itu source yg digithub, file activity_main.xml nya kok error yah? Mohon bantuannya 🙏🙏

    ReplyDelete
  21. logcatnya eror gini itu kenapa ya gan pahal apinya udah semua
    E/libprocessgroup: set_timerslack_ns write failed: Operation not permitted

    ReplyDelete
  22. Bang tolong di bantu bang aplikasinya berjalan lancar tapi waktu kita pilih spinernya mislakan atm gitu lokasi atmnya gak muncul di map. trus keterangan runing errornya kek gini "E/libprocessgroup: set_timerslack_ns write failed: Operation not permitted"

    ReplyDelete

Silahkan tinggalkan komentar jika Anda punya saran, kritik, atau pertanyaan seputar topik pembahasan. Gunakan bahasa yang bijak dan santun. Terima Kasih.
EmoticonEmoticon