Android AddJavascripInterface tidak berjalan saat release

Agak sedikit berkaitan dengan postingan sebelumnya, di Android, jika kita ingin memanggil sebuah fungsi java melalui javascript pada webview yang bisa kita lakukan adalah dengan menggunakan fungsi addJavascriptInterface, kayak sample-nya gini:

 class JsObject {
    @JavascriptInterface
    public String toString() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new JsObject(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");

jangan lupa untuk selalu menambahkan anotasi atribut @JavascriptInterface pada fungsi yang akan dipanggil dari javascript, karena ini mandatory mulai dari Android API Level 17.

Problem

Pada saat development aplikasi, pada umumnya developer secara default akan menjalankan aplikasi langsung dari IDE (eclipse, Android Studio, intelliJ ddl) ke device; hal ini berarti aplikasi masih dalam mode debug dan belum di signature. Flow-nya kurang lebih seperti ini

IDE -> Build -> apk -> Run -> Device/Simulator

Akan tetapi, saat me-release aplikasi ke Google Play, pada umumnya yang kita lakukan adalah:

IDE->Build->Obfuscate->sign->apk->submit ke Google Play Store

di sini terlihat ada dua langkah tambahan sebelum aplikasi release ke Google Play Store, yaitu obfuscate & sign. Secara umum kedua langkah tersebut tidak akan membuat masalah yang berarti di aplikasi; akan tetapi jika tidak hati-hati masalah bisa timbul dan lambat dideteksi jika kita terbiasa melakukan testing aplikasi kita dalam mode debug saja; misalnya saat kita memanfaatkan javascript interface ke Java seperti yang diceritakan di awal blog ini.

Salah satu langkah yang dilakukan oleh obfuscator, adalah “meminimize” nama-nama fungsi yang kita buat sehingga menjadi nama-nama yang pendek (misalnya dengan satu karakter) sehingga menjadikan ukuran aplikasi kita lebih kecil dan kalaupun ada yang me-reverse engineer/decompile aplikasi yang kita buat juga akan kesulitan memahami alur aplikasi kita. Perlu dijadikan perhatian, obfuscator tidak akan pernah mengubah konstanta string yang ada di source code aplikasi kita.Hal ini juga berlaku untuk konten string yang ada di webview yang kita isi secara manual seperti contoh pada awal blog ini. Sehingga boleh jadi, setelah selesai obfuscation kelas yang kita buat menjadi kurang lebih seperti ini:

class J {
    public String s() { return "injectedObject"; }
 }
 webView.addJavascriptInterface(new J(), "injectedObject");
 webView.loadData("", "text/html", null);
 webView.loadUrl("javascript:alert(injectedObject.toString())");

Kita perhatikan source code di atas, anotasi atribut @JavascriptInterface hilang, dan nama kelas JsObject berubah menjadi J dan fungsi toString berubah menjadi s(), tetapi di fungsi javascript nama fungsinya tidak berubah tetap toString; anda bisa lihat, ini akan membuat javascript tidak berjalan karena fungsi toString sudah tidak lagi ada dan kalau anda menjalankan aplikasi tersebut di device dengan API Level 17 ke atas juga “lebih” bermasalah karena anotasi  @JavascriptInterface hilang.

Solution

Agar fungsi yang kita gunakan melalui interface javacript tidak diikut di obfuscate, kita bisa menambahkan beberapa rule di file konfigurasi obfuscator/proguard:
1. Konfigurasi agar proguard tidak menghapus anotasi atribut

-keepattributes JavascriptInterface
-keepattributes *Annotation*

2. Konfigurasi agar proguard tidak mengubah nama fungsi dan kelasnya

-keep public class com.bla.bli.blu.Bleblo$JsObject
-keep public class * implements com.bla.bli.blu.Bleblo$JsObject
-keepclassmembers class com.bla.bli.blu.Bleblo$JsObject {
<methods>;
}

dengan beberapa baris konfigurasi di atas, maka aplikasi tidak lagi bermasalah saat melakukan interfacing fungsi dari javascript ke java.

happy coding :)

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s