Kena limit referensi 64K di Android

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*

Ada komentar?

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: