Pemanfaatan Google Maps dan Google Directions sebagai penunjuk jalan
Oke kali ini saya mau cerita mengenai sebuah aplikasi yang saya buat dalam waktu tidak terlalu lama, kenapa saya buat aplikasi ini, tujuannya adalah untuk membantu saya menemukan lokasi wisata yang ingin saya tuju, kemarin waktu libur imlek saya berencana untuk keluar dari rutinitas sehari-hari(ngoding, tidur, main dota) dengan mengunjungi lokasi wisata yang ada disekitaran jogja terutama di gunung kidul, bosen kalo mesti ke parangtritis lagi,
jadilah ditetapkan,, “Yuk pantai, gunung kidul”.

Destinasinya sudah ditetapkan, kami akan ke salah satu pantai yang ada digunung kidul yaitu pantai Sadranan. Masalah lain muncul, tanya ke temen yang mau diajakin tahu jalannya atau tidak, dengan polos dan lugunya bilang, “gak ngerti… T.T (muka mewek)”, dan dijawab lagi dengan polos “owh (muka datar).
Jiwa IT nya lalu keluar, kenapa gak make google maps, owh iya, setelah dicek via google maps browser ternyata lumayan jauh, dan banyak persimpangan yang dapat membuat hati gegana (gelisah galau merana) karena nyasar T.T terus adalagi, gimana ntar kalo disana gak ada signal ? bisa po buka google maps
Jadi teringat beberapa tahun lalu ketika masih kuliah pernah buat sebuah aplikasi yang memanfaatkan google directions dan google maps untuk memandu ke lokasi wisata, setelah dicari – cari beberapa menit, gak ketemu sourcenya, ini akibat ganti komputer beberapa tahun lalu, dan sepertinya sourcenya gak ke copy, dulu masih polos gak ngerti cara make git T.T
gambaran aplikasi
Konsep aplikasinya adalah pengembangan dari artikel yang saya tulis duluuu sekali, bedanya adalah dah gak make AsyncTask, udah diganti networking library Volley, terus parsing JSONnnya gak make cara lama parsing satu persatu (lamaaa bro) udah make Gson kemudian database tidak menggunakan SQLite tapi menggunakan Realm salah satu database NoSQL yang ada di android.
Oke sekarang nyeritain alur aplikasinya seperti apa, jadi gini nanti apps akan coba mengambil data directions yang dihasilkan dari google directions, kemudian hasil JSONnya ini diparsing oleh library Gson dan polylinenya disimpan kedalam database Realm, setelah disimpan dalam database baru ditampilkan kedalam maps, kenapa disimpan kedalam database polylinenya ? agar nanti ketika dibuka untuk selanjutnya tidak memerlukan internet lagi, tinggal baca dari database hal ini untuk menanggulangi ketika diperjalanan tidak adanya koneksi internet tapi signal gps masih ada.
Sebelum user dapat menekan tombol generate route, user harus memasukkan starting point dimana rute akan mulai digenerate, saya menggunakan maps dan sebuah marker untuk meminta inputan user dimana starting pointya, classnya seperti ini
jika diperhatikan script diatas, saya menggunakan
FusedLocationProvider untuk menentukan lokasi user saat ini berada, dapat
dilihat dari kode dibawah
@Override
public void
onConnected(Bundle bundle) {
if (location == null) {
// get
last location device
location =
LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
if (mMap
!= null) {
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new
LatLng(location.getLatitude(), location.getLongitude()), 13));
mMap.addMarker(new MarkerOptions()
.position(new
LatLng(location.getLatitude(), location.getLongitude()))
.title("Starting Point")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
);
lat =
location.getLatitude();
lng =
location.getLongitude();
Toast.makeText(this,
"Lokasi kamu saat ini, sebagai patokan titik awal perjalanan kamu kak
:')", Toast.LENGTH_LONG).show();
}
}
}
ketika googleApiClient berhasil terkoneksi, dan
FusedLocationProvider dapat mengakses last location maka saya akan menggerakkan
camera maps ke location user sekarang, kemudian menambahkan marker diatasnya.
Agar lebih fleksibel saya membuat user dapat memilih
starting point sesuai dengan kehendaknya, caranya adalah dengan mengklik dimana
saja diatas peta maka lokasi klik tersebut akan menjadi starting point, caranya
dalah dengan menambahkan event onMapClickListener ke peta, setelah itu
implement method onMapClick
@Override
public void
onMapClick(LatLng latLng) {
mMap.clear();
mMap.addMarker(new MarkerOptions()
.position(new LatLng(latLng.latitude, latLng.longitude))
.title("Starting Point")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
);
lat =
latLng.latitude;
lng =
latLng.longitude;
}
setelah dirasa cukup user tinggal menekan tombol centang
yang ada dibawah yang akan menjalankan code berikut
@OnClick(R.id.fab)
public void
onFabClick() {
Toast.makeText(this, "fab click", Toast.LENGTH_SHORT).show();
Bundle data =
new Bundle();
data.putDouble("lat", lat);
data.putDouble("lng", lng);
Intent
resultIntent = new Intent();
resultIntent.putExtras(data);
setResult(RESULT_OK, resultIntent);
finish();
}
kode diatas adalah untuk mengembalikan ke activity
sebelumnya dengan Result OK dan nilai latitude dan longitude yang sudah
dipilih.
Selanjutnya user akan memilih destinasi wisata tujuan yang
ditampilkan kedalam Spinner, lokasi didapet dari mana ? masih dihardcode, jadi
langsung ditulis kedalam code, belom ada niat ambil dari sebuah API
link class
/**
* hekz!
* Hardcode doloe
gan..
* forgive me ~
*/
private void
generateLocationDummy() {
locations.add(new Location("Sadranan", -8.146982,
110.6076521));
locations.add(new Location("Ngrenehan", -8.1235303,
110.5161231));
locations.add(new Location("Indrayanti", -8.1501091,
110.6121113));
locations.add(new Location("KaliBiru",
-7.8017879,110.1318019));
}
Setelah memilih destinasi maka selanjutnya tombol generate
route akan memanggil activity ViewRoute dengan membawa beberapa parameter
link class
@OnClick(R.id.btnGetRoute)
public void
getRoute() {
if
(!TextUtils.isEmpty(etFrom.getText())) {
Location
loc = locations.get(spDestination.getSelectedItemPosition());
Bundle
data = new Bundle();
data.putDouble("latAwal", lat);
data.putDouble("lngAwal", lng);
data.putDouble("latTujuan", loc.getLat());
data.putDouble("lngTujuan", loc.getLng());
data.putInt("status", MainActivity.FROM_NET);
data.putString("tujuan", loc.getName());
startActivity(new Intent(this,
ViewRouteActivity.class).putExtras(data));
} else {
Toast.makeText(this, "can't empty",
Toast.LENGTH_SHORT).show();
}
}
Setetal memilih starting point dan destinasi tujuan, langkah
selanjutnya adalah mendapatkan titik-titik lokasi yang digunakan untuk
menggambar jalur kedalam peta, dibagian inilah fungsi dari Google Directions,
untuk melakukan request ke google directions saya menggunakan volleylibrary
dengan class batuan JsonObjectRequestnya, sehingga hasil dari requestnya
otomatis dibuatkan JsonObject
link class
private void
getDirections(String URL) {
JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET,
URL,
null,
new Response.Listener<JSONObject>()
{
@Override
public void onResponse(JSONObject jsonObject) {
progressDialog.dismiss();
response = new Gson().fromJson(jsonObject.toString(),
com.pratamawijaya.panggilpeta.json.Response.class);
Log.d("debug", "" +
response.getRouteList().get(0).getLegsList().get(0).getDistance());
// Fetch Directions From Json
fetchDirection(response.getRouteList().get(0).getLegsList().get(0).getStepsList());
saveToDb(response.getRouteList().get(0).getLegsList().get(0));
// TODO: Save to DB
}
},
new
Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError volleyError) {
progressDialog.dismiss();
Log.d("error", "" + volleyError.toString());
}
});
progressDialog.show();
BaseApplication.getInstance().addToRequestQueue(request,
"tag");
}
jika diperhatikan dari method getDirections didalam method
onResponse saya akan memanggil method fetchDirections, dimana didalam method
inilah proses pengambilan data berubah lat lng yang akan dijadikan polyline
link class
private void
fetchDirection(List<Steps> stepsList) {
Log.d("debug", "size list awal: " +
latLngList.size());
for (Steps
data : stepsList) {
// add
start
latLngList.add(new LatLng(data.getStartLocation().getLat(),
data.getStartLocation().getLng()));
// decode
poly
List<LatLng> decodedPoly =
Utils.decodePoly(data.getPolyline().getPoints());
for
(LatLng point : decodedPoly)
latLngList.add(new LatLng(point.latitude, point.longitude));
latLngList.add(new LatLng(data.getEndLocation().getLat(),
data.getEndLocation().getLng()));
// add end
}
Log.d("debug", "size list akhir : " +
latLngList.size());
drawDirectionToMap(latLngList);
}
setelah didapatkan polylinenya baru digambar kedalam
mapsnya, prosesnya menggunakan method drawDirections berikut ini
link class
private void
drawDirectionToMap(List<LatLng> latLngList) {
PolylineOptions line = new PolylineOptions().width(3).color(Color.BLUE);
for (int i =
0; i < latLngList.size(); i++) {
line.add(latLngList.get(i));
}
mMap.addPolyline(line);
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new
LatLng(latLngList.get(0).latitude, latLngList.get(0).longitude), 14));
// add marker
diawal
mMap.addMarker(new MarkerOptions()
.position(new LatLng(latLngList.get(0).latitude,
latLngList.get(0).longitude))
.title("starting
point")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
);
// add marker
di akhir
int index =
latLngList.size() - 1;
mMap.addMarker(new MarkerOptions()
.position(new LatLng(latLngList.get(index).latitude,
latLngList.get(index).longitude))
.title("end point")
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_marker))
);
Toast.makeText(this, "Jalur berhasil digambar kak, hati2 dijalan
pelan2 saja,,, ", Toast.LENGTH_SHORT).show();
}
nah untuk proses pengambilan data via internet seperti itu,
lalu untuk yang offline alurnya seperti apa, nah alurnya seperti ini, semuanya
berawal dari class MainActivity berikut ini
public class MainActivity extends BaseActivity implements
RecyclerItemClickListener.OnItemClickListener {
public static
final int FROM_LOCAL = 0;
public static
final int FROM_NET = 1;
@InjectView(R.id.recyclerview)
RecyclerView
recyclerView;
@InjectView(R.id.emptytext)
TextView
emptyText;
@InjectView(R.id.fab)
FloatingActionButton fab;
private
ListRouteAdapter adapterRoute;
private
List<LocationModel> locationModels;
private Realm
realm;
@Override
protected void
onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.inject(this);
realm =
Realm.getInstance(this);
getSupportActionBar().setTitle(getResources().getString(R.string.txt_liburan));
locationModels
= new ArrayList<>();
adapterRoute =
new ListRouteAdapter(this, locationModels);
updateView();
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(adapterRoute);
recyclerView.addOnItemTouchListener(new RecyclerItemClickListener(this,
this));
readDataFromDb();
}
private void
updateView() {
if
(locationModels.isEmpty()) {
emptyText.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
emptyText.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
}
private void
readDataFromDb() {
if
(locationModels.size() > 0)
locationModels.clear();
RealmResults<LocationModel> result = realm
.where(LocationModel.class)
.findAll();
// sortiny by
id.
// show
greater first
result.sort("id",
RealmResults.SORT_ORDER_DESCENDING);
for
(LocationModel data : result) {
Log.d("tag", "datanya " + data.getId());
locationModels.add(data);
}
// notify
adapter
adapterRoute.notifyDataSetChanged();
// update view
updateView();
}
@OnClick(R.id.fab)
public void
onFabClick() {
startActivity(new Intent(this, AddRouteActivity.class));
}
@Override
public void
onItemClick(View v, int position) {
Toast.makeText(this, "" +
locationModels.get(position).getTujuan(), Toast.LENGTH_SHORT).show();
Bundle data =
new Bundle();
data.putInt("status", FROM_LOCAL);
data.putString("id",
locationModels.get(position).getId());
startActivity(new Intent(this,
ViewRouteActivity.class).putExtras(data));
}
@Override
protected void
onResume() {
super.onResume();
readDataFromDb();
}
}
view ra
Yang pertama adalah jelas membaca data yang ada ditabase
Realm, method yang bertanggung jawab untuk tugas itu adalah method
readDataFromDb berikut ini
link class
private void
readDataFromDb() {
if
(locationModels.size() > 0)
locationModels.clear();
RealmResults<LocationModel> result = realm
.where(LocationModel.class)
.findAll();
// sortiny by
id.
// show
greater first
result.sort("id", RealmResults.SORT_ORDER_DESCENDING);
for
(LocationModel data : result) {
Log.d("tag", "datanya " + data.getId());
locationModels.add(data);
}
// notify
adapter
adapterRoute.notifyDataSetChanged();
// update view
updateView();
}
intinya dari method itu adalah mencoba untuk query kedalam
class model, kemudian disorting berdasarkan id secara descending, saya set
seperti ini saya pengennya rute yang terakhir saya generate yang akan berada
diatas sendiri.
kemudian untuk event agar ketika list route di klik saya
menggunakan event RecyclerItemClickListener.OnItemClickListener yang dibuat
sendiri dan berada di package helper, isi dari methodnya adalah
link class
@Override
public void onItemClick(View v, int position)
{
Toast.makeText(this, "" +
locationModels.get(position).getTujuan(), Toast.LENGTH_SHORT).show();
Bundle data =
new Bundle();
data.putInt("status", FROM_LOCAL);
data.putString("id", locationModels.get(position).getId());
startActivity(new Intent(this,
ViewRouteActivity.class).putExtras(data));
}
yang perlu diperhatikan disini adalah saya menambahkan key
untuk menentukan route yang digambar itu dari database atau dari internet, dan
id dari database rute yang akan saya gambar.
Selanjutnya kembali lagi ke class ViewRouteActivity untuk
melihat bagaiman proses menggambar polyline yang didapat dari database. Proses
utamanya ada di method onCreate yang ada diclass ViewRoute activity berikut
link class
data =
getIntent().getExtras();
if
(data.getInt("status") == MainActivity.FROM_LOCAL) {
// baca db
latLngList
= readDataFromDB(data.getString("id"));
// draw
drawDirectionToMap(latLngList);
} else {
latAwal =
data.getDouble("latAwal");
lngAwal =
data.getDouble("lngAwal");
latTujuan
= data.getDouble("latTujuan");
lngTujuan
= data.getDouble("lngTujuan");
tujuan =
data.getString("tujuan");
getDirections(getGoogleDirectionsUrl(latAwal, lngAwal, latTujuan,
lngTujuan));
}
Pertama saya akan cek statusnya apakah rute tersebut diambil dari database atau dari internet, cara ngeceknya make key itu tadi, di bagian MainActivity saya membuat key untuk membedakan data diambil dari db maupun internet
jika data yang diambil dari database, maka selanjutnya adalah melalukan read ke database berdasarkan dari id rute,
sedangkan isi dari method readDataFromDB itu sendiri adalah seperti ini
di method tersebut saya coba melakukan query ke LocationModel class dengan id berdasarkan dari id yang dibawa class sebelumnya, kemudian memasukkan data lat lng kedalam list yang disiapkan untuk menampung data latitude dan longitude, setelah data berhasil dibaca kemudian method drawDirectionToMap dijalankan dengan parameter List dari latlng yang telah didapatkan sebelumnya.
Sumber : https://pratamawijaya.com/programming/android-programming/android-studio-project-pemanfaatan-google-maps-dan-google-directions-sebagai-penunjuk-jalan
0 komentar:
Post a Comment
Mari kita saling berkomentar. Jika kalian suka dengan artikel ini, ayo kita "Share" untuk membagikan informasi ini kepada sobat yang lain agar lebih bermanfaat. Terima kasih, Salam Blogger . . .