/ plugin

Adobe Native Extension #2 : Android

Bir önceki yazımda, Adobe AIR hakkında ve neden extension yazmamız gerektiği hakkında bilgi vermiştim. Kısaca tekrar etmem gerekirse; AIR bize cross-platform uygulamama geliştirebilmemize olanak sağlıyor. ActionScript ile yazdığımız uygulamalarımızı Android’e, iOS’a, Windows’a ve hatta BlackBerry’e derleyebilmekteyiz. ActionScript ile yazdığımız kodların native kodlarla iletişim kurabilmesi için ise ANE yazmamız gerektiğinden bahsetmiştim.

ANE, bir pakettir. Bu paketin içerisinde hem native kodlar (bu yazı için Java – .jar) hem de ActionScript tarafında yazdığımız kodlar(.swc uzantılı kütüphane) bulunmaktadır. İki taraf birbiriyle FlashExtension kütüphanesi sayesinde iletişime geçebilmektedir. Teorik bilgiler bu kadar. Şimdi pratiğe dökelim ve puzzle parçaları yerlerine otursun.

Gerekli Ortamın Kurulması

ANE geliştirebilmemiz için gerekenler: JDK (Java Development Kit) , AIR 3 SDK, ActionScript kod yazabilmek için bir IDE(Ben Adobe Flash Builder 4.7 kullanacağım) ve java kütüphanesi geliştirmek için Android Studio.

JDK ve Android Studio için:
https://developer.android.com/studio/index.html

AIR 3 SDK için:
http://www.adobe.com/devnet/air/air-sdk-download.html

SWC Kütüphanesinin Oluşturulması (ActionScript Tarafı)

Bu bölümde Java kodumuz ve AIR uygulaması arasında arayüz görevi görecek bir ActionScript kütüphanesi yazacağız. Yazacağımız kod basit. Bir ExtensionContext oluşturacağız ve bunu ilklendireceğiz. Bu context sayesinde native taraf ve AIR arasında bir köprü kurmuş olacağız. Buna ek olarak ise basit bir fonksiyon yazacağız. Bu fonksiyon Java tarafındaki bir methodu tetikleyecek. Bu metod da ekrana bir alert dialog getirerek, gönderdiğimiz mesajı yayınlayacak. Hadi işe koyulalım.

package com.demiremrece.alertdialog{

import flash.external.ExtensionContext;

public class AlertDialog{
    //Native kod ile köprü kuracak context değişkeni
    private static var extContext:ExtensionContext=null;
    //Context yakalanması için gereki özel id
    private static var extensionID:String = "com.demiremrece.alert.extension";	
    /* Oluşturduğumuz id yi kullanarak bir context yaratıyoruz. Bu context sayesinde Java tarafındaki init metodunu çağırarak bağlantıyı kuruyoruz.*/

    private static function initContext():void{
       if(!extContext){	
            extContext=ExtensionContext.createExtensionContext(extensionID,"");
        extContext.call("init");
         }
       }

    /*Java tarafındaki showAlert metodunu tetiklemek için. Birden fazla parametre gönderilebilir.Örn;("showAlert",message,intDeger,...)*/	
    public static function showAlert(message:String):void{
        initContext();
        extContext.call("showAlert",message);
    }	
}
}

SWC tarafı bu kadar. Şimdi iletişime geçeceğimiz Android-Java tarafını yazalım.

Java Kütüphanesinin Oluşturulması (Android Tarafı)

Amacımız .jar uzantılı bir kütüphane oluşturmak olduğundan, öncelikle bir Java kütüphane projesi oluşturmamız lazım. Bu yüzden ilk olarak normal bir Android projesi oluşturuyoruz.

1

2

Ardından gradle dosyamızdaki “applicationId” özelliğini yorum satırına alıyoruz ya da siliyoruz. Buna ek olarak apply plugin : ‘com.android.aplication’ ı ‘com.android.library’ ile değiştirerek uygulama projesini kütüphane projesine çevirmiş oluyoruz.

3

Java kodları altında olan MainActivity ve diğer default olarak gelen tüm sınıfları(classları) siliyoruz. Buna ek olarak FlashRuntimeExtensions.jar kütüphanesini projemizde libs klasörü altına eklememiz lazım. Bu kütüphaneyi indirdiğiniz AIR SDK içerisine bulabilirsiniz. Elimizdeki son yapı aşağıdaki şekilde olduğunda kodlamaya hazırız demektir.

5-1

Şimdi kütüphanemizi yazmaya başlayabiliriz. İhtiyacımız olan dört sınıf var: AlertExtensionContext, AlertExtension, AlertExtensionInitFunction, ShowDialogFunction. Sırasıyla bu sınıfları oluşturalım.

İlk olarak AlertExtension sınıfını yaratalım. Bu sınıf FREExtension’ı implement edeceği için üç metodu olmalı: createContext() , dispose() ve initialize().

public class AlertExtension implements FREExtension {
    @Override
    public void initialize() {
       //Native extension kullanıma hazır olduğunda çağrılacak. Bizim örneğimizde boş kalacak.
    }
    @Override
    public FREContext createContext(String s) {
        //Bu sınıftaki en önemli metod. SWC tarafındaki ExtensionContext.createExtensionContext fonksiyonu native tarafta bu metodu tetikliyor ve bağlantı kuruluyor.
        //Dönüş değeri FREContext sınıfını extend eden bir sınıf objesi olmalı. Bir sonraki aşamada bu sınıfı yazacağız.
        alertExtensionContext = new AlertExtensionContext();
        return alertExtensionContext;
    }
    @Override
    public void dispose() {
        //Bu metod, native extensiona artık ihtiyaç duyulmadığında çağrılacak. Burada temizleme işlemi yapabilirsiniz. Bizim örneğimizde boş kalıcak.
    }
}

İkinci olarak ise AlertExtensionContext sınıfını yazalım. İki metodumuz var: dispose() ve getFunctions() .

public class AlertExtensionContext extends FREContext {
    @Override
    public Map<String, FREFunction> getFunctions() {
       //getFunctions() metodu Action Script tarafında tetikleyebileceğimiz fonksiyonları tanımladığımız yer. Her bir fonksiyon için ayrı bir sınıf yaratıyoruz.
        Map<String,FREFunction> functionMap=new java.util.HashMap<String,FREFunction>();
        functionMap.put("init",new AlertExtensionInitFunction());
        functionMap.put("showDialog",new ShowDialogFunction());
        return functionMap;
    }
    @Override
    public void dispose() {
    }
}

Son temel fonksiyonumuz olan init metodu için bir sınıf oluşturalım. Bu sınıf FREExtension ve FREFuntion sınıfını implement edecek.

public class AlertExtensionInitFunction implements FREExtension,FREFunction {
    static FREContext alertExtensionContext; // static yapıyoruz, çünkü oluşturulacak bu bağlantı objesi üzerinden SWC tarafına event yollayabileceğiz.
    @Override
    public void initialize() {
    }
    @Override
    public FREContext createContext(String s) {
        return null;
    }
    @Override
    public void dispose() {
        alertExtensionContext = null;
    }
    @Override
    public FREObject call(FREContext context, FREObject[] args) {
        alertExtensionContext = (AlertExtensionContext) context;
        android.app.Activity activity = alertExtensionContext.getActivity();
        return null;
    }
}

Ve son olarak da ShowDialog sınıfımızı yazalım. Bu sınıf da FREFunction ve FREExtension sınıfını implement edecek.

public class ShowDialog implements FREExtension,FREFunction {
    @Override
    public void initialize() {
    }
    @Override
    public FREContext createContext(String s) {
        return null;
    }
    @Override
    public void dispose() {
    }
    @Override
    public FREObject call(FREContext freContext, FREObject[] freObjects) {
        //aktivitemizin context ini alıyoruz. Bunu oluşturduğumuz static objeye de set edebilirsiniz.
        AlertExtensionContext aec = (AlertExtensionContext) freContext;
        android.app.Activity activity = aec.getActivity();
        String message ="";
        try {
            message = freObjects[0].getAsString(); // eğer gönderilmişse message parametremizi alıyoruz
        } catch (Exception e) {
            e.printStackTrace();
        }
        //Dialogda aldığımız mesajı gösteriyoruz
        try {
            AlertDialog.Builder builder = new AlertDialog.Builder(activity);
            builder.setMessage(message)
                    .setCancelable(true);
            AlertDialog alertDialog = builder.create();
            alertDialog.show();
        } catch (Exception e) {
            // Hata yönetimi
        }
        return null;
    }
}

Kodlama işlemleri buraya kadar. Java projemizi .jar uzantılı bir paket haline getirdikten sonra artık ANE yaratmaya hazırız demektir. Nasıl jar paketlemesi yapacağınızı bilmiyorsanız daha önceki yazıma: Jar Paketlemesi göz atabilirsiniz.

ANE Paketlemesinin Yapılması

Artık hem swc hem de java kütüphanemiz hazır olduğuna göre elimizde iki adet dosya bulunmakta: alertDialog.jar ve AlertDialogSample.swc. Bu dosyalarla birlikte çeşitli ayarlamalar yaparak ANE paketlemesi yapacağız. Bunun için daha önce indirmiş olduğumuz AIR SDK’dan yararlanacağız.Şimdi masaüstümüzde bir klasör oluşturalım ve içeriği aşağıdaki resimdeki gibi olsun.

build-ane-1

İlk olarak “AlertDialogSample.swc” dosyasını bu dizine kopyalayın. Bu dosyayı winrar ya da türevinde açarak içindeki “library.swf” dosyasını oluşturduğunuz klasörlere(Android-ARM,Android-x86 ve default) çıkartın.
Daha sonra ise “alertdialogsample.jar” dosyasını Android-x86 ve Android-ARM klasörleri altına kopyalayın. Son durumda klasör yapımız aşağıdaki şekildeyse eğer bir sonraki aşamaya geçebiliriz.

build-ane-2

Şimdi bulunduğunuz dizinde(Build Ane dosyası benim için) “extension.xml” adında yeni bir dosya oluşturun. Bu dosyanın içeriği aşağıdaki gibi olsun.

/*id olarak Action Script kütüphanesini oluştururken verdiğiniz extensionID'yi set ediyoruz.
Bu sayede köprü kuracağız.
nativelibrary olarak oluşturduğunuz jar dosyasının adını veriyoruz.
initializer ve finalizer olarak Java tarafında yazdığımız AlertExtension sınıfının tam paket adresini veriyoruz.
Burası yanlış yapılması en muhtemel noktadır. Bilgileri dikkatle kontrol ediniz. Aksi durumda Action Script kodları ile Java kodları arasındaki bağlantı kurulamaz.*/
 
<extension xmlns="http://ns.adobe.com/air/extension/4.0">
      <id>com.demiremrece.alert.extension</id>
      <versionNumber>1</versionNumber>
      <platforms>
        <platform name="Android-ARM">
          <applicationDeployment>
            <nativeLibrary>alerdialogsample.jar</nativeLibrary>
            <initializer>demiremrece.alertdialogexample.AlertExtension</initializer>
            <finalizer>demiremrece.alertdialogexample.AlertExtension</finalizer>
          </applicationDeployment>
        </platform>
<platform name="Android-x86">
          <applicationDeployment>
            <nativeLibrary>alerdialogsample.jar</nativeLibrary>
            <initializer>demiremrece.alertdialogexample.AlertExtension</initializer>
            <finalizer>demiremrece.alertdialogexample.AlertExtension</finalizer>
          </applicationDeployment>
        </platform>
<platform name="default">
          <applicationDeployment>
          </applicationDeployment>
        </platform>
      </platforms>
</extension>

Son olarak dosya yapımız şu şekilde oldu:

build-ane-3

Bundan sonrasında terminal kullanarak ilerleyeceğiz. Öncelikle windows kullanıyorsanız cmd , mac os kullanıyorsanız terminal açarak oluşturduğunuz dosya içerisine girin.

//Dosyanızın bulunduğu dizine gidiyoruz. Build Ane benim oluşturduğum dosyaya verdiğim isim. Siz kendinizinkini yazmalısınız.
cd ~/Build\ Ane
//~ işaretini sizin AIR SDK'yı yüklediğiniz yeri bilmediğimden koyuyorum. SDK içerisindeki "adt" yardımıyla ane paketlemesi yapacağız.
 
~\AIRSDK_Compiler\bin\adt -package -target ane alertdialogsample.ane .\extension.xml -swc .\AlertDialogSample.swc -platform Android-ARM -C Android-ARM . -platform Android-x86 -C Android-x86 . -platform default -C default .

Bu şekilde “alertdialogsample.ane” dosyası proje dizininizde oluşacaktır.
Paketlemeyle ilgili detaylı bilgi için Adobe ADT Packaging

Böylece Animate CC için nasıl Android kütüphanesini kullanarak ANE oluşturduğumuzu öğrenmiş olduk. Herhangi bir probleminizde veya zorlandığınız aşamada soru sormaktan çekinmeyin.

Hayatınızdan kod eksik olmasın. :)