29 Haziran 2015 Pazartesi

Android Dinamik Sınıf Yükleme



Merhaba Arkadaşlar,

Yazılım geliştirirken bazen classpath'e dinamik sınıf yüklememizi gerektirecek bir durum oluşabilir; plugin tabanlı, esnek ve genişletilebilir mimari kurmak veya uygulama konfigrasyonuna bağlı olarak runtime'da *.jar yükleme gibi. Neyse ki bu gibi durumları kotarmak için jvm tarafında Class Loader yapısı bize bu olanağı sunuyor.

ClassLoader tipinin alt sınıflarından olan URLClassLoader ile jar'ın bulunduğu path'i belirterek, ilgili sınıfları classpath'e dahil edip kullanmak mümkün. Fakat android tarafında sanal makina olarak Dalvik VM kullanıldığı ve Dalvik'in kabul ettiği format bytecode yerine dex olduğu için süreç biraz daha çetrefilli bir hal alıyor. Bu sebepten iş mantığınızı kodladığınız sınıfları barındıran jar dosyalarını dex formatına çevirmeniz gerekli. Bunun için android sdk altında (pathToAndroidSdk/build-tools/22.0.1/dx) gelen dx aracını kullanabilirsiniz:

Linux/Mac : ./dx --dex --output = output.jar input.jar
Windows   : dx.bat --dex --output = output.jar input.jar

Oluşan output.jar dosyasını açarsanız classes.dex dosyasını barındırdığını görürsünüz. Eğer dex dosyasının sınıflarınızı içerip içermediğini kontrol etmek istiyorsanız Dex2Jar aracını kullanarak ters işlem uygulayabilirsiniz.

Evet elinizdek jar'ı dex formatına dönüştürdünüz, artık yapmanız gereken bu dosyayı runtime'a dahil etmek. Bunun için URLClassLoader yerine DexClassLoader tipini kullanmanız gerekli. DexClassLoader'a yüklemek istediğiniz dex formatlı jar paketinin path'ini vererek, ilgili sınıfları kullanılmak üzere register etmiş oluyoruz:
File dexOutputDir = getDir("dex", Context.MODE_PRIVATE);
DexClassLoader dexLoader = new DexClassLoader(fullPathToJar,
    dexOutputDir.getAbsolutePath(),
    null,
    act.getClassLoader());

Artık sınfılarımız classpath'e eklendi, kullanmak için reflection yapıyoruz:
try {
    Class myClass = dexLoader.loadClass(completeClassName);
    Object obj = (Object)myClass.newInstance();
    Method m = myClass.getMethod(methodToInvoke);
    m.invoke(obj);
} catch (Exception e) {
    e.printStackTrace();
}

Girdide bahsi geçen gradle yapılandırmalı android projesine buradan ulaşabilirsiniz.

Yürütme zamanında dinamik sınıf yükleme ile daha esnek ve kolay genişletilebilir uygulamalar geliştirebileceğimiz aşikar.

Umarım faydalı olur, hayırlı ramazanlar.

Hiç yorum yok:

Yorum Gönder