Biraz zorlarsam “vücut geliştirme” bile olurdu. Öhöm, her neyse Android, level 1’den itibaren uygulamalara widget izni veriyor.
Android’de çalışacak şekilde, yalnızca bir widget dahi geliştirmek mümkün. Konuyla ilgili Türkçe kaynağa hiç denk gelmedim. Yapmış ve uğraşıyorken yazmaya karar verdim.
Normal bir uygulamada kullanılan bileşenlerin bir kısmını widget üzerinde kullanmak maalesef mümkün değil. Olsaydı (örneğin textView) birçok atraksiyon yapmaya niyetlenmiştim. İzin verilen bileşenlerin listesine burada.
Yeni bir Android projesi açıp; isim, paket, level (7 üzeri önerilir) gibi detayları tamamladıktan sonra bir Activicty class’ı oluşturmadan -dikkat- işlemi tamamlayın. Oluşturmama sebebi uygulama değil widget geliştirecek olmamız.
Ardından malum paketinizin içerisine HelloWidget class’ı oluşturun. Verilen isimlerin aynı olması yazının sonrası için faydalı olabilir. Bu sınıfı widget olarak çalışacağı için AppWidgetProvider‘dan extend edilmesi gerekiyor. Eclipse -veya kullandığınız ide- uyarmadı ise elle extend edin.
Bu işlemden sonra AppWidgetProvider’ın onUpdate metodunu override edin. Buraya kadar doğru geldiyseniz kod şu şekilde olacaktır:
[code lang=”java”]public class HelloWidget extends AppWidgetProvider{
@Override
public void onUpdate( Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds ){
//widget çalıştığında ilk olarak bu metod çağırılır
}
Bu kısmı direkt kopyala-yapıştır yerine uygulayarak yaparsanız Android.Manifest dosyası Activity’den gelen kodlardan arınacaktır. Her ihtimale karşın aşağıdaki ile güncelleyebilirsiniz:
[code lang=”xml”]<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.ogulcan.hellowidget"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="7" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<receiver android:name=".HelloWidget" android:label="@string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider" android:resource="@xml/widget" />
</receiver>
</application>
</manifest>
Faydalı ve öğretici olması açısından Hello World uygulaması oluşturup Activity’nin manifest dosyasına yansımasıyla, widget’ın yansımasını karşılaştırabilirsiniz.
Düzenlemeyi tamamladıktan sonra projeye widget’ın yapısını belirtecek (genişlik, yükseklik vb) bir xml oluşturun. Türünü (layout, drawable vs) AppProvider seçerseniz res/xml yoluna kaydedecektir. Sorun olmaması açısından ismini widget yapın (Manifest içinde tanımına uygun olmalı).
Widget.xml’i hem görsel arayüzden, hem de kod ile değiştirmek mümkün. Örnek için kullandığım xml yapısını aktarın:
[code lang=”xml”] <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"android:initialLayout="@layout/main"
android:updatePeriodMillis="10000"
android:minHeight="40dip"
android:minWidth="120dip"/>
[/code]
Android 1.5 sürümünden sonra updatePeriodMillis sınırını en az 30 dakika olacak şekilde değiştirdi. Dolasıyla (birimi ms) buradaki değer geçersiz kalıyor.
Widget.xml’de dikkat edilecek nokta belirtilen initialLayout parametresidir. Burada ben main.xml üzerinden widget tasarımını kontrol edeceğimi belirttim. Geçelim main.xml’i düzenlemeye.
[code lang=”xml”]<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="120dp"
android:layout_height="40dp"
android:baselineAligned="false"
android:background="@drawable/background"
android:orientation="vertical">
<TextView
android:textSize="15dp"
android:id="@+id/hello"
android:textColor="#222"
android:text="Hello Widget"
android:typeface="sans"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_gravity="center">
</TextView>
</LinearLayout>
Arkaplanı gradient yaptım ve stili ayrı bir xml’den çağırdım. Drawable klasörlerinden herhangi birine (drawable türünde) bir xml oluşturun ve adını background tanımlayıp aşağıdaki kodları yapıştırın:
[code lang=”xml”]<shape xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/Corners">
<gradient android:startColor="#cecece" android:endColor="#efefef" android:angle="45"/>
<padding android:left="4dp" android:top="1dp" android:right="4dp" android:bottom="1dp" />
<corners android:radius="4dp"/>
<stroke android:width="2dp" android:color="#FFAfAfAf"/>
</shape>
Son olarak, yazının en başında tanımladığımız onUpdate metodunu gerekli şekilde doldurmak kaldı. Toparlarsak: Bir arkaplan üzerinde (background.xml) bir textView var. Uygulama çalıştığında (widget çağırılınca) onUpdate çalışacak ve mesaj textView üzerinde çıkacak.
Aslında xml tarafından textView’e ilk değerini atayıp direkt çalıştırmak da işe yarayacaktır fakat işlevsel olmayacaktır. Dolasıyla onUpdate üzerinden bileşene erişmek en iyisi.
Sonuç:
[code lang=”java”] public class HelloWidget extends AppWidgetProvider { RemoteViews rmViews;
ComponentName cmName;
AppWidgetManager appWidgetManager;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// Layout üzerindeki bileşenlere erişmek için RemoteViews tanımlanır
rmViews = new RemoteViews(context.getPackageName(), R.layout.main);
// Widget’ı yönetmek için appWidgetManager tanımlanır
appWidgetManager = this.appWidgetManager;
// Bileşenleri kontrol etmek için ComponentName tanımlanır
cmName = new ComponentName(context, HelloWidget.class);
// main.xml’deki hello id’li textView’ı günceller
rmViews.setTextViewText(R.id.hello, "Hello Widget");
// Yapılan istekleri aktarır */
appWidgetManager.updateAppWidget(cmName, rmViews);
}
}
[/code]
Hata ve sorular için yorumları kullanabilirsiniz. Ayrıca, örneğin tamamı github’da mevcut.
Kolay gelsin.
Hocam R.id.hello göremiyor nedendir acaba.
[…] […]
Teşekkürler. Eline sağlık
@mete import.projeadi.R; yazman gerekir