Bu yazım, QT, özellikle de, çoklu platform (android) için QML kullanan yazılımperver dostlarım için. Kodunuza taş değmesin diye, bir süredir geliştirmekte olduğum QML uygulamasını geliştirirken karşılaştığım sıkıntılara ilişkin çözümleri ve daha önce kullandığım bazı işinizi kolaylaştıracak ipuçlarını sizler ile paylaşacağım. Ayrıca ileride unutursam diye kendime de not tabi 😀
QT ve QML yazılımları geliştirirken bir süredir QT Creator kullanıyorum (En son 4.11 sürümüne geçtim) ve açıkçası işimi fazlasıyla görüyor. Benzer kabiliyetleri her ne kadar Visual Studio kullanarak da gerçekleştirebilirseniz de (ki oldukça uzun bir süre ben de kullandım), özellikle android gibi platformlar için QT yazılımı geliştirecekseniz, QT Creator kullanmanızı tavsiye edeceğim. Gerek yazılım geliştirme, gerekse konuşlandırma, ilgili ayarlar QT Creator üzerinden çok kolay bir şekilde kotarılabiliyor. Bunun ile birlikte bu, her şeyin de güllük gülistanlık olduğu anlamına da gelmiyor ne yazık ki 🙂 Daha fazla oyalanmadan, sizler için derlediğim ipuçlarına göz atalım. Sizlere aktarmak istediğimi ip uçlarını, kolay takip edebilesiniz diye alt başlıklar halinde sizlere aktarıyor olacağım.
İçerik
QT Creator Sürümler Arası Geçiş
QT Creator ile projenizi geliştiriyorsunuz ve yeni sürümü çıktı, buraya kadar her şey güzel. Yeni sürümü kurdunuz, windows üzerinde uygulamanızı yeniden oluşturdunuz ve hiç bir sıkıntı yok lakin artık yazılımınız android üzerinde çalışmıyor (windows üzerinde çalışan uygulamalarda çok sık buna rastlamadım açıkçası, yaşayan var ise bizi de bilgilendirebilir) ve tadınız kaçtı, sebep ne olabilir? Bu başlıkta olası problemlere ve bunları nasıl çözebileceğinize bakacağız.
Arkadaşlar bu sıkıntılarınınz kaynağı, özellikle android için, kullanılan bazı alanların artık kullanılmaması, isimlerinin değiştirilmesi ya da yeni zorunlu alanların eklenmesinden kaynaklanıyor olabilir. Bu anlamda da en olağan şüpheli AndroidManifest.xml dosyası. Bu dosyayı henüz duymamış olabilirsiniz diye ilgili google bağlantısını da ekliyorum. Ayrıca sizleri, bu ve diğer benzeri android kavramlarını aktardığım yazıya bir göz atmaya çağırıyorum:
Android NDK ile uğraşırken dikkat edilecekler 🙂
Bu dosya Android uygulamanız ile ilgili çok temel bilgileri girdiğimiz ve gerekli izin ve benzeri ayarlarının yapıldığı dosyadır. Qt creator sağ olsun burada bulunan bir çok alanı daha kolay bir şekilde doldurabilmemiz için bir grafiksel kullanıcı arayüzü aracılığı ile bu dosyaya müdahale etmenize olanak sağlıyor.
Peki bu sıkıntıyı nasıl gidereceğiz. Bana göre en kolay yöntem bu dosyanın silinip baştan oluşturulması (tabi öncesinde muhakkak bu dosyanın bir yedeğiniz alınız). Dosyayı sildik, peki yenisini el ile mi oluşturacağız? Elbette hayır, aşağıdaki adımları izleyerek, Qt creator’ın sizin için bu dosyayı oluşturmasını sağlayabilirsiniz:
Qt creator içerisinden aşağıdaki pencereyi açıp, daha sonra “Create Templates” diyerek ilgili dosyaları oluşturabilirsiniz. Daha sonra oluşturulan AndroidManifest.xml dosyasına çift tıklarak gerekli ayarlara tekrar yapıp, uygulamanızı yeniden oluşturmayı deneyebilirsiniz.
Bu arada lafı açılmışken, bu ve benzeri diğer bir çok ayarı nasıl yapabileceğinize ve uygulamalarınız Android üzerinde konuşlandırabileceğinize ilişkin detaylı bilgi için aşağıdaki adrese muhakkak bakmalısınız:
https://doc.qt.io/qtcreator/creator-deploying-android.html
Bu arada bu husus ile ilintili olduğunu düşündüğüm hata raporuna da aşağıdaki adresten göz atabilirsiniz:
https://bugreports.qt.io/projects/QTBUG/issues/QTBUG-80444?filter=allissues
QT Creator Çıktı Dizini Uzunluğu
QT Creator ile uygulama oluştururken karşılaşabileceğiniz bir diğer problem ise aşağıdaki gibi hata metinleri ile kendisini gösterir:
1 2 |
aidl.exe E 12-26 23:20:06 2616 23156 io_delegate.cpp:50] Failed to GetFullPathName(D:\BlaBlaBla\build-QMLSocketApplication-Android_for_armeabi_v7a_arm64_v8a_x86_x86_64_Clang_Qt_5_14_0_for_Android-Release\android |
Böyle bir hata gördüğünüzde aklınıza gelecek ilk şey, Qt Creator Android kit ayarları altındaki çıktı dizinine ait yolun uzunluğu kontrol etmek olmalı.
bunun uzunluğunu kısalttığınızda hatanın da kaybolduğunu göreceksiniz.
QML Uygulamasının Android Üzerinde Takılı Kalması
Uygulamanızı geliştirdiniz ve bir önceki başlıklarda anlatılan sıkıntıların hepsini de giderdiniz. Yazılımınızı hedef android platformuna yüklediniz, uygulama açıldı ama bir hareket yok, hata mesajı da yok (görünürde). Sebebi ne olabilir? Elbette bunun birden fazla sebebi olabilir (ör. sonsuz döngü, bloklanmış bir çağrı, vs), ben burada, yeni QT Creator ile peyda olmuş bir problemden bahsedeceğim.
Ne yazık ki QT Creator 5.14.0 ile birlikte, bazı önemli dosyaların ekskik olması sebebi ile, QML uygulamaları göçüyormuş. Bunun ile ilgili hata raporuna aşağıdaki bağlantıdan ulaşabilirsiniz:
https://bugreports.qt.io/browse/QTBUG-80713
Bu problem çözülene kadar ise “Projects -> Build Settings -> qmake -> Enable Qt Quick Compiler” seçeneğini kaldırarak, projelerinizi oluşturabilirsiniz.
Tabi böyle kestirme bir çözüme gidince insanın aklına, bu ayara kapayınca, neleri kaçırdığımız sorusu gelebilir. Bu durumda da “Qt Quick Compiler” ne iş yapar sorusu gelmesi gayet doğal.
Anladığım kadarı ile bu yazılım ile, QT quick uygulamaları (yani qml dosyaları), derlenerek nihai çalıştırılabilir dosyanın içerisine gömülüyor ve bu sayede QML dosyalarını uygulamanız ile birlikte taşımanıza gerek kalmıyor (normalde bu dosyaların da çalıştırılabilir dosyanız ile birlikte sunulması gerekmekte). Bu noktada, çok da önemli değil diyebilirsiniz amma şu var ki, bu sayede uygulamaların açılış süreleri, oldukça kısalıyormuş. Açıkçası, geliştirdiğim uygulamalarda, bunun kazandırdığı süreyi ölçmedim ama geliştiriciler böyle bir not düşüyorlar ise, ciddi bir fark olduğu ortada.
Bu arada bu problem, Qt Creator kullanan yazılımcıların takip etmesi gereken bir sayfanın da önemini ortaya koydu. O da “Qt for Android known issues“. Bu sayfa QT’nin android platformu için bilinen sıkıntılarını listelemekte ve bu sıkıntı da orada, listenin başında yer alıyor.
Size pek mantıklı gelmeyen, ya da, daha önce çalışan ve güncelleme ile çalışmayan sorunlar için bu sayfaya göz atmanızda fayda var.
Mobil Cihazlar Girdi Problemi
Diğer problemlere göre, biraz daha detay sayılabilecek bir problemden bahsetmek istiyorum.
Problemimiz şu: bir QML uygulaması geliştiriyorum, grafiksel kullanıcı arayüzünde, kullanıcıdan girdi almak için, bir noktada TextField veya türevi QML tipini kullanıyorum. Yetinmiyorum, bu TextField’e ilişkin onTextChanged() sinyal kotarıcısı içerisinde de bir takım işler çeviriyorum (örneğin, her iki karakter de bir fazladan “:” eklemek ya da girilen değeri sürekli kontrol etmek, vb.). Bu noktaya kadar her şey güzel. Uygulamanızı Windows üzerinde çalıştırdınız, gayet güzel çalışıyor, sonra artık hedef platform android için paketinizi oluşturdunuz ve mobil cihazınıza uygulamayı kurdunuz.
Tam o noktada, artık metin girdi kutularınızın beklediğiniz gibi çalışmadığını fark ettiniz. Hemen, “debug” etmeye başladınız ve gördünüz ki, onTextChange() hiç çağrılmıyor, neden acaba? Hatta text nesnesinin de hiç güncellenmediğini fark ediyorsunuz.
Dostlar, benim gördüğüm kadarı ile bu tarz problemlerinin çoğunun kaynağı, telefonlarda kullanılan klavyeler. Bu klavyelerin çoğu, ya tamamlama ya da öneri altında ek kabiliyetler sunuyor ve bunların kullanılması durumunda ise, girilen metin text nesnesi güncellenmiyor ve doğal olarak da, onTextChange() sinyal kotarıcısı da çalışmıyor. Dokümanları incelediğinizde, bu kabiliyetleri pasifleştirmek için Qt.ImhNoPredictiveText özelliğinin eklenmesinin gerektiği ifade edilmiş fakat benim ve gördüğüm kadarı ile bir çok kullanıcının problemini bu çözmüyor (hatta bunun ile ilgili de bir hata raporu mevcut).
Bu problem için elimde iki çözüm var:
- İlki, hedef platformda, klavye ayarlarından, bu tarz ek özellikleri kapatmak. Bunu yazılımsal olarak yapılıp/yapılmadığından emin değilim ama illaki yapılabiliyordur. Bu yaklaşım her ne kadar bu problemi çözüyor olsa da hedef platforma müdahale gerektirdiğinden pek tercih edilmeyebilir.
- İkincisi is displayText ve bu nesne ile ilintili onDisplayTextChanged sinyal kotarıcısının kullanılması. text nesnesinden farklı olarak, displayText nesnesi biraz önce bahsetmiş olduğum klavye eklentilerinden etkilenmiyor ve ne görüyorsanız, bu değişken içerisinde tutuluyor. Bu sebeple text nesnesi ile yapabileceğiniz her şeyi bunu kullanarak bir oktaya kadar yapabilirsiniz.
Bu noktada aklınızda bir soru işareti belirmiş olabilir. Şöyle ki: mobil cihazımda bu yazı tamamlama ve benzeri özellikleri kullansam da, eninde sonunda bu text nesnesi girdiğim metin ile güncellenmesi gerekmiyor mu? Aynen, gerekiyor ve bu da genelde, mobil cihazının üzerinden bir şekilde girilen metni onayladığınızda (ki samsun note 9 da bunun için bir düğme beliyor, bazı durumlarda da bunu otomatik olarak yapıyor), o zaman bu sinyal kotarıcısı (onTextChanged()) ve text nesnesi güncelleniyor. Metin kutularınızın ara sıra çalışıyor olduğunu size düşündüren de bu davranış olabilir.
Başta belirttiğim problem için, yukarıdaki yaklaşımların, bir çok durumda işinizi göreceğini düşünüyorum. Farklı bir çözümü her zaman burada bizimle paylaşabilirsiniz.
Platform Bağımlı QML Davranışı
Son başlık altında her ne kadar bir problem olmasa da bazı durumlarda problem haline gelebilecek bir ihtiyaçtan bahsetmek istiyorum.
QT bizlere, platform bağımsız alt yapı sunsa da, yazılımınızın, bir noktada farklı platformlar için farklı davranışlar sergilemesini isteyebilirsiniz. Örneğin, bir PC ya da Mac ile mobil versiyonunun farklı davranmasını isteyebilirsiniz. Peki, bunu nasıl sağlayacağız?
Burada iki çözümden bahsedeceğim, elbette farklı çözümler olacaktır ama açıkçası bana en kolay gelenler bunlar.
- İlki biraz dolaylı bir çözüm. Eğer, QML uygulamanız ile birlikte C++ kullanıyorsanız, C++ sınıflarınız içerisinde #ifdef yapılarını kullanarak platform bağımlı kodları yazıp daha sonra bu sınıfı QML üzerinden kullanarak, farklı platformlara hizmet edebilirsiniz,
- Bir diğer yöntem ise C++ kullanmasanız da, QML içerisinde kullanabileceğiniz bir yöntem. Bu yöntemde Qt qml tipini kullanıyoruz. Bu tip içerisinde bulunan platform.os nesnesi ile, kodun çalıştığı platforma ilişkin bilgi elde edebilirsiniz. Hemen örnek bir koda bakalım birlikte:
1 2 3 4 5 6 |
if(Qt.platform.os === "android"){ // Androide ozgu davranislari buraya ekleyebilirsiniz } else{ // Diger platformlar icin ise buraya } |
- Desteklenen bütün platformlar ise:
- “android” – Android
“ios” – iOS
“tvos” – tvOS
“linux” – Linux
“osx” – macOS
“qnx” – QNX (since Qt 5.9.3)
“unix” – Other Unix-based OS
“windows” – Windows
“winrt” – WinRT / UWP
- “android” – Android
- Bu nesne üzerinden ulaşabileceğiniz diğer bilgiler için ilgili bağlantıya muhakkak bir göz atınız.
Evet sevgili yazılımperver dostlarım, bir yazımın daha sonuna geldim. Bir sonraki yazımda görüşmek dileğiyle, kendinize çok iyi davranın 😉