Blog Archive

Monday, March 12, 2012

Daha hızlı bir Flash Builder

Tüm geliştiricilerin hızla yayılan modaya uygun olarak HTML5'e kaydığı Adobe'nin bile HTML5'e yönlendirme yaptığı şu günlerde halen Flex framework'un enterprise ölçekteki bir projede, yönetim paneli geliştirmek için biçilmiş kaftan olduğunun farkında olan ve kullanan insan sayısı da hızla azalıyor.

Flex framework'ü terketmeye zaten niyetli pek çok kişi için, bulunan bahanerlerden birisi de Büyük ölçekli projelerdeki performans sorunları. Pek çok teknolojide bir sorunla karşılaşıldığında çözüm aranır, Flash platform söz konusu olduğunda ise bahane aranıyor.


Kabul etmek gerek Adobe, Macromedia'yı satın aldığından  beri, flash platform, performans sorunları ile boğuşuyor. Ayrıca Eclipse kendi başına hantal bir IDE iken Flash platformun sorunları ile iyice kötüye gidiyor. Yani aslında Eclipse Flash projes geliştirmek için başından beri yanlış ortam. Tüm bu olumsuzluklara rağmen, sizde ısrarla yada mecburen Flash platformda proje geliştiriyorsanız, performans problemlerini aşmak için yapılması gerekenleri dereyip topladım ve buraya yazıyorum. Birileri için yararlı olacağını umuyorum.

1. Embed dosyalar:

Embed edilen yani proje içine gömülen dosyalar, değişebilen veriler değildir. Bu nedenle her derlemeye katılmamalıdır. Ancak embed ile kastettiğimiz dosyaların arasına fontları dahil etmiyoruz. O ayrı bir maddede incelenecek.  Embed dosyaları ayrı bir Library projede toplayın, O Library projesinde Embed dosyaları bir class içinde static sabitler olarak belirleyebilirsiniz. Bu Library projesini swc olarak ve RSL (Runtime Shared Library) asıl projenize dahil edebilirsniz.
Package Explorer içinde boş bir yere sağ tıklayarak bu menüye ulaşabilirsiniz.


Library projesi içinde Embed dosyalar için bir class oluşturun ve  tüm Embed dosyalarınızı bu  class içinde  tanımayın.

Projenizin üzerine sağ tıklayın be propeties seçeneğpine tıklayın. Böylece proje özellikleri penceresini açmış olacaksınız.

Flex Build Path sekmesinde Add Project butonuna tıklayın.
Workspace içindeki Library projeleri listesinden, Oluşturduğunuz Library Projesini seçip OK butonuna basınız
Library Projeleri listesinden, eklediğimiz projeyi seçip, LinkType üzerine çift tıklıyoruz.
Burada LinkType olarak Runtime Shared Library seçeneğini seçiyoruz
Add butonuna basıp, Library projemizin dosya adını belirliyoruz. Browser cache'inden kurtulmak için dosyanın sonuna bir versiyon numarası yazın ve her güncellemede bu versiyon numarasını değiştirin.
Bu işlemden sonra OK butonları ile açık tüm pencereleri kapatabiliriz.

2. Embed fontlar: 

Embed dosyalar gibi embed fontlar da harici bir dosyada tutulmalıdır. Bu işlem için sadece embed fontlerın yer aldığı css dosyasını swf olarak derlemek gereklidir.
Fontları embed etme işini ayrı bir css dosyası içinde yapın. Çünkü bu css dosyasını swf olarak derleyeceğiz ve runtime'da projeye dahil edeceğiz.
Komut satırından css dosyasını mxmlc(flex compiler) yardımıyla derliyoruz. Bu aşamada yukarıdaki hataları alırsanız önemsizdir. Framework dosyalarını da export etmek istiyor ancak framework config dosyasında uzak bir bağlantı adresi kullanıldığı için bu hataları veriyor. Ancak css ile ilgili bir hata alırsanız hatanızı düzeltiniz.
Oluşturduğumuz derlenmiş css dosyasını projemize ActionScript ile ekliyoruz. Böylece fontları derlemek için de ek bir performans harcanmayacak.

3. Modüller:

Projeyi modüller halinde geliştirmek en doğru seçim. Flex Framework s:Module bieşenini içerir. Bir yönetim panelinin farklı ekranları farklı modüller içinde yazılabilir. Her bir module ayrı bir swf olarak derlenir ve runtime 'da projeye dahil edilir. Derleme esnasında sadece değişiklik yapılmış modüller yeninden derlenir. Bu da tüm projenin derlenmesinden daha iyidir. Ancak embed fontlar için oluşurduğumuz swf dosyasını modüller içinde de ayrıca çağırmamız gerekir.
Yeni modül oluşturmak için modülün bulunacağı klasörün üzerine sağ tıklayıp New->MXML Module seçeneğini seçin. Proje derlendiğinde Modülden oluşan swf dosyası yine aynı klasör içinde olacaktır.
Modülünüzü Projeye göre optimize ederseniz, daha düşük boyutlu olacaktır.
Modülü yüklemek için Flex Fremework'e ait ModuleLoader kullanabileceğiniz gibi kendi ModuleLoad sınfınızı da oluşturabilirsiniz. Eğer yeterince uzmansanız, kendi ModuleLoader sınıfınız ile parametrik bilgileri de Modül içine geçirebilirsiniz.

4. Eclipse Heap Status:

Eclipse, malesef hafıza organizasyonu bakımından çok başarılı bir IDE değil. İlk açıldığı anda yüksek performans ile çalışırken zamanla performansının düştüğünü siz de farketmiş olmalısınız. Eclipse IDE'nin manuel çalışan bir Grabage Collector aracı var. 
Window Menüsünden Prefencences seçeneğini seçin.
General başlığında Show Heap Status seçeneğini işaretleyin ve OK butonuna basın
Hep Status Aracı pencrenin sağ alt köşesinde belirecektir, onu istediğiniz yere taşıyabilirsiniz. Sarı bar kullanılan heap ram miktarını gösterir. Biraz çalıştıkç bunun arttığını gözlemleyebilirsiniz. Böyle durumlarda çöp kutusu ikonlu butona basıp, belleği temizleyebilirsiniz.

5. Oracle JRockit:

Standard javaya göre JROckit daha yüksek performans sağlamaktadır. Flashbuilder'i standalone olarak kullanıyorsanız, program kendi içinde kullancağı JRE ile birlikte yüklenir. JRockit kullanmak için Oracle JRockit 'i indirip bilgisayarınıza kurun.

Ardından Flash Builder'in yüklü olduğu dizini açıp FlashBuilder.ini dosyasını bulun. Öncelikle bu dosyayı yazılabilir olarak ayarlamalısınız.
Açtığnız dosyanın orjinali şu şekildedir:

-startup
plugins/org.eclipse.equinox.launcher_1.0.201.R35x_v20090715.jar
--launcher.library
plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.0.200.v20090519
-nl
en_US
-vmargs
-Xms256m
-Xmx512m
-XX:MaxPermSize=256m
-XX:PermSize=64m
-Djava.net.preferIPv4Stack=true
-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=dropins



Bu dosyayı şu şekilde düzenleyin:

-showsplash
org.eclipse.platform
-vm "C:Program Files/Java/jrockit-jdk1.6.0_29-R28.2.2-4.1.0/bin/javaw.exe"
-startup
eclipse/plugins/org.eclipse.equinox.launcher_1.2.0.v20110502.jar
--launcher.library
eclipse/plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.100.v20110502
--launcher.defaultAction
openFile
-nl
en_US
-vmargs
-Xms512m
-Xmx1024m
-XgcPrio:deterministic
-XpauseTarget:20
-XXcompactratio:1
-XX:MaxPermSize=256m
-XX:PermSize=64m
-XX:+UseParallelGC
-Dorg.eclipse.equinox.p2.reconciler.dropins.directory=eclipse/dropins
-Declipse.application=com.adobe.flexbuilder.standalone.FlashBuilderApplication


Burada -Xms512m ve -Xmx1024m değerleri biraz yüksek değerlerdir. Benim bilgisayrım i5 işlemcili ve 8GB ram'li, Kendi bilgisayarınızın performansını buna göre kıyaslayıp daha yüksek ve daha düşük değerler verebilirsiniz. Ayrıca -vm parametresinde pelirtilen JRocket yolunu da kendi bilgisayarınıza göre uyarlamayı unutmayın.

Son olarak Eclipse içinden JRE path'ini tanımlamak gerekli.
Window->Preferences menüsünden Installed JRE's başlığına gelin ve ADD butonuna tıklayın.
Burada Standard JVM seçenği ile Next diyoruz
Directory butonuna basıp JRockit'in yüklü olduğu dizini seçiyoruz.  Son olarak Finish butonuna basıp bitiriyoruz.

6. Ant Builder ile multi thread MXMLC compile:

Henüz bunu test edemedim ama meraklısı için buradaki makale faydalı olacaktır.

Sunday, January 2, 2011

Post SocialPhone Kurtarıcımız "Hero" ve kadim dostu "Burrito"


Adobe Flex framework'unun yeni sürümü Flex 4.5 yada Adobe'nin alpha adıyala Flex Hero. Bir kaç aydır Beta olarak dağıtılmakta. Şimdilerde birde ona yarenlik eden bir IDE var. FlashBuilder'in yeni sürümü "Burrito"

Hatırlayacak olursak, Flex 4 içinde alpha ismi olarak Gumbo seçilmişti. Gumbo meğersem proje yöneticisinin soyadı imiş.acaba "Burrito" kim?

neyse nedir bu "Burrito" ve "Hero" yada Hero niye Hero(Kahraman). Biraz hafızamızı yoklarsak en son Flash CS5 ile Adobe, IPhone için uygulama geliştirebilmeyi sağlamıştı. Ama IPhone gibi "Yavaş" işlemcilili bir telefon ile  Flash gibi "Hantal" bir sistem bir arada olmuyor. Önceleri steve jobs "IPhone'a flash sokmam" dedi. Ardında anlaşıldı ki zaten "IPhone flash kaldırmaz". Sonra Android geldi. Yüksek performanslı telefon. Tüm Telefon üreticileri çok beğendi. 1 GHz işlemci ile yine Adobe'un ağzı sulandı. İşte Hero'muz burada sahneye girmeye hazırlanıyor.

Sosyal Ceptelefonları için yazılım geliştrmenin zahmetli, pahalı ve ağır ilerleyen bir iş olduğunu gören Adobe, birazda bu pazarsa söz sahibi olma arzusundan, önce bir Android SDK çıkartı ama geliştiriciler için karmaşık gelince bunu Flex'e entegre etti. Adı da Hero oldu.

Hero'yu buradan indirebilirsiniz :
http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+Hero

yada Hero 'su içinde Burrito'yu buradan indirebilirsiniz:
http://www.adobe.com/cfusion/entitlement/index.cfm?e=labs_flashbuilder_burrito

ilk Hero uygulamamızda dikkati çeken ilk şey MobileApplication tag'i ile uygulamanın oluşturulmuş olması. Demek ki Adobe AIR'in gerçektende her platformda çalışamayacağını anlamış. Mobil uygulama kavramına geri dönmüş.





























Eğer uygulamadan bir release build alırsanız. .apk uzantılı Android paket dosyasını görebilirsiniz.


















Android uygulaması geliştirenler apk dosyasını yakınan tanırlar.Ama detaylı bilgiyi Wikipedia'da apk başlığında bulabilirsiniz. Burada okuyacağınız gibi apk, jar benzeri bir sıkıştırılmış dosya paketi. Yani bu dosyanın uzantısını .zip yapıp açabilirniz. İçinde de tipik apk paketleri çıkar. Ama birde .swf çıkacaktır.
















Aradığımız .swf dosyası da assets klasörünün içinde. Yani bu şu demek oluyor. Tipik AIR uygulamalarında olduğu gibi paket bir flash oynatıcı birde flash swf dosyası ile çalışmakta.

Henüz bu şekilde geliştirilmiş bir uygulamanın Android işletim sistemli bir telefonda performansını test edemedim. Onu da başka bir yazı konusu yapalım.

Friday, October 15, 2010

AIR ve Flex ile Unzip yapmak

Bu class'ı yazarken Javascript ile yazılmış http://help.adobe.com/en_US/AIR/1.5/devappshtml/WS5b3ccc516d4fbf351e63e3d118666ade46-7d53.html örneğin actionsctipt 3.0 ile yazılmış hali.

package com.egnity
{
import flash.filesystem.File;
import flash.filesystem.FileMode;
import flash.filesystem.FileStream;
import flash.utils.ByteArray;
import flash.utils.CompressionAlgorithm;
import flash.utils.Endian;

public class UnzipFile
{

public function UnzipFile()
{

}
public function unzip(zipFilePath:String,targetPath:String):void{
var bytes:ByteArray= new ByteArray();
var flNameLenght:int;
var xfldLength:int;
var offset:int;
var compSize:int;
var uncompSize:Number;
var compMethod:Object;
var signature:int;
var output;
var flNameLength:int;
var fileName:String
var zipFile:File = new File(zipFilePath);
var zipStream:FileStream = new FileStream();
zipStream.open(zipFile,FileMode.READ);
bytes.endian = Endian.LITTLE_ENDIAN;
while(zipStream.position
zipStream.readBytes(bytes,0,30);
bytes.position =0;
signature = bytes.readInt();
if(signature!=0x04034b50){
break;
}
bytes.position=8;
compMethod = bytes.readByte();
offset = 0;    // stores length of variable portion of metadata
bytes.position = 26;  // offset to file name length
flNameLength = bytes.readShort();    // store file name
offset += flNameLength;     // add length of file name
bytes.position = 28;    // offset to extra field length
xfldLength = bytes.readShort();
offset += xfldLength;    // add length of extra field
// read compressed file to offset 0 of bytes; for uncompressed files
// the compressed and uncompressed size is the same
// read variable length bytes between fixed-length header and compressed file data
zipStream.readBytes(bytes, 30, offset);
bytes.position = 30;
fileName = bytes.readUTFBytes(flNameLength); // read file name
output += fileName + "
"; // write file name to text area
bytes.position = 18;
compSize = bytes.readUnsignedInt();  // store size of compressed portion
output += "\tCompressed size is: " + compSize + '
';
bytes.position = 22;  // offset to uncompressed size
uncompSize = bytes.readUnsignedInt();  // store uncompressed size
zipStream.readBytes(bytes, 0, compSize);
if (compMethod == 8) // if file is compressed, uncompress
{
bytes.uncompress(CompressionAlgorithm.DEFLATE);
}
outFile(fileName, bytes,targetPath);   // call outFile() to write out the file
}
}
private function outFile(fileName:String, data:ByteArray,targetPath:String)
{
var outFile:File = new File(targetPath+"/"+fileName)
var outStream:FileStream = new FileStream();
// open output file stream in WRITE mode
outStream.open(outFile, FileMode.WRITE);
// write out the file
outStream.writeBytes(data, 0, data.length);
// close it
outStream.close();
}
}
}


kullanımı ise şöyle 

var unzip:UnzipFile = new UnzipFile();
unzip.unzip(ornek.zip.hedefDirectory);

Saturday, July 10, 2010

Flash cs5'te Emebeded Font Problemi Nasıl Çözülür?

Üzerinde çalıştığım projede Flash CS5 kullanıyordum ve bir problemle karşılaştım. Bir kaç deneme yaptıktan sonra sorunu anladım. Aynı Font ailesinden iki fontu (Örneğin Arial Regular ve Arial Bold) embed ettiğimde. Bunlardan yanlızca bir tanesi Classical Text (nağmı diğer TextField) içinde çalışıyordu! TLF Text kütüphanesini kullanmak istemiyordum çünkü kütüphanesini RSL ile swc olarak dışarıya çıkarttığım halde swf'nin boyutunu 70 Kb etkiliyordu. Bu proje için pekte kabul edilebilir bir rakam değil. Ama buna rağmen sorunu çözemezsem kullanmaya razıydım.


Küçük bir test uygulaması oluşturup deneme yaptım.


ve bu Dinamic Classic Text içerisine ActionScript ile yazı yerleştirdim.

txtDeneme1.text="Deneme";
txtDeneme2.text="Deneme";


sonuç:

yani gerçekten bir problem var. Aynı aileden iki yazı tipi aynı anda embed edildiğinde yalnızca bir tanesi kullanılabiliyor. Bu problemi iki şekilde çözmeyi başardım. 1. Metod Dynamic Classical Text'lerden kalın olacak olanın render HTML özelliğini etkin hale getirdim ve actionScript'i şu şekilde değiştirdim:

txtDeneme1.text="Deneme";
txtDeneme2.htmlText="Deneme";
evet oldukça kötü bir yöntem olduğunun bende farkındayım ama çalıştı.


ikinci method ise daha kullanışlı. Doğrudan TextFormat üzerinden değişiklik yapmak:

import flash.text.TextFormat;
import flash.text.TextField;

txtDeneme1.text="Deneme";
txtDeneme2.text="Deneme";
var tf2:TextFormat = (txtDeneme2 as TextField).getTextFormat();
tf2.bold=true;
(txtDeneme2 as TextField).setTextFormat(tf2);
bu kodlarla çalışan uygulama ise şöyle:

ama bu method'da bu şekliyle kullanışlı değil tabiki. Bu yöntemi biraz daha geliştirmeye karar verdim embed ettiğim fontları Class olarak tanımladım:


sonrada TextFormat ayarlamalarını dinamik olarak yaptım:
import flash.text.TextFormat;
import flash.text.TextField;

Font.registerFont(embededArialBold);
Font.registerFont(embededArialRegular);

txtDeneme1.text="Deneme";
txtDeneme2.text="Deneme";

var arialBoldTextFormat:TextFormat= new TextFormat();
arialBoldTextFormat.font = "Arial";
arialBoldTextFormat.bold = true;
txtDeneme2.setTextFormat(arialBoldTextFormat);

var arialRegularTextFormat:TextFormat= new TextFormat();
arialRegularTextFormat.font = "Arial";
arialRegularTextFormat.bold = false;
txtDeneme2.setTextFormat(arialBoldTextFormat);
ve sorunu çözdüm. Ama bu bir bug ve bu kadar zahmette girmek yerine keşke sorunu Adobe çözseydi :(

Friday, May 28, 2010

RTMP(Real Time Messaging Protocol) Protokolü

Diyelim ki Flash player kullanarak bir oyun yazmak istiyoruz. Çok kullanıcılı olmasını da istiyoruz. İşi biraz basit tutalım ve diyelim ki tic-tac-toe gibi bir oyun.
Bu noktada karşımıza ilk çıkan sorun hamlelerin oyuncular arasında iletilmesi olacaktır. O halde problemimizi daha basit bir çözüme odaklayalım ve diyelim ki eğer oyuncular arasında sohbeti sağlayabilirsek, aynı şekilde de hamlelerin iletişimini de sağlayabiliriz.
Flash Player'in ilk sürümlerinden bu işi yapmak için XMLSocket kullanılıyordu. Java, C++ gibi sistem kaynaklarını ve ağı kullanabilecek bir dille XMLSocket Server uygulaması yazılıyor ve XMLSocket sınıfı ile haberleşme sağlanıyordu. Bazende Flash programcıları hazır bir socket server kullanmayı tercih ediyorlardı. Hatta bu sunuculardan en meşhuruda smartfoxserver olsa gerek.

XMLSocket sınıfı halen kullanılabilir durumda olmasına rağmen bu gün pek çok multiplayer oyun geliştiricisi FMS(Flash Media Server), Red5, WebOrb gibi sunucuları tercih etmektedir. Bu sunucuları XMLSocket server uygulamalarından ayıran en önemli özellik ise RTMP protokolü üzerinden AMF mesajlaşma formatı ile haberleşme sağlıyor olmasıdır.

RTMP: Real Time Messaging Protocol(Gerçek zamanlı mesajlaşma protokolü) anlamına gelmektedir. Bu protokol üzerinden serialize edilebilen nesneler, Ses ve Video streamleri taşınabilmektedir. TCP üzerinden bir portla sunucu ile çift yönlü haberleşme sağlar. Çift yönlü kavramı şunu alatır: Flash Player sunucuya bilgi gönderebildiği gibi , sunucu da ,"her hangi bir talep olmasa da", Flash Player'a istediği anda bilgi gönderebilir. Bu anlamda HTTP protokölü tek yönlüdür. HTTP protoklünde sunucudan bilgi almak için istemcinin (browser yada flash player) istekte bulunması gereklidir. RTMP bağlatısının davranışarını denetlemek için kullanılan sunucuya ait (Red5, FMS yada WebOrb) API kullanılarak bir uygulama geliştirilir ve bağlantı bu uygulamaya yapılır.

RTMP Protoklünün bazı türevleri de vardır.

RTMPT : Mesajlaşmanın güvenlik duvarına takılması durumunda tünel üzerinden açık bir portla (çoğunlukla 80 numaralı port (HTTP portu) tercih edilir. Çünkü hep açıktır. ) yürütülmesi için kullanılır.

RTMPS : Mesajlaşmanın başında bir şifre ile kimlik doğrulaması yapıp sonra mesajlaşmaya müsade edilen protokoldür.

RTMPE : Mesajlaşmanın güvenli bir kanaldan kriptolu olarak yapılmasını sağlar.

RTMFP : RTMP protokolünün diğer tüm türevlerinde haberleşme Flash Player ile Sunucu arasında yapılır. Eğer iki Flash Player haberleşecekse, bu sunucu üzerinden gerçekleştirilir. Bu da sunucunun kaynaklarını tüketir, haberleşmeyi yavaşlatır ve aşırı bant genişliği kullanımını sağlar.
RTMFP ise bu türden haberleşmeler için geliştirilmiştir. P2P haberleşmeye müsade eder. Bu protokolün nasıl çalıştığını daha detaylı olarak daha sonraki yazılarımda anlatacağım.


RTMP protoklü ile bilikte kullanılan yardımcı sınıflar:

NetConnection: NetConnection sunucu ile bağlantıyı kurmak için kullanılır. Bu esnada sunucuya çeşitli parametreler gönderilebilir. Bağlantının başarısız olması, sonradan kopması, sunucu tarafından reddedilmesi yada başarılı olması gibi durumlarda bir olay tetiklenecektir. Ayrıca sunucu üzerinde bağlantı kurulan uygulamaya ait "public" özniteliğindeki foksiyonları da çağırabilir. Bu çağrıdan geriye dönen değerleri alabilir.

RemoteObject : Sunucu üzerinde bağlantı kurulan uygulama aslında bir class dosyasıdır. RemoteObject ise o class'tan türetilmiş bir nesne gibi düşünebilir. Uzaktaki class üzerinde "public" öznitelikli fonksiyonları sanki kendi uygulamamızdaymış gibi çağırabiliriz.

SharedObject: Çoğu geliştirici SharedObject sınıfını local olarak kullanmış yada kullanmaktadır. Oysaki RTMP protoklü ile SharedObject sınıfı sunucu üzerinde kullanılabilmektedir. SharedObject 'i RTMP ile uzak sunucuda kullanmak multiplayer oyunlar için çok işlevseldir. Çünkü bu haliyle SharedObject'e ait bir kopya bir oyuncuda, bir kopya sunucuda, bir koya ise diğer oyuncu/oyunuclar da tutulmaktadır. Herhangibirisi (sunucu yada istemci) SharedObject üzerinde bir değişiklik yaptığında bu durum anında diğer taraflara da iletilmekte ve bir olay tetiklenmektedir.

Bu sınıflar dışında daha pek çok sınıf vardır. Daha ileriki yazılarımda örneklendirilmiş olarak hepsini anlatmaya çalışacağım.

AmfPHP ile Flash Remoting'e Giriş(Flash ile veri tabanı arasında XML olmadan veri alışverişi yapacağız)

Flash ile ActionScript kullananların şu ana kadarki en büyük korkulu rüyası veri tabanı ile iletişim kurmaktı herhalde. Çünkü Flash doğrudan veri tabanından veri alamaz. Doğrudan veri tabanına veri yazamaz.

Adobe Flex Data Services ürününü çıkardığında işte bu ve benzeri sorunları çözme yoluna gitti. Flex Data Services, Java Programlama Dili ile server taraflı uygulamalaları, class olarak yazdıktan sonra, Flash uygulamalarınızla bu classlardan nesne yaratma olanağı sunuyor idi.

XML ile iletişimde farklı olarak Adobe Flex Data Services ürünü flash ile Binary iletişim kuruyordu. Bu da XML için kullandığınız Tag ‘ları kullanmamanız böylece daha yalın veriler ile alışveriş yapmanız anlamına geliyordu. Adobe iletişimde kullandığı bu mesaj formatına Adobe Messaging Format ismini verdi. Bu şekilde AMF0 ortaya çıktı. Bu gün bu format revize edildi ve AMF3 oldu. Ancak siz haberleşmenizde hala AMF0 ve AMF3 tercihi yapabiliyorsunuz.

Daha sonra adobe firması bu ürünün adını Adobe Live Cycle Data Services olarak değiştirdi. Açık kaynak kod cephesinde de bu ürünün yerini doldurmak amacıyla çeşitli ürünler çıktı. Bu ürünlerden en popüleri olarak RED5 ‘i burada örnek vermek yerinde olur.

Adobe bir boşluğu doldurmuştu ama bu ürünle birlikte önemli bir boşluk daha ortaya çıkmıştı. PHP, ASP.NET dillerini kullanarak server taraflı kod yazan ve Flash’ı bu şekilde veri tabanı ile haberleştiren kişiler için de bu teknikleri kullanabilecekleri bir ürün gerekliydi. Bu amaçla 3. nesil program olarak birkaç çözüm geldi. Bu çözümlerden en popüler ikisinin ismi AmfPHP ve WebOrb.

WebOrb, php,.NET,Java ve Ruby on Rails için 4 ayrı sürüme sahiptir ve .NET için olan sürümü RTMP dahil Adobe Live Cycle Data Services ürününün Java ile yapabildiği herşeyi yapabilir.

AmfPHP ise sadece yazdığınız PHP class dosyasını uzaktan çalıştırmanızı sağlar.

AmfPHP’yi www.amfphp.org adresinden indirebilirsiniz. Yada buraya tıklayarak doğrudan indirebilirsiniz. Şu anki kararlı son sürüm amfphp 1.2 ve son sürüm ise amfphp 1.9 betadır.

AmfPHP ‘yi indirdikten sonra web server’ınızdaki document root klasörüne açınız. yani http://localhost/amfphp

şeklinde AmfPHP’ye erişebilmeliyiz. Eğer herşey yolunda ise

http://localhost/amfphp/gateway.php

adresinden aşağıdaki gibi bir görüntü alırsınız:

MMİstanbul

eğer Load the service browser linkine tıklarsanız. Oluşturduğunuz servisleri görmek ve olarla test sürüşü yapma şansına sahip olursunuz. Ancak ilk kez service browser’ı açıyorsanız o zaman AmfPHP size hangi iletişim kuralını kullanacağınızı sorar.

MMİstanbul

AmfPHP’yi başka bir klasöre kopyalarsanız yada uzak sunucuya atarsanız yine aynı soru ile karşılaşırsınız. Bu soruya bir kez yanıtvermeden de flash yada flex ile AmfPHP’ye bağlantı kuramazsınız

AmfPHP ile bir web servisi oluşturmak için tek yapmanız gereken servisinizi bir class olarak hazırlayıp amfphp klasörü içindeki services klasörüne atmak olacaktır.

Ancak buna geçmeden önce AmfPHP ile yapılacak son bir işlemimiz daha var. AmfPHP standart olarak ilk kurulduğunda ISO-8859-1 karakter setiyle çalışmaktadır. Oysaki bu karakter seti ile türkçe karakterleri kullanmamız çok zor olur. Bu karakter seti ayarlamasını UTF-8 ‘e dönüştürmeliyiz. Bunun için amfphp kök dizinindeki gateway.php dosyasını açıp şu satırı bulun:

//Read above large note for explanation of charset handling
//The main contributor (Patrick Mineault) is French,
//so don't be afraid if he forgot to turn off iconv by default!
$gateway->setCharsetHandler("utf8_decode", "ISO-8859-1", "ISO-8859-1");

üstteki üç satır açıklama satırı. Alttaki satır ise karakter setinin belirlendiği satır. Bu satırı şu şekilde yeniden düzenleyin:

$gateway->setCharsetHandler("utf8_decode", "utf-8", "utf-8");

Şimdi Flash Remoting ‘e en basit girişi yapabileceğimiz AmfPHP ‘yi kullanarak, bir veri tabanına kayıt yapalım. Öncelikle MySQL ile bir veri tabanı ve tablo oluşturalım:

CREATE DATABASE `flash_test_db` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE `flash_test_db`.`kisiler` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR( 20 ) NOT NULL ,
`tel` VARCHAR( 11 ) NOT NULL ,
PRIMARY KEY ( `id` )
) ENGINE = InnoDB

veri tabanımızın adı : flashtestdb ve kişi isimleri ve telefon numaralarını tutacağımız tablonun ismi ise kisiler oldu.

Bu veritabanında yetkili kullanıcıyı oluşturalım ve bu veri tabanı üzerinde yetkilendirelim

CREATE USER 'amfphpuser'@'localhost' IDENTIFIED BY 'amfphppass';

GRANT USAGE ON * . * TO 'amfphpuser'@'localhost' IDENTIFIED BY 'amfphppass' WITH MAX_QUERIES_PER_HOUR 0 MAX_CONNECTIONS_PER_HOUR 0 MAX_UPDATES_PER_HOUR 0 MAX_USER_CONNECTIONS 0 ;

GRANT ALL PRIVILEGES ON `flash\_test\_db` . * TO 'amfphpuser'@'localhost' WITH GRANT OPTION ;

bu veri tabanına ulaşacak php class’ını oluşturalım:

dbObj = mysql_pconnect(DATABASE_SERVER, DATABASE_USERNAME, DATABASE_PASSWORD) or (trigger_error(mysql_error(),E_USER_ERROR));
mysql_select_db(DATABASE_NAME, $this->dbObj);
}
private function SQL($sql){
$queryReturn= mysql_query($sql,$this->dbObj) or trigger_error("AMFPHP şu hatayı döndürdü hata oluşan class: 'connect_to_mysql' hata veri tabanında SELECT cümlesi işlenirken oldu. mysql tarafından döndürlen hata :\nError:" . mysql_error());
return $queryReturn;
}
private function insertSQL($table,$fields){
$insertSQL="INSERT INTO `".$this->dbPrepend.$table."` (";
$fieldSQL="";
$valueSQL="";
foreach ($fields as $field=>$value){
if($fieldSQL!="") $fieldSQL.=",";
$fieldSQL.="`".$field."`";
if($valueSQL!="") $valueSQL.=",";
$valueSQL.="'".$value."'";
}
$insertSQL.=$fieldSQL.") VALUES (";
$insertSQL.=$valueSQL.");";
mysql_query($insertSQL,$this->dbObj) or trigger_error("AMFPHP şu hatayı döndürdü hata oluşan class: 'connect_to_mysql' hata veri tabanında INSERT cümlesi işlenirken oldu. mysql tarafından döndürlen hata :\nError:" . mysql_error());
return true;
}
public function insertPerson($person){
$values= array(
'name' =>$person['name'],
'tel' =>$person['tel']
);
$this->insertSQL('kisiler',$values);
}
public function getAllPersons(){
$personSQL="SELECT * FROM `kisiler`";
return $this->SQL($personSQL);
}
}
?>

bu php class’ı PHP5 standarlarına göre yazıldı. Ancak PHP4’e de uygun yazıldı. eğer public ve private bildirimlerini silerseniz PHP4 ile de çalışacaktır. Yazdığımız class dosyasını amfphp klasöründeki services klasörünün altına kaydediyoruz.

Nesne Yönelimli Programlamanın en temel unsurlarından olan public ve private bildirimleri ile çalışmak çok önemlidir. Yazdığımız php cllass’ındaki private yordamlara (fonksiyon) flashRemoting ile erişmemiz mümkün değil. Bu yolla veri tabanını ve uygulamamızı korumuş oluyoruz.

Şimdi de flash dosyamızı oluşturalım:

MMİstanbul

ve action script kodları da şöyle:

btnGonder.addEventListener(MouseEvent.CLICK,btnGonderClicked);
function btnGonderClicked(event:MouseEvent){
var postObj:Object={name:txtAdSoyad.text,tel:txtTelefon.text}
var nc:NetConnection= new NetConnection();
var resp:Responder = new Responder(postSuccessHandler,faultHandler);
nc.connect("http://localhost/amfphp/gateway.php");
nc.call("connect_to_mysql.insertPerson",resp,postObj);
}
function postSuccessHandler(result:Object){
trace("Kayıt Girişi başarılı");
}
function faultHandler(fault:Object){
trace("Bağlantı Hatası");
}

burada yapılan işlem kabaca şöyle:

http://localhost/amfphp/gateway.php adresine bir bağlantı oluşturuluyor. Bu bağlantıyı oluşturan bağlantı nesnesinin türü NetConnection, ismi ise nc. Bu nesnenin call yordamı bizim yazdığımız php class’ına erişmemizi sağlıyor. sınıfadı.yordam_adı şekilnde hangi yordama bağlanacağımızı ilk parametre ile anltoyoruz.

ikinci parametre bu işlem gerçekleştiğinde dönen bilgileri yakalamak için kullanılacak Responder tipinde resp nesnesi. Bu nesne ise iki türlü sonucun olabilirliği ile çalışıyor. Birisi fonksiyonun (yordamın) başarıyla çalışması ve geriye bir değer döndürmesi. Diğeri ise bir hata oluşması.

üçüncü parametre isteğe bağlıdır. Son parametre değildir. Üçüncü parametreden itibaren istediğimiz kadar parametre yazabiliriz. Bu parametreler çağırdığımız yordama geçirilecektir. Bizim yazdığımız insertPerson yordamı bir parametre aldığı için bizde bir parametre göndermeyi tercih ettik. Gönderdiğimiz parametre bir Object idi. Bu türden parametreler göndermeye mecbur değiliz. Sadece öreneğimizin zengin olması bakımından, nesneleri de parametre olarak geçirbileceğimizi göstermek ve geçirdiğimiz nesne parametreleri PHP ile nasıl çözeceğimizi de göstermek amacıyla Object geçirdik.

flash’ı çalıştıralım ve bir veri girişi yapalım :

MMİstanbul

bu işlem sonucunda veri tabanına veri girişi yapılıp yapılmadığını phpmyadmin ile kontrol edelim :

MMİstanbul

service borwser’ı tekrar çalıştıralım:

MMİstanbul

yazdığımız class soltarafta görünüyor. Sağda ise class’daki public fonksiyonlar görünüyor. getAllPersons fonksiyonunu seçip call butonuna bastığımda alt kısımda fonksiyon çaıştığında geriye döndürdüğü değerleri görüyoruz. Eğer Flex ile çalışıyorsanız o zaman aşağıdaki kodu kullanabilirsiniz.

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute">
<mx:Script>
<![CDATA[
public function btnGonderClicked(event:MouseEvent):void{
var postObj:Object={name:txtAdSoyad.text,tel:txtTelefon.text}
var nc:NetConnection= new NetConnection();
var resp:Responder = new Responder(postSuccessHandler,faultHandler);
nc.connect("http://localhost/amfphp/gateway.php");
nc.call("connect_to_mysql.insertPerson",resp,postObj);
}
private function postSuccessHandler(result:Object):void{
trace("Kayıt Girişi başarılı");
}
private function faultHandler(fault:Object):void{
trace("Bağlantı Hatası");
}
]]>

</mx:Script>
<mx:Panel x="10" y="10" width="370" height="238" layout="absolute">

<mx:Form right="0" left="0" bottom="50" top="0">
<mx:FormItem label="Adı Soyadı">
<mx:TextInput id="txtAdSoyad"/>

</mx:FormItem>
<mx:FormItem label="Telefonu">
<mx:TextInput id="txtTelefon"/>
</mx:FormItem>
</mx:Form>
<mx:Button x="187" y="156" label="Gönder" id="btnGonder" click="btnGonderClicked(event)"/>

</mx:Panel>

</mx:Application>


php class’ındaki fonksiyondan geriye dönen değerler Responder clasından tanımladığımız nesnenin result olayına atadığımız fonksiyona parametre olarak döner. Yani yukarıdaki iki örnekte de eğer fonksiyon bir değer döndürüyorsa

private function postSuccessHandler(result:Object):void{

fonksiyonundaki result bu dönen değeri alabilir. result ismi ile tanımladığımız nesne illaki Object olmak zorunda değildir. php class’ından hangi türde değer dönüyorsa ona göre ihtiyaç duyduğunuz tipte tanımlayabilirsiniz.

Followers