/ ActionScript3

Adobe Native Extension #3 : iOS

Bir önceki yazımda Android kütüphanesi geliştirmiş ve ActionScript bağlantısını kurarak AnimateCC’ye extension geliştirmiştik. ANE nedir, neden ihtiyaç duyuyoruz sorularının cevabını tekrar gözden geçirmek için sizi öncelikle şuraya alayım: Adobe Air Native Extension

Bu yazımda Objective C kullanarak daha önceki yazımda olduğu gibi bir alert dialog göstermek için native kütüphane yazacağım. Sonra bu kütüphaneyle ANE paketlemesi yapacağım.

Gerekli Ortamın Kurulması

ANE geliştirebilmemiz için gerekenler: AIR 3 SDK , ActionScript kod yazabilmek için bir IDE (ben Adobe Flash Builder 4.7 kullanacağım) ve Objective C kütüphanesi geliştirmek için XCode

XCode için:
https://developer.apple.com/xcode/

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 Objective C kodumuz ve AIR uygulaması arasında arayüz görevi görecek bir ActionScript kütüphanesi yazacağız. Yazacağımız kod Android için yazdığımız kütüphaneyle aynı olacak. 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 Objective C tarafındaki bir methodu tetikleyecek. Bu metod da ekrana bir alert dialog getirerek, gönderdiğimiz mesajı yayınlayacak.

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,"");
     }
   }
/*iOS 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 iOS-Objective C tarafını yazalım.

Objective C Kütüphanesinin Oluşturulması (iOS Tarafı)

Amacımız .a uzantılı bir kütüphane oluşturmak olduğundan, öncelikle bir Cocoa Touch Static Library projesi oluşturmamız lazım. Sırasıyla adımlar şu şekilde:

ios-ane-1

ios-ane-2

Proje dosyamız oluştuktan sonra, ilk olarak projemizin Build Settings ayarlarına giriyoruz ve “Buid Active Architecture Only” ayarını hem debug hem de release için NO yapıyoruz. Bu şekilde kütüphanemizi derlediğimizde hem ARM hem de x86 platformu için çalışabilir bir kütüphane elde etmiş olacağız.

ios-ane-3

Buna ek olarak FlashRuntimeExtensions.h header dosyasını projemize dahil etmemiz lazım. Bu kütüphaneyi indirdiğiniz AIR SDK içerisine bulabilirsiniz. Projeye header dosyamızı eklemek için ise projeye sağ tıklayıp “Add Files to AlertDialog” seçeneğini seçiyor ve dosyanın yerini gösteriyoruz.

ios-ane-4

Bu aşamaları geçtikten sonra elimizdeki yapı aşağıdaki gibiyse, kodlamaya hazırız demektir.

ios-ane-5

AlertDialog.h’a girip aşağıdaki kodları yazalım. Burada dört tane fonksiyonumuz bulunmakta: VXIOSApiContextInitializer, VXIOSApiContextFinalizer, VXIOSApiExtInitializer, VXIOSApiExtFinalizer.

#import <Foundation/Foundation.h>
#import "FlashRuntimeExtensions.h"
 
@interface AlertDialog : NSObject
 
void AlertDialogContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet);
void AlertDialogContextFinalizer(FREContext ctx);
 
void AlertDialogExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet);
void AlertDialogExtFinalizer(void* extData);
 
@end

Yukarıda yazdığımız fonksiyonların işlevlerini detaylı bir şekilde AlertDialog.m dosyasını yazarken inceleyeceğiz. Şimdi bunu kodlayalım.

#import "AlertDialog.h"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
 
 
@implementation AlertDialog
 
FREContext *initContext;
 
void AlertDialogContextInitializer(void* extData, const uint8_t* ctxType, FREContext ctx, uint32_t* numFunctionsToTest, const FRENamedFunction** functionsToSet){
    
    // ActionScript tarafından bağlantı burada kuruluyor.
    // Bu fonksiyonda ActionScripte kullanacağımız fonksiyonları da bildiriyoruz.
    
    *numFunctionsToTest = 1; // Kaç tane fonksiyon oluşturacağız? Bizim örneğimizde sadece showAlertDialog fonksiyonu olduğundan bu kadar bir alan oluşturuyoruz.
    
    FRENamedFunction* func = (FRENamedFunction*) malloc(sizeof(FRENamedFunction) * (*numFunctionsToTest));
    
    func[0].name = (const uint8_t*) "showAlertDialog"; // fonksiyonumuzun adı
    func[0].functionData = NULL;
    func[0].function = &showAlertDialog; // fonksiyonumuzun pointer adresi
    
    
    *functionsToSet = func; // fonksiyon dizimizi bildiriyoruz
    initContext = ctx; // ortak context i bir sonraki kullanımlar için bir değişkene atayabiliriz.
    
}
 
void AlertDialogExtInitializer(void** extDataToSet, FREContextInitializer* ctxInitializerToSet, FREContextFinalizer* ctxFinalizerToSet){
    
    // Burada ekstra bir şey yapmamıza gerek yok.
    // Oluşturduğumuz context initializer ve finalizer fonksiyonlarının pointer adreslerini bildiriyoruz.
    
    *extDataToSet = NULL;
    *ctxInitializerToSet = &AlertDialogContextInitializer;
    *ctxFinalizerToSet = &AlertDialogContextFinalizer;
}
 
void AlertDialogExtFinalizer(void* extData){
}
 
void AlertDialogContextFinalizer(FREContext ctx){
}
 
 
 
NSString* getNSStringFromFreObject(FREObject object){
    
    // ActionScript tarafından gönderilen String mesajları NSString'e çevirmek için bu fonksiyonu yazdım. Direk kullanabilirsiniz.
    // Mantık olarak C tarz String, NSString e çevriliyor. Çünkü farkettiğiniz gibi tüm fonksiyonlarımızı C'de yazdık. Aldığımız parametreler de C tabanlı.
    
    uint32_t strLength = 0;
    const uint8_t * strValue = NULL;
    FREResult success = FREGetObjectAsUTF8( object, &strLength, &strValue );
    
    if ( ( FRE_OK == success ) && ( 0 < strLength ) && ( NULL != strValue ) )
    {
        return  [ NSString stringWithUTF8String: ( const char * ) strValue ];
    }
    
    else{
        return nil;
    }
    
}
 
 
FREObject showAlertDialog (FREContext context, void* functionData, uint32_t argc, FREObject argv[]) {
    
    @autoreleasepool {
        
        NSString* ourMessage = getNSStringFromFreObject(argv[0]); // Gönderdiğimiz mesajı alıyoruz. ActionScript'ten bir tane mesaj gönderdiğimizden 0.gözde parametremiz.
        
        // Basit bir dialog oluşturup mesajımızı yayınlıyoruz.
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Hello Alert"
                                                        message:ourMessage
                                                       delegate:nil
                                              cancelButtonTitle:@"OK"
                                              otherButtonTitles:nil];
        [alert show];
        
        return nil;
    }
}
 
 
@end

Kütüphanemiz hazır. Şimdi derleyebiliriz. Derlerken dikkat etmemiz gereken nokta “Generic iOS Device” seçeneğiyle çalışmamız gerektiği. Bu sayede evrensel bir iOS kütüphanesi yapmış olacağız. Herhangi bir iPhone cihazına özel olmamış olacak. Projemizi derlediğimizde gördüğünüz gibi Products altında libAlertDialog.a adında kütüphanemiz oluştu.

ios-ane-6

ANE Paketlemesinin Yapılması

Artık hem swc hem de objective c kütüphanemiz hazır olduğuna göre elimizde iki adet dosya bulunmakta: libAlertDialog.a 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.

ios-ane-7

İ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(iPhone-ARM,iPhone-x86 ve default) çıkartın.
Daha sonra ise “libAlertDialog.a” dosyasını iPhone-ARM ve iPhone-x86 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.

ios-ane-8

Ş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 .a dosyasının adını veriyoruz.
initializer ve finalizer olarak Objective C tarafında yazdığımız AlertDialogExtInitializer'ı ve AlertDialogExtFinalizer'ı 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="iPhone-ARM">
          <applicationDeployment>
            <nativeLibrary>libAlertDialog.a</nativeLibrary>
            <initializer>AlertDialogExtInitializer</initializer>
            <finalizer>AlertDialogExtFinalizer</finalizer>
          </applicationDeployment>
        </platform>
<platform name="iPhone-x86">
          <applicationDeployment>
            <nativeLibrary>libAlertDialog.a</nativeLibrary>
            <initializerAlertDialogExtInitializer</initializer>
            <finalizer>AlertDialogExtFinalizer</finalizer>
          </applicationDeployment>
        </platform>
<platform name="default">
          <applicationDeployment>
          </applicationDeployment>
        </platform>
      </platforms>
</extension>

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

ios-ane-9

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 iPhone-ARM -C iPhone-ARM . -platform iPhone-x86 -C iPhone-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 iOS 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. :)