Android

Android Wear Uygulamaları Geliştirmek

Artık akıllı kol saatleri sayesinde kullanıcı cebinden telefonunu çıkartmadan bile uygulamanızla iletişime geçebilir! O zaman, Android Wear için uygulama yazmaya ne dersiniz? Android Wear uygulamasının temel özellikleri Android Wear bir süredir pazarda ve şimdiden geniş bir kullanıcı...

Orkun Bulut Duman |

11.11.2014

Artık akıllı kol saatleri sayesinde kullanıcı cebinden telefonunu çıkartmadan bile uygulamanızla iletişime geçebilir! O zaman, Android Wear için uygulama yazmaya ne dersiniz?

 

Android Wear uygulamasının temel özellikleri

Android Wear bir süredir pazarda ve şimdiden geniş bir kullanıcı kitlesi tarafından kullanılıyor. Dikdörtgen modellerinin (Gear Live ve G Watch) yanı sıra dairesel modeli (Moto 360) de 4 Eylül'de piyasaya sürüldü. Henüz Türkiye'de satılmasa da Android Wear uygulamalarınızı şimdiden yazmak heyecan verici.

Wear uygulamaları standart Android uygulamalarına çok benziyor. Aynı bir mobil uygulamada olduğu gibi "layout" kullanıyoruz ve neredeyse aynı kütüphaneler ile kodlarımızı geliştirebiliyoruz. Ancak Wear uygulamarına özel bilinmesi gereken birkaç nokta var:

  • Wear uygulaması kol saati üzerindeki CPU'yu kullanacağı için çok daha hafif olmak zorunda. Eğer ağır işlemler yapacaksak bunları Android telefonda yapıp Wear'a aktarmak daha doğru olacaktır.
  • Uygulamamız ana ekranda çok kısa bir süre kalıyor. Eğer kullanıcı tepki vermezse uygulama arka plana atılıyor. Bu yüzden basit ve çalışma süresi kısa uygulamalar oluşturmalıyız.
  • Wear uygulamaları direkt olarak saate indirilemiyor. Saat telefona bağımlı. Telefonda Google Play'den indirilen bir uygulama Wear destekliyorsa uygulamanın Wear ayağı kol saatine Bluetooth üzerinden otomatik olarak kuruluyor.
  • Saatteki uygulamamız ile kullanıcı iki şekilde iletişime geçebilir: telefondan gönderilen bir bildiri ekranda belirdiğinde buna dokunabilir veya seslenebilir, ya da saatteki start menüsünden uygulamamızı sesle veya dokunarak başlatabilir.

 

İlk Android Wear uygulamamız

Öncelikle bir Android Wear uygulamasını nasıl yaratacağımıza bakalım. Wear uygulamaları farklı kütüphaneler kullandığından ve markete gönderilirken farklı şekilde paketlendiğinden Android Wear uygulaması geliştirirken Android Studio kullanılmasını şiddetle tavsiye ediyorum. Bu blog yazısında ben de Android Studio kullanıyor olacağım.

İlk adım, projemizi oluştururken Android Studio'ya Wear desteklediğimizi söylemek:

Bu şekilde hem telefon ayağı hem de Wear ayağı olan bir uygulama oluşturmuş oluyoruz. Navigasyon penceresine bakarak "Mobile" ve "Wear" adında iki modül oluştuğunu görebilirsiniz. Bunlar iki farklı uygulama olarak kabul edilmeli ve kodlama o şekilde yapılmalıdır. "Wear" modülünde sayfa tasarımları "rect_aktiviteismi.xml" ve "round_aktiviteismi.xml" dosyaları için ayrı ayrı yapılabilir. Bu da uygulamamızın hem dikdörtgen hem de dairesel saatlerde güzel görünmesini sağlar.

Android Wear ile alakalı özel 3 temel kütüphane bulunmakta. Bunlar, Wear bildirilerini destekleyen "Android v4 Support Library", veri senkronlamamıza yardımcı olan "Google Play Services" ve sadece wearable uygulamarında çalışıp Wear için çok kullanışlı görsel elementler sunan "UI Widgets for Wearables". Bu kütüphaneler projenizin "build.gradle" dosyasına Android Studio tarafından otomatik olarak eklenecektir. Hangi durumlarda işe yarayacaklarını ilerleyen adımlarda göreceğiz.

Eğer gerçek bir Wear kol saatiniz varsa, cihazı bilgisayara bağladıktan sonra uygulamanızı çalıştırabilir ve test edebilirsiniz ama emülatör kullanmak da mümkün. Bunun için önce AVD Manager'ı açıp yeni bir cihaz eklememiz gerekiyor. Ayarları aşağıdaki gibi yapalım:

Sonrasında "Çalıştır"'dan "wear"'ı seçerek uygulamamızı çalıştırabiliriz.

 

Özel bildiri tasarımı

Normal koşullar altında Android bizden özel bildirim tasarımı yapmamamızı istiyor. Sayfalarında, uygulamamızın telefona yüklenecek olan modülünün bildirileri düzenlemesinin daha iyi olacağını, bize sağladıkları "NotificationCompat.BigTextStyle" gibi sınıfları kullanmanın gerekliliğinden bahsetmişler. Aslına bakarsanız bu iyi bir tavsiye. Eğer Android Wear'daki her sayfayı kendimiz tasarlar, animasyonlar eklersek cihaz sayfayı yüklerken donabiliyor. İşlemciye çok yüklenmiş oluyoruz. Yine de eğer kullanıcıya spesifik bir bilgi göstermek istiyorsak, küçük kol saati ekranında uygulamamıza ait içeriği sunabileceğimiz daha iyi bir dizayn fikrimiz varsa birkaç özel bildiri ekranı tasarımı zarar vermeyeceği gibi fark yaratmamızı da kolaylaştıracaktır.

Özel bildiri oluşturmak için önce yeni bir "layout" dosyası oluşturmamız gerekiyor. Bu layout dosyası bildiri dizaynını temsil edecek. Aynı zamanda layout dosyamızı gösterecek olan bir "Activity" sınıfı yaratmalıyız.

Aktivite sınıfımız da hazır olduğu zaman bu özel bildirimimizi çağıran bir mekanızma yazmamız gerekiyor. Bildiri sadece cihazın kendisi tarafından tetiklenebiliyor. Eğer Android Wear ekranında özel bir bildiri göstereceksek bu bildiri Android Wear içerisindeki bir sınıftan veya servisten çağırılmalı. Ancak eğer kullanıcının telefonuna bir mesaj geldiği zaman, veya kullanıcı telefondan bir uygulamayı başlattığı zaman Android Wear üzerinde bu bildirimimizi göstermek istiyorsak, araya tetikleyici bir mekanizma koymalıyız. Bu mekanizma MessageApi. Telefon GoogleApiClient ile saate bağlanacak, MessageApi veya DataApi ile bildiriyi gönderecek, saatteki servis bunu yakalayacak ve özel bildiri ekranını ekranda gösterecek. Bu sistemi kurmak için gerekli tüm sınıflara ve metodlara bu blogun devamında bakacağız.

 

Android Wear'da hata ayıklamak

Android Wear uygulamalarında hata ayıklamak (debugging) çok basit. Gerek gerçek bir Wear'da çalışıyor olun gerekse de emülatörde, "logcat" aracılığı ile konsoldan uygulama akışını takip edebilirsiniz. Android aynı zamanda Bluetooth üzerinden de hata ayıklama olanağı sunuyor ancak çok kullanışlı olduğunu söyleyemeyeceğim. Emülatör üzerinden program test etme alternatifi bile bu seçenekten daha hızlı.

 

Android ile veri eşleştirme

Android telefon ile Android Wear arasındaki her türlü iletişim için "GoogleApiClient" kullanmamız gerekiyor. Google'ın sağlamış olduğu bu sınıf cihazların birbirini dinlemesini sağlıyor ve kullanımı epey basit. Aktivitemize "ConnectionCallbacks" ve "OnConnectionFailedListener" sınıflarını gerçeklememiz yeterli. Yeni bir GoogleApiClient objesi oluşturarak build() metodunu çağırıyoruz. connect() metodu ise bağlantıyı açıyor. Bağlantı sonucu ile ilgili üç metod, aşağıdaki resimde açıklamaları ile gösterilmiş. Bunları ihtiyaçlarınıza göre düzenleyebilirsiniz.

[code]
public class VeriSaglayici extends Activity implements GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    GoogleApiClient mGoogleApiClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.layout_veri_saglayici);
        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(Wearable.API)
                .build();
        mGoogleApiClient.connect();
    }

    @Override
    public void onConnectionSuspended(int i) {
        //Bağlantı durduruldu/iptal edildi.
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        //Bağlanti saglanamadı.
    }
}
[/code] 

GoogleApiClient bağlantısı sağlandı ancak cihazlarımız arasında mesaj gönderip almamız için bir bilgiye daha ihtiyacımız var: Mesajın gitmesini istediğimiz cihaz hangisi? Bir Android telefon birden çok GoogleApiClient destekleyen Bluetooth cihazına bağlı olabilir ya da GoogleApiClient bağlantısı açılmış olsa bile mesajı göndermek istediğimiz cihaz Bluetooth ağı üzerinde bulunamayabilir. Bunun sağlamasını yapmak için yine basit bir metod var:

[code]
    private String OZEL_MESAJ_ANAHTARI = "/com/gmail/orkun1675/androidwearuygulamaornegi/ornekmesaj";
    private final byte[] data = {0};

    public boolean mesajGonder() {
        ArrayList<Node> cihazlar = getNodes();
        if (cihazlar.size() < 1) {
            //Bağlı cihaz bulunamadı.
            return false;
        }
        MessageApi.SendMessageResult result = Wearable.MessageApi.sendMessage(mGoogleApiClient,
                cihazlar.get(0).getId(), OZEL_MESAJ_ANAHTARI, data).await();
        if (!result.getStatus().isSuccess()) {
            //Mesaj gönderilemedi.
            return false;
        } else {
            //Mesaj gönderildi.
            return true;
        }
    }

    private ArrayList<Node> getNodes() {
        ArrayList<Node> results = new ArrayList<Node>();
        NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(mGoogleApiClient).await();
        for (Node node : nodes.getNodes()) {
            results.add(node);
        }
        return results;
    }
[/code]

NodeApi.GetConnectedNodesResult sınıfı Wearable.NodeApi ile kullanıldığı zaman Bluetooth üzerinden bağlı olan Android Wear cihaz listesini döndürecektir. Buradaki sorguda yine GoogleApiClient kullandığımızı hatırlatmak isterim. Eğer bize döndürülen bu cihaz listesi boş ise o zaman cihazlarımız birbirine bağlanamamış demektir. Bu hatayı kullanıcıya yansıtmak yararlı olur.

Mesajı göndermek istediğimiz cihazın da adresini (id'sini) öğrendiğimize artık mesajımızı gönderebiliriz. Bu mesaj tek seferlik olarak gönderilir ve hedef mesajı aldığı anda yok olur, hafızada tutulmaz. SendMessageResult metodu GoogleApiClient bağlantımızın yanı sıra bizden mesajı tanımlamak için bir mesaj anahtarı talep eder. Bu anahtarın sadece size özel olduğundan emin olmalısınız. Son olarak eğer mesajla beraber herhangi bir veri göndermek istiyorsak (100kb sınırını geçmemelidir) bunu da metod çağrısına dâhil edebiliriz. Ben burada sadece karşıdaki cihaza ben burdayım demek istiyorum, bu yüzden veriye sadece 0 verdim.

Mesajın gönderilip gönderilmediğini yarattığımız "result" objesinin "status" değerine bakarak anlayabiliriz.

Not: Mesajı gönderen ve bağlı cihaz listesini alan metotlar "await()" kullandığı için asenkron bir görev yaratarak bunun içerisinde çağırmalısınız.

Mesajımızı gönderen kodu yazdık peki diğer cihazımız bu gelen mesajı nasıl dinleyecek? Yine kısa bir örnekle bakalım:

Mesaj olaylarını dinleyebilmek için sınıfımızın açıklamasında "MessageApi.MessageListener" sınıfını implemente etmeyi unutmamız gerekir. Daha sonra "onMessageReceived" metodunu "Override" ederek gerekli komutları çağırabiliriz.

[code]
@Override

    public void onConnected(Bundle bundle) {

        //Bağlantı sağlandı.

        Wearable.MessageApi.addListener(mGoogleApiClient, this);

        //Mesaj olaylarını dinliyoruz.

    }
    @Override
    public void onMessageReceived(MessageEvent messageEvent) {

        //Yeni bir mesaj alındı.

        if (messageEvent.getData().equals(OZEL_MESAJ_ANAHTARI)) {

            //Anahtarlar uyuştuğu için mesaj bize ait.

            byte[] data = messageEvent.getData();

            //Mesaj ile beraber gönderilen veri.

            gelenMesajIleIsYap(data);

        }

    }
    public void gelenMesajIleIsYap(byte[] data) {

        //İş yap

    }
[/code]

GoogleApiClient ile bağlantı sağlandığı zaman mesaj dinleyicisini sisteme tanıtarak/kaydederek mesaj olaylarını dinlemeye başlıyoruz. Yeni bir mesaj geldiği zaman onMessageReceived metodu çağırılıyor. getData() metodu bize mesajın kendine özel anahtarını döndürecektir. Eğer bu anahtar daha önceden mesajı gönderirken kullandığımız anahtara eşitse, mesaj bize aittir. Gelen bu mesaj ve gönderilen veri ile burada kolayca işlem yapmak mümkün.

 

DataItem ile veri göndermek

Göndermek istediğimiz mesaj basit bitlerden daha komplike olduğu zaman, örneğin bir ArrayList<String> göndermek istiyorsak, DataItem ile veri gönderimi yardımımıza koşuyor. Veri göndermede DataApi kullanmamız durumunda hem göndermek istediğimiz verinin formatı korunuyor hem de eğer cihazlar birbirine bağlı değilse veri buffer'a atılıyor ve bağlantı kurulduğunda gönderiliyor.

Bir örnek ile nasıl veri gönderileceğine bakalım:

[code]
private String OZEL_VERI_ANAHTARI = "/com/gmail/orkun1675/androidwearuygulamaornegi/ornekveri";
    private String ornekString = "ornekString";
    private int ornekInt = 123;
    private boolean ornekBoolean = true;
    private ArrayList<String> ornekStringArrayList = new ArrayList<String>() {{
        add("ornekVeri1");
        add("ornekVeri2");
        add("ornekVeri3");
    }};

    private void veriGonder() {
        PutDataMapRequest dataMap = PutDataMapRequest.create(OZEL_VERI_ANAHTARI);
        dataMap.getDataMap().putString("MyString", ornekString);
        dataMap.getDataMap().putInt("MyInt", ornekInt);
        dataMap.getDataMap().putBoolean("MyBoolean", ornekBoolean);
        dataMap.getDataMap().putStringArrayList("MyArrayList", ornekStringArrayList);
        PutDataRequest request = dataMap.asPutDataRequest();
        PendingResult<DataApi.DataItemResult> pendingResult = Wearable.DataApi.putDataItem(mGoogleApiClient, request);
    }
[/code]

Burada PutDataMapRequest içerisinde bulunan dataMap'i kullanarak verilerimizi paketliyoruz. Daha sonra DataApi ve GoogleApiClient bağlantımızı kullanarak verimizi gönderebiliyoruz. Dediğimiz gibi bu metodu çağırmak için cihaza bağlı olmak gibi bir zorunluluğumuz bulunmamakta.

 

Veri beklemek/almak ve servis kullanımı

Android Wear ve Android Phone ile nasıl basit mesajlar ve daha organize DataItem'lar gönderebileceğimize baktık. Şimdi gönderilen bu veriyi nasıl yakalayabilir ve üzerinde işlem yapabiliriz ona bakacağız.

Öncelikle DataItem ile gönderilen verileri nasıl okuyabileceğimize bakalım. Veri olaylarını takip edebilmek için aktivitemizde "DataApi.DataListener" sınıfını gerçeklemeliyiz. Bu sınıf onDataChanged metodunun yazılmasını zorunlu kılar. DataApi'deki herhangi bir veride bir değişiklik olduğu zaman bu metod otomatik olarak çağırılacaktır (Önemli: Bu metodun çağırılması için aktivitenin ekranda veya aktif olması gerekir).

[code]​
@Override
    public void onConnected(Bundle bundle) {
        //Bağlantı sağlandı.
        Wearable.MessageApi.addListener(mGoogleApiClient, this);
        //Mesaj olaylarını dinliyoruz.
    }
    
    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                //Bellekteki verilerden biri değişti veya yeni veri geldi.
                DataMapItem dataMapItem = DataMapItem.fromDataItem(event.getDataItem());
                if (dataMapItem.getDataMap().containsKey("MyString")) {
                    String myString = dataMapItem.getDataMap().getString("MyString");
                    //Veriyi aldık.
                    //Veriyi kullandık artık silebiliriz.
                    Wearable.DataApi.deleteDataItems(mGoogleApiClient, event.getDataItem().getUri());
                } else {
                    //Istediğimiz özellikteki veriyi bulamadık.
                }
            }
            if (event.getType() == DataEvent.TYPE_DELETED) {
                //Bellekteki verilerden biri silindi.
            }
        }
    }

    public void baglantiyiKapat() {
        //Veri dinlemeyi bırak.
        Wearable.DataApi.removeListener(mGoogleApiClient, this);
        //GoogleApiConnection bağlantısını kapat.
        mGoogleApiClient.disconnect();
    }
[/code]

Bize veri değiştiğine dair bildiri geldiği zaman yapmamız gereken, tüm DataEvent'leri kontrol ederek bizim istediğimiz veriye ait bir değişiklik var mı yok mu anlamak. Öncelikle veri değişim şekline bakabiliriz: veri güncellenmiş olabilir (TYPE_CHANGED) veya silinmiş olabilir (TYPE_DELETED). Daha sonrasında verinin bize ait bilgileri içerip içermediğini anlamak için containsKey() metodunu çağırırız. Hatırlarsanız veriyi DataMap'e koyarken çeşitli anahtar kelimeler tanımlamıştık. Yine bu anahtar kelimeleri kullanarak verimizi DataApi'dan temin etmemiz mümkün.

Dikkat edilmesi gereken bir unsur da tüm DataMap'lerin ve DataEvent'lerin size ait olmama olasılığı. Diğer uygulamalar da aynı iletişim unsurlarını kullandığından bizi ilgilendirmeyen veri paketlerine müdahele etmemeliyiz. Bir diğer önemli nokta ise bellekteki şişmeyi engellemek ve gönderilen yeni verileri eskilerinden daha kolay ayırt edebilmek için (veri paketlerinin zaman değeri yok) kullanmış olduğumuz verileri bellekten silmek. Yukarıdaki örnekte de görüldüğü gibi verimizi DataMap'den çektikten sonra DataItem objesini siliyoruz. "Kullanmadığın veriyi sil" yaklaşımı GoogleApiClient kullanırken çok işinize yarayacak.

Son olarak bir servis oluşturarak nasıl veri olaylarını ve mesajları yakalayabileceğimize bakacağız. Servisiniz yeni bir sınıf olmalı ve "WearableListenerService"'den türemelidir. Bu sınıfın içerisinde implemente edebileceğiniz 4 kullanışlı metod var:

  • onPeerConnected : Android Phone veya Wear ile bağlantı kuruldu.
  • onMessageReceived : Yeni bir mesaj.
  • onDataChanged : Veri güncellendi veya silindi.
  • onPeerDisconnected : Bağlantı kapatıldı.
[code]
public class VeriDinleyici extends WearableListenerService {

    private String OZEL_MESAJ_ANAHTARI = "/com/gmail/orkun1675/androidwearuygulamaornegi/ornekmesaj";

    @Override
    public void onMessageReceived(MessageEvent messageEvent) {
        //Yeni bir mesaj alindi.
        if (messageEvent.getData().equals(OZEL_MESAJ_ANAHTARI)) {
            //Anahtarlar uyuştuğu için mesaj bize ait.
            byte[] data = messageEvent.getData();
            //Mesaj ile beraber gonderilen veri.
            gelenMesajIleIsYap();
        } else {
            //Mesaj bize ait değil.
            super.onMessageReceived(messageEvent);
        }
    }
    @Override
    public void onDataChanged(DataEventBuffer dataEvents) {
        for (DataEvent event : dataEvents) {
            if (event.getType() == DataEvent.TYPE_CHANGED) {
                //Bellekteki verilerden biri değişti veya yeni veri geldi.
            }
            if (event.getType() == DataEvent.TYPE_DELETED) {
                //Bellekteki verilerden biri silindi.
            }
        }
    }
    public void gelenMesajIleIsYap() {

    }
}
[/code]

Servis kullanmanın en büyük avantajı, uygulamanız o an kullanılmıyor olsa bile kodunuzun çalışıyor olacak olmasıdır. Servis sınıflarının kaydedilmesi ve sistem tarafından daha sonra otomatik olarak çağırılması için kullanıcının uygulamanızı indirip tek bir sefer açması yeterlidir. Bu şekilde Android Phone ayağı sadece servis olan (örneğin internete bağlanıp veri çeken bir servis) ve Android Wear ayağı görsellik olan (kullanıcı uygulamayı açtığı zaman telefondan çekilen veriyi gösterme) uygulamalar yazmanız mümkün.

Android Wear ile olasılıklar sonsuz. Bakalım siz ne yapacaksınız?

Okuduğunuz için teşekkürler.

Android Dev Makalesi'ne buradan ulaşabilirsiniz.

Orkun Bulut Duman |

11.11.2014

Yorumlar

Emre Kaplan
21.12.2016 - 04:00

Merhaba bir sorum olacak. Android Wear ile internete wireless üzerinden erişmenin bir mümkünatı yok mudur acava? 

Tolga
04.11.2016 - 12:22

merhaba benim yorum değilde sorum olucak doğru yere yazmıyorda olabilirim affınıza sığınıyorum özür dilerim

sorunum şu

arkadaşımın kullanmış olduğu huawei mate 8 telefonuna eşlik etsin diye birde Huawei SmartWatch aldı burayakadar herşey güzel.
cihazları kendi arasında kullanmak için android wear programını kuruyoruz ama telefonda karşımıza şöle bir yazı geliyor.

(saatinizin bağlı kalmasını sağlamak için wear uygulamasının arka planda çalışmaya devam etmesine izin verin)

bağlı kal diyoruz devam diyoruz sonra bize

Bağlı Kalın

Saatinizin telefona bağlı kalması için Android Wear'ın arka planda çalışmaya devam etmesine izin verilmesi gerekiyor.Bu ayar bu uygulamaya ilişkin bazı pil optimizasyonlarını kapatmanızı gerektirir

Devam diyorum tekrar

(saatinizin bağlı kalmasını sağlamak için wear uygulamasının arka planda çalışmaya devam etmesine izin verin)

diyor

aynı işleme sony c5 ultra ile yaptık böle bir uyarı gelmedi

bu uyarı huawei mate 8 e geldiği sürece telefona düşen mesaj,email,whatsupp,hangout mesajları bildirimi saate gitmiyor.

yardımlarınızı talep ediyorum

Tolga Okul

Eyüp KAYA
28.12.2014 - 01:05

Diğer android mobil cihazları için yazılan uygulamalar burada direkt çalışmaz mı yani ?
Çok bir fark olmasa gerek.

Eyüp KAYA
28.12.2014 - 01:06

bir de arz talep olayı var acaba bunu kaş milyon kişi kullanıyor ?

Orkun Bulut Duman
28.12.2014 - 02:04

Apayri bir ortam oldugu icin gelistiricinin ayrica kod yazmasi gerekiyor. Kodlama mantigi dediginiz gibi ayni. Burada tek yeni konsept GoogleApiClient ile veri aktarimi.

Orkun Bulut Duman
28.12.2014 - 02:04
Android Wear cihazlari daha yeni piyasaya suruldu, ne kadar yaygin kullanilacaklari suan icin bir soru isareti. Ancak tuketicinin giyilebilir teknolojiye ilgi duydugu kesin.
Hüseyin Durmus
08.12.2014 - 10:20

Detaylı anlatım için teşekkürler.

Nihat
17.11.2014 - 12:01

ilgi duyduğum bir alan, teşekkürler