Sunday, March 6, 2016

Pemanfaatan Google Maps dan Google Directions sebagai penunjuk jalan

Pemanfaatan Google Maps dan Google Directions sebagai penunjuk jalan 
Aplikasi android google maps directions
Tampilan Home Screen Aplikasi
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
Aplikasi android google maps directions
Tampilan ketika user memilih destination
Android apps google maps directions
Tampilan map dan rute ke lokasi tujuan
Android Apps Google Maps directions
Tetap dapat menggunakan maps walaupun kondisi tidak ada jaringan
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
private List<LatLng> readDataFromDB(String id) {
RealmResults<LocationModel> result = realm.where(LocationModel.class).equalTo("id", id).findAll();
List<LatLng> listlatlng = new ArrayList<>();
for (LatLngModel data : result.get(0).getLatLngRealmList())
listlatlng.add(new LatLng(data.getLat(), data.getLng()));
return listlatlng;
}
view rawgistfile1.java hosted with ❤ by GitHub
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

BERKOMENTARLAH YANG SANTUN, JANGAN SPAM, AYO BERKOMENTARLAH DISINI. . .

Ditulis Oleh : I Gusti Ngurah Made Ardika ~ Mari Berbagi dan Belajar Bersama

Artikel Pemanfaatan Google Maps dan Google Directions sebagai penunjuk jalan ini diposting oleh I Gusti Ngurah Made Ardika pada hari Sunday, March 6, 2016. Terimakasih atas kunjungan Anda serta kesediaan Anda membaca artikel ini. Kritik dan saran dapat anda sampaikan melalui kotak komentar.

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 . . .