24 Mart 2014 Pazartesi

Widget'i AlarmManager'la Yenileme


Herkese Selam,

Bildiğiniz gibi android widget yenileme sıklığı(updatePeriodMillis), batarya ömrünü uzun tutmak adına minimum 30 dk ile sınırlı. Fakat gün geldi bir sebepten daha düşük periyotta widgeti yenileme ihtiyacınız oldu, nasıl bir çözüm giderdiniz? Bu durumda biraz düşününce eminim aklınıza AlarmManager sınıfını bu iş için kullanmak gelecektir.

AlarmManager sınıfını kullanarak bir widget'i istediğimiz periyotta güncelleyebiliriz, bunun için tek ihtiyacımız widget ui'ını güncelleyecek olan bir receiver yazmak ve bu receiver'ı tetiklemek için AlarmManager'ı kullanmak. Takip edilmesi gereken adımları sıralayacak olursak;

  1. Widget'i oluşturmak
  2. Güncelleme mekanizmasını kurmak
  3. Güncelleme mekanizmasını iptal etmek

Yukarıdaki adımları zamanı 19:07:00 (hh:mm:ss) formatında gösteren, sn'de bir yenilenen basit bir saat widget'ı oluşturarak uygulayacağım, girdinin sonunda alttaki gibi harika renklere sahip bir widget'a sahip olmanız işten bile değil :]

O zaman hız kesmeden yukarıda tanımladığımız adımları uygulamaya başlayalım;

1. Widget'i oluşturmak
1.1 Xml layout oluşturmak : Widget'in ui tarafı için sadece bir adet TextView yeterli, res/layout/widget_layout.xml


    

1.2 AppWidgetProviderInfo xml dosyası ile widget konfigrasyonunu belirliyoruz, buradaki android:updateperiodmillis="1800000" ataması formalite zira güncelleme işlemini receiver üzerinden halledeceğiz, res/xml/widget_metadata.xml

1.3 ClockWidget adlı widget'ı ve AlarmManagerBroadcastReceiver adlı receiver'ı manifest'te deklare ediyoruz, AndroidManifest.xml


 
  
 
 




1.4 AppWidgetProvider sınıfından türeyen ClockWidget sınıfını oluşturuyoruz, dikkat edeceğiniz üzere onUpdate() metodunu ezmedik, ClockWidgetProvider.java
public class ClockWidgetProvider extends AppWidgetProvider {

    @Override
    public void onEnabled(Context context) {
        // ..
    }

    @Override
    public void onDisabled(Context context) {
        // ..
    }

}
2. Güncelleme mekanizmasını kurmak
2.1 Widget'i güncelleyecek olan receiver'ı oluşturuyoruz, AlarmManagerBroadcastReceiver.java
// widget'i güncelleyen receiver
public class AlarmManagerBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // geçerli zaman
        String currentTime = new SimpleDateFormat("hh:mm:ss").format(new Date(System.currentTimeMillis()));

        // geçerli zamanı widget ui'a atıyoruz
        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
        remoteViews.setTextViewText(R.id.textView, currentTime);

        // widget ui'ını yeniliyoruz
        ComponentName widget = new ComponentName(context, ClockWidgetProvider.class);
        AppWidgetManager manager = AppWidgetManager.getInstance(context);
        manager.updateAppWidget(widget, remoteViews);
    }

}
2.2 Receiver'ı tetiklemek için AlarmManager sınıfı yardımıyla periyodik olarak broadcast yayınlınlamak için   ClockWidget sınıfının onEnabled() metodunu eziyoruz, ClockWidgetProvider.java

// uygulamaya ait ilk widget home screen'e eklenince tetiklenir
@Override
public void onEnabled(Context context) {
 Toast.makeText(context, "ClockWidgetProvider.onEnabled", Toast.LENGTH_SHORT).show();
 super.onEnabled(context);

 // güncelleyici receiver için broadcast yayını hazırlıyoruz
 Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
 PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

 // alarmManager yardımı ile her sn broadcast yayınlıyoruz
 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 alarmManager.setRepeating(
   AlarmManager.RTC, // type
   0, // triggerAtMillis
   1 * 1000, // intervalMillis
   pendingIntent // operation
 );
}
3. Güncelleme mekanizmasını iptal etmek
Widget ana ekrandan kaldırılınca gereksiz broadcast yayınlama işlemini iptal etmek için ClockWidget sınıfının onDisabled() metoduna aşağıdaki kodları ekliyoruz, ClockWidgetProvider.java
// uygulamaya ait son widget da home screen'den kaldırılınca tetiklenir
@Override
public void onDisabled(Context context) {
 Toast.makeText(context, "ClockWidgetProvider.onDisabled", Toast.LENGTH_SHORT).show();
 super.onDisabled(context);

 // güncelleyici receiver için periyodik tetikleme mekanizmasını kaldırıyoruz
 Intent intent = new Intent(context, AlarmManagerBroadcastReceiver.class);
 PendingIntent sender = PendingIntent.getBroadcast(context, 0, intent, 0);
 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
 alarmManager.cancel(sender);
}
Anlatımda kullandığım "Clock Widget" android projesine github üzinden buraya tıklayarak ulaşabilirsiniz.

Başta da belirttiğim gibi mecbur kalmadıkça widget'in yarım saat altında bir periyot için güncellenmesi batarya ömrü açısından sakıncalı olduğu için android tarafında önerilmiyor, karar sizin:
http://developer.android.com/reference/android/appwidget/AppWidgetProviderInfo.html#updatePeriodMillis

Umarım faydalı olmuştur, esen kalın.

Hiç yorum yok:

Yorum Gönder