Aplikasi Pencarian Tempat Terdekat dengan 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.
Google Cloud Platform |
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 :
Aplikasi Pencarian Tempat Terdekat |
Aplikasi Pencarian Tempat Terdekat |
file php nya diupload gak mas ?
ReplyDeleteini gak pakai file php gan
Deletebang bisa bantu dengan video tdk? saya beneran awam dan agak bingung kalau dengan penjelasan tulisan
ReplyDeletebingungnya dimana?
Deletekok eror ya bang (ERROR: The processing instruction target matching "[xX][mM][lL]" is not allowed.)
ReplyDeletecek lagi xmlnya, itu ada yg typo
Deletekalau import project dari eclipse, trouble saya selalu di method getmap nya itu gimana yaa?
ReplyDeleteudah dipakein onmapreadycallback tetep gamau, udah tambah modul xml google maps api pake api key nya juga gamau
maaf saya bukan user eclips gan, jadi saya kurang tahu..
Deletegan, saya sudah jalanain project tempat pelayanan kesehatannya yang full kotlin itu..
Deletemasalah sudah saya solve satu persatu, nah masalah yang terakhir pas mau didebug ke hape selalu error duplicat class itu kenapa ya gan..
saya kurang tahu gan, coba cek sourcenya ada yg typo mungkin
Deletesaya sudah follow instagram nya mas, di acc dong :D
ReplyDeleteanjay
Deletemau tanya dong mas com.google.android.gms.version yang value nya diambil dari mana ya kodenya itu
ReplyDeletebiasakan baca artikelnya pelan2 ya. itu harus import library. di awal langakahnya sudah saya kasih tau
Deletegan ic_pin nya dimana ya?
ReplyDeleteitu ada di source codenya, link ada di paragraf ketiga sebelum video
Deletepadahal udah jelas di string / android manifest
ReplyDeletebang gua udah coba tapi lokasi nya kadang muncul kadang nga bang, kenapa yaa?
ReplyDeletekayaknya dari source codenya gan, nanti saya perbaiki ya
DeleteDi yang mananya yak bang? Biar saya mau perbaiki juga ini aplikasi yang udah saya bikin ini. Mohon respon nya bang
DeleteBang mau nanya, pas di run kok blank aja ya bang mapnya itu gimana solusinya bang?
ReplyDeletelah kamu udah bikin api key belum buat di android manifestnya?
Deletekalo diberi backend user management gimana gan jadi usernya bisa nambah lokasi baru dengan validasi admin
ReplyDeletepake gps tracking itu
Deletegimana gan punya referensinya nggak ?
Deletedi github banyak gan.. search aja gps tracking
Deletewkwkk
Deletemas ini pake kotlin yaa bukan java?
ReplyDeleteitu kan ada source codenya-_-
DeleteBang, saat mau mencari bank, ATM dll. Kok gak muncul ya lokasinya?
ReplyDeleteudah bikin api key?
DeleteUdah bang. Tapi saat cari bank, RS, dll kok gak bisa ya?.
Deletesama bang ane juga
Deletemohon bantuannya
bang pas mencet mosque ko ga muncul apa-apa ya ? sama aja kya ga mencet
ReplyDeleteya di debug, jalan apa ngga fungsi spinnernya. udah bikin api key apa belum
DeleteTerimakasih kak atas artikel gis nya
ReplyDeletePerkenalkan nama saya sofian sabudin dari kampus ISB atma luhur.
mantap..
Deletebang mau nanya kenapa muncul Cannot parse result path string:
ReplyDeleteapi keynya udah bikin?
Deletebang mau tanya ini pake google maps api yg versi lama ya?
ReplyDeleteudah saya perbarui kok
DeleteKak 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?
ReplyDeletelokasi di hp kamu aktif apa ngga?
Deletebang aku error di "app:layout_behavior" itu gimana ya?
ReplyDeletemohon pencerahannya
biasakan new project jangan copas
DeleteBng maaf itu source yg digithub, file activity_main.xml nya kok error yah? Mohon bantuannya 🙏🙏
ReplyDeletebiasakan new project jangan copas
Deletelogcatnya eror gini itu kenapa ya gan pahal apinya udah semua
ReplyDeleteE/libprocessgroup: set_timerslack_ns write failed: Operation not permitted
di debug
DeleteBang 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"
ReplyDeletepermission lokasi udah nyala?
Delete