Last Updated on 11 years by Mas Herdi
Beberapa hari yang lalu, saya disibukkan oleh sebuah proyek aplikasi Android yang berbasiskan mobile web (HTML5, JQuery, PHP dan kawan-kawannya). Karena ingin dibuat lintas platform, sehingga dibuatlah aplikasi tersebut berupa mobile web. Awalnya saya kira porting ke Android menggunakan WebView-nya mudah dan tidak membutuhkan usaha banyak. Namun ternyata setelah dicoba, banyak sekali blunder dan tantangan yang harus dihadapi ketika kita menggunakan WebView di Android…
Apa itu WebView
WebView adalah sebuah class pada Android yang berfungsi sebagai semacam sandbox untuk menampilkan dan menjalan aplikasi mobile yang berbasiskan web, entah itu HTML5, JQuery Mobile, dan sebagainya. Cara gampangnya WebView itu seperti Android browser, tetapi tidak mempunyai address bar tempat memasukkan alamat URL. Karena URL yang mau kita buka sudah didefinisikan di aplikasi dan tidak bisa kita ganti.
Web Client
Dalam implementasinya, WebView mempunyai dua buah klien yang bisa kita gunakan untuk me-render halaman web, dan tiap-tiap klien tersebut mempunyai fungsionalitas yang berbeda-beda. Kedua klien tersebut adalah WebViewClient dan WebChromeClient.
WebViewClient adalah sebuah browser klien yang menyediakan fungsi-fungsi dasar dalam menampilkan halaman web. Sedangkan, WebChromeClient adalah browser klien yang menyediakan fitur-fitur advanced dalam rendering halaman web, kebanyakan berhubungan dengan interaksi antara browser dengan javascript, menampilkan objek seperti video, dan fitur-fitur advanced lainnya. Kalian bisa menggunakan kedua klien tersebut, namun apabila kalian hanya ingin me-render halaman web yang tidak membutuhkan banyak fitur (misal berisi HTML saja, tanpa javascript) maka kalian cukup menggunakan WebViewClient.
Pada dasarnya inisialisasi sebuah aplikasi WebView di Android adalah seperti berikut :
webView= (WebView) findViewById(R.id.webview); webView.setWebChromeClient(new WebChromeClient()); webView.setWebViewClient(new WebViewClient()); //mengaktifkan dukungan untuk javascript webView.getSettings().setJavaScriptEnabled(true); webView.loadUrl("http://www.twoh.co");
Adapun untuk aplikasi yang lebih advanced, contoh kodenya seperti berikut :
webView = (WebView) findViewById(R.id.wv_twoh); webSettings = (WebSettings) webView.getSettings(); String url = "http://twoh.co"; // memberitahukan browser untuk mengaktifkan Wide ViewPort webSettings.setUseWideViewPort(true); // otomatis website akan diload dengan zoom out webSettings.setLoadWithOverviewMode(true); // otomatis menampilkan javascript window webSettings.setJavaScriptCanOpenWindowsAutomatically(true); // mengaktifkan fungsi-fungsi storage HTML5 webSettings.setDatabaseEnabled(true); webSettings.setDomStorageEnabled(true); String databasePath = this.getApplicationContext() .getDir("databases", Context.MODE_PRIVATE).getPath(); webSettings.setDatabasePath(databasePath); webSettings.setJavaScriptEnabled(true); // mengaktifkan fitur geolocation (deteksi lokasi) webSettings.setGeolocationEnabled(true); webSettings.setGeolocationDatabasePath(databasePath); // menonaktifkan hw acceleration yang kadang bermasalah // dengan mengaktifkan software layer webView.setLayerType(View.LAYER_TYPE_SOFTWARE, null); webView.loadUrl(url);
Bisa dilihat, banyak sekali settingan yang saya nyalakan pada kode di atas. Untuk geolocation, ketika diaktifkan maka browser akan menampilkan alert, apakah aplikasi boleh mengakses lokasi pengguna atau tidak. Namun fungsionalitas ini bisa di bypass sehingga aplikasi secara otomatis akan mendapatkan lokasi pengguna. 😀 Setelah itu saya akan memberikan contoh pembuatan custom WebViewClient dan WebChromeClient
Custom WebViewClient
Pada aplikasi WebView yang saya buat, tidak ada banyak perubahan untuk kelas WebViewClient. Adapun beberapa hal dasar yang saya implementasikan seperti, menampilkan progress dialog ketika mulai me-load web page, dan meng-override url loading sehingga url yang diklik akan di-load pada WebView tersebut dan tidak membuka aplikasi browser lainnya. Berikut ini contoh kodenya.
public class TwohWebViewClient extends WebViewClient{ public static final String TAG = TwohWebViewClient.class.getSimpleName(); private Activity activity; private ProgressDialog pgDialog; public TwohWebViewClient(Activity act) { activity = act; // inisialisasi progress dialog pgDialog = TwohWebViewUtils.getProgressDialog(activity, ProgressDialog.STYLE_SPINNER, true, "loading", false); } // Untuk memaksa me-load URL pada browser WebView ini @Override public boolean shouldOverrideUrlLoading(WebView view, String url) { webView.loadUrl(url); return true; } // dipanggil pada saat halaman web mulai di-load, menampilkan progress dialog @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); pgDialog.show(); Log.v(TAG,"page started "+ url); } // dipanggil pada saat halaman web selesai di-load, menghilangkan progress dialog @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); pgDialog.dismiss(); Log.v(TAG,"page finished "+ url); } }
Custom WebChromeClient
Sedangkan untuk custom WebChromeClient, ada lumayan banyak method yang harus diubah. Diantaranya seperti bypass geolocation permission menjadi always allow, kemudian menampilkan output console.log()
pada javascript ke logcat Android, dan yang terakhir adalah mengaktifkan fitur HTML5 media capture. Dan bagian terakhir ini yang menjadi blunder terbesar. :v
public class TwohWebChromeClient extends WebChromeClient{ private Context context; private Activity activity; public static final String TAG = TwohWebChromeClient .class.getSimpleName(); public TwohWebChromeClient (Context ctx, Activity act) { context = ctx; activity = act; } // display javascript log message pada LogCat @Override public boolean onConsoleMessage(ConsoleMessage cm) { Log.v(TAG,cm.message() + " log from line "+cm.lineNumber()+ " of " + cm.sourceId()); return true; } // tidak menampilkan prompt, bypass menjadi always allow get location @Override public void onGeolocationPermissionsShowPrompt(final String origin, final GeolocationPermissions.Callback callback) { callback.invoke(origin, true, true); } // hidden API, akan dijelaskan lebih lanjut :D public void openFileChooser(ValueCallback<Uri> uploadMsg,String acceptType, String capture) { Log.v(TAG, "called first"); openFileChooser(uploadMsg); } public void openFileChooser(ValueCallback<Uri> uploadMsg, String acceptType) { Log.v(TAG, "called two"); openFileChooser(uploadMsg); } public void openFileChooser(ValueCallback<Uri> uploadMsg) { TwohWebActivity.mUploadMessage = uploadMsg; Log.v(TAG, "called three"); Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); File externalDataDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM); File cameraDataDir = new File(externalDataDir.getAbsolutePath() + File.separator + "browser-photos"); cameraDataDir.mkdirs(); TwohWebActivity.filePath = cameraDataDir.getAbsolutePath() + File.separator +"static_photo.jpg"; cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(TwohWebActivity.filePath))); activity.startActivityForResult(cameraIntent, TwohWebActivity.TAKE_PICTURE); } }
Kelemahan WebView
Sebenarnya untuk fungsi-fungsi dasar, aplikasi ini berjalan dengan lancar. Hingga kemudian ada satu requirements yaitu capture image dari kamera dan kemudian menguploadnya ke web yang ternyata tidak berjalan dengan mulus. Pada kode HTML-nya menggunakan syntax HTML5 untuk upload file, yaitu <input type="file" media="capture" />
. Ketika link tersebut dibuka lewat browser bawaan Android dan Google Chrome for Android, aplikasi akan langsung menjalankan kamera sehingga user bisa ambil gambar dan menguploadnya. Namun ketika membukanya menggunakan WebView, tidak muncul apa-apa. 😀 Setelah saya selidiki, ternyata ada sebuah hidden API yang harus dipanggil supaya aplikasi bisa membuka kamera dan menjalankan HTML5 media capture. Hidden API itu adalah method openFileChooser()
.
Disebut hidden API karena method tersebut adalah private API, bukan public API, sehingga apabila kalian menulis ulang method tersebut dan menambahkan @Override
, Eclipse akan memberikan pesan error walaupun nyatanya memang method tersebut sudah di-override.
Selain merupakan private API, jika kalian cermati pada kode di atas ada tiga buah deklarasi openFileChooser()
method. Hal itu karena pada tiap-tiap API level, method openFileChooser() yang dipanggil berbeda-beda, yaitu :
– openFileChooser(ValueCallback uploadMsg), untuk Android versi <= 3.0
– openFileChooser(ValueCallback uploadMsg, String acceptType), untuk Android versi > 3.0
– openFileChooser(ValueCallback uploadMsg, String acceptType, String capture), untuk Android versi Jelly Bean
Lantas, bagaimana dengan KitKat? 😀
Ternyata, pada release Android KitKat, default WebView pada Android diganti menggunakan engine Chrome. Sehingga tidak ada satupun method openFileChooser di atas yang berjalan pada Android KitKat.
Tidak hanya itu, WebView seringkali juga menunjukkan performansi yang tidak konsisten. Seperti kadang berhasil upload gambar, dan kadang tidak berhasil. Padahal menggunakan baris kode yang sama. Walaupun sebenarnya bisa saja hal ini disebabkan oleh script di sisi web-nya, karena kebetulan yang membuat aplikasi web-nya bukan saya, sehingga kurang bebas untuk melakukan modifikasi. Mungkin untuk teknik lebih advanced-nya, aplikasi mobile web yang akan ditampilkan menggunakan WebView harus dicoding dengan Android in mind. Dan kemudian dari sisi Android membuat sebuah javascript interface sendiri yang bisa berinteraksi dengan javascript di sisi website.
Untuk aplikasi web mobile yang sekedar browsing, input form dan sebagainya, WebView masih bagus dan recommended untuk digunakan. Namun untuk aplikasi yang membutuhkan fungsi native, sepertinya harus menggunakan aplikasi native juga. Atau framework yang lebih canggih seperti PhoneGap/Apache Cordova.
Bang, mau tanya, kalau webview ada audionya, kok nggak main ya audionya?
Audionya di embed dari mana?
Selamat dini hari 🙂
gan. mau tanya
webview punya saya kok ndak sempurna ya pas ngeload web yang berbasis bootstrap. ..
apa ada sesuatu yang belum saya inputkan?
Terimakasih 🙂
Hmm… kurang tau juga gan, tapi kalo sudah bisa nampilin berarti sudah benar.
Barangkali web agan yang kurang responsive 🙂
Wah bner juga yak…
Okedah thanks gan 😀
Sip, semangat gan
maaf mau tanya, saya sudah coba buat android webview app menggunakan android studio, tapi saat pengguna ingin save image dari tampilan itu enggak bisa, kalau pake browser biasa di klik+tahan nanti keluar pilihan save. tapi di android webview app yang saya buat enggak keluar. sedang cari tutorial atau cara2 untuk membuat aplikasi saya bisa digunakan untuk download/save imagenya. barangkali agan bisa bantu ^_^
iya, itu butuh tambahan fungsi sendiri yang harus dibikin manual
nah sama nih kayak mas ini.. BTW mas punya source codenya ga webview yang bisa save image??
Kang, kapan nnih pembelajaran untuk yang membuat applikasi web native nya 😀
pengen bisa juga 😀
hehe kalo web native ada banyak tutorial nya gan, yang mengajarkan HTML, PHP dan CSS
met dini hari gan„ mau tanya di web view ini bisa di masukin kode admodnya tidak ya… masukin kodenya di bagiamana ya? terima kasih
bisa gan, sama saja di bagian XML nya untuk memasukkan AdMob
Kalo saya misalnya mau bikin web seperti daftarperumahanmurah.com versi android gini gampang gak ya gan?
gan Hafizh Herdi saya ada problem untuk webview sama kasusnya yang pertama comment agan Muhammad Zaini, saya coba ngeload audio mp3 kok ga jalan saya coba jalanin di browser jalan tapi pas di compile apk ga jalan? untuk audio saya taro file di assets/www dan saat saya panggil di html5 src=”assets/sound-app/my.mp3″ mohon pencerahannya gan..Thanks
ya tinggal dipindah gan mp3-nya dari assets/www ke assets/sound-app/
udah gan tapi tetep ga ada suaranya pas diandroid
Bagaimana menambahkan link nomor telepon ke webview?
Ditunggu tutorial membuat aplikasi web nativenya Gan Hafizh Herdi, saya googling kesana kemari belum nemu juga, Nuhun
Gan ,, ada solusi buat yang kitkat ??
Gan, mau nanya ni, Saya simpan file video di google drive, kemudian saya kopikan URL nya di WebView. ketika di run halaman webnya udah tampil, tapi pas di klik videonya ko ga jalan-jalan ya? Mohon solusinya, terimakasih…
Gan mau nanya ni. Saya simpan file video di google drive kemudian saya kopikan URL nya di WebView. Setelah di run, halaman webnya muncul tapi pas di klik videonya ko ngga jalan-jalan ya? kenapa ya? Mohon solusinya… terimaksih.
Gan mau nanya ni… Saya simpan file video di google drive kemudian saya kopi URL nya ke WebView. Setelah di run, halaman web nya muncul tapi pas di klik videonya ko ngga jalan-jalan ya? kenapa? Mohon solusinya… Terimakasih.
Banyak faktor gan, tapi pastikan WebView nya support Javascript, cache dan sebagainya
mas Hafiz, aku mau nanya saya udah buat notifikasi suara di website udah bunyi tapi di webview ga bunyi
jadi begini sintaxnya
if($databaru > 0 ){
}
mas Hafiz, aku mau nanya saya udah buat notifikasi suara di website udah bunyi tapi di webview ga bunyi
jadi begini sintaxnya
if($databaru > 0 ){
}