Salah satu horor ketika memprogram Android adalah limitasi Method 64K. Dengan limitasi ini, pemrogram harus bisa mengatur agar jangan sampai method yang digunakan (dan berbagai pusatakanya) melebihi dari 65536 buah. Sayangnya itu sulit, setidaknya buat saya.
Seperti dialami salah satu aplikasi yang saya kembangkan. Saat build rilis terakhir sekitar sebulan lalu, tidak ada masalah dengan limitasi ini. Tapi tadi sore ketika mau coba build debug dan release, tiba-tiba saja muncul error seperti di bawah ini.
Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.internal.zzadf.zzg Could not find class 'com.aplikasi.activity.SplashActivity$1', referenced from method com.aplikasi.activity.SplashActivity.cekLoginToken Could not find class 'com.aplikasi.activity.SplashActivity$2', referenced from method com.aplikasi.activity.SplashActivity.checkVersion Could not find class 'android.graphics.drawable.RippleDrawable', referenced from method android.support.v7.widget.AppCompatImageHelper.hasOverlappingRendering Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.clearAnimationCallbacks Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.registerAnimationCallback Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.unregisterAnimationCallback Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.clearAnimationCallbacks Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.isRunning Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.registerAnimationCallback Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.start Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.stop Could not find class 'android.graphics.drawable.AnimatedVectorDrawable', referenced from method android.support.graphics.drawable.AnimatedVectorDrawableCompat.unregisterAnimationCallback Could not find class 'com.aplikasi.util.sync.TokenService', referenced from method com.aplikasi.util.ConnectionDetector.cekToken Could not find class 'retrofit2.Retrofit$Builder', referenced from method com.aplikasi.util.ConnectionDetector.checkToken Could not find class 'okhttp3.OkHttpClient', referenced from method com.aplikasi.util.api.ApiFactory.createApiService FATAL EXCEPTION: main java.lang.NoClassDefFoundError: okhttp3.OkHttpClient at com.aplikasi.util.api.ApiFactory.createApiService(ApiFactory.java:31) at com.aplikasi.activity.SplashActivity.checkVersion(SplashActivity.java:310) at com.aplikasi.activity.SplashActivity.cekPemakaianApp(SplashActivity.java:159) at com.aplikasi.activity.SplashActivity.onCreate(SplashActivity.java:107) at android.app.Activity.performCreate(Activity.java:5104) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1080) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2144) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2230) at android.app.ActivityThread.access$600(ActivityThread.java:141) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1234) at android.os.Handler.dispatchMessage(Handler.java:99) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5041) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:511) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) at dalvik.system.NativeStart.main(Native Method)
Dari hasil googling dan ubek-ubek StackOverflow, katanya error itu merupakan pertanda bahwa aplikasi yang saya kembangkan sudah mencapai batas limit 64K. Duh.
Sebenarnya, apa itu limitasi Method 64K? Mengutip dari sini, limitasi method atau batas referensi 64K adalah ketika jumlah total metode yang bisa dirujuk dalam file DEX tunggal sudah melebihi dari 65.536 alias 2^16. Ini termasuk metode kerangka kerja Android, metode pustaka, dan metode yang kita buat.
Mengingat sulit untuk tetap membatasi metode yang dipakai kurang dari 64K, solusinya adalah dengan memecah APK sesuai arsitektur ponsel pengguna. Karena itu multidexEnabled harus diatur true.
android { defaultConfig { ... minSdkVersion 21 targetSdkVersion 26 multiDexEnabled true } ... }
Tapi itu tidak cukup jika aplikasi yang kita bangun ingin juga mendukung versi Android yang lebih lama, seperti KitKat (API 19) atau Jelly Bean (17). Untuk itu kita harus menambahkan pustaka multidex, sehingga berkas build.gradle-nya seperti ini:
android { defaultConfig { ... minSdkVersion 15 targetSdkVersion 26 multiDexEnabled true } ... } dependencies { compile 'com.android.support:multidex:1.0.1' }
Selain itu, pada berkas Application.java (atau nama kelas lain yang extends dari Application), tambahkan method attachBaseContext(Context base) :
public class MyApplication extends Application { @Override protected void attachBaseContext(Context base) { super.attachBaseContext(context); Multidex.install(this); } }
Jika kita gunakan kelas Application, jangan lupa tambahkan baris berikut di berkas AndroidManifest.xml :
<application android:name=".MyApplication" android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme.NoActionBar">
Seharusnya, sekarang kita bisa build lagi aplikasinya. Minimal untuk melakukan debugging. Tapi, di saya masih ada masalah. Ketika coba lakukan build Release APK, masih terjadi error, terutama ketika proguard-nya diaktifkan :|. Ketika proguardnya dinonaktifkan, eh bisa di-build. Nasib. Semoga di build yang terakhir ini tidak ada error lagi.
*Ditulis sambil nunggu proses build signed APK yang sudah berjalan sekitar satu jam dan masih belum selesai juga*