Merhaba Arkadaşlar,
Android komponentleri arasında haberleşme genellikle intent'ler üzerinden gerçekleşir. Intent tipinin bol overload'lu putExtra() metoduyla, primitive tipler veya kendi oluşturduğunuz sınfların serilize edilebilir(parcelable, serializable) nesne örnekleri, iki android komponenti arasında taşınmasıyla haberleşme sağlanmış olur. Misal activity içerisinden service başlatırken intent ile service'e bir takım veriler aktarılabilir. Ne var ki aksi yönde bir iletişim bu denli basit değildir, zira service'ler genelde artalanda takılan ve önyüzle mümkün mertebe muhattap olmayan gizli kahramanlardır.
Android'de service'ten activity'ye doğru iletişim kurmak için iki yöntem mevcut:
- Bounded Service yapısı kurarak IBinder üzerinden standart java RPC(remote procedure call) mekanizmasını kullanmak. Bu yapı farklı process'ler arası, hızlı iletişime de destek sağladığı için uygulanması nispeten daha komplike.
- Bu blog girdisinde üzerinde duracağımız, daha basit olan diğer yöntem de Broadcast-Receiver mekanizması.
- Service'te işlem bitince yayınlanacak olan broadcasti dinleyen receiver'ı yazmak ve sisteme register etmek
- İşlem yapacak olan servisi yazmak ve activity içinden start vermek
- Service tarafında işlem bitince ilgili broadcasti yayınlamak
Anlaşılabilirlik adına kodları sade tuttum, Acitivity sınıfı:
public class MainActivity extends Activity { public static final String FILTER = "just.a.filter"; public static final String KEY = "key"; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // service'ten yayınlanacak olan broadcast'i dinliyoruz
LocalBroadcastManager.getInstance(this).registerReceiver(new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // yanıt için geri bildirim Log.w("servisten gelen cevap", intent.getStringExtra(KEY)); Toast.makeText(MainActivity.this, intent.getStringExtra(KEY), Toast.LENGTH_SHORT).show(); } }, new IntentFilter(FILTER)); // işlem yapacak olan service'i başlatıyoruz startService(new Intent(this, DownloadService.class)); } }Service sınıfı:
public class DownloadService extends Service { @Override public IBinder onBind(Intent intent) { return null; } @Override public int onStartCommand(Intent intent, int flags, int startId) { Log.d(" ", "onStartCommand"); // farklı thread'e çıkarak asenkron işlem başlatılır new Thread(new Runnable() { @Override public void run() { try { String result = null; // uzun süreli işlem yapılır; dosya indirme, hesaplama vs. // gecikmeyi simule edelim Thread.sleep(3000); // temsili islem sonucu result = "tek gercek fenerbahce :]"; // işlem bitti sonucu takipçi activity'e bildirelim LocalBroadcastManager.getInstance(getBaseContext()).sendBroadcast( new Intent(MainActivity.FILTER).putExtra(MainActivity.KEY, result) ); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); return super.onStartCommand(intent, flags, startId); } }Service tarafında hayali olarak bir web sayfasının html içeriğini indirip döndürüyormuş gibi işlem yaptım, siz burda farklı implementasyonlara gidebilirsiniz. Yine bir kereye mahsus activity ile iletişim kurdum oysa büyük boyutlu dosya indirme işlemi gibi bir senaryoda ilerleme bilgisi belirli aralıklarla activity'e gönderilip orada da progressbar gibi bir ui kontrolü ile kullanıcıya dönüş sağlanabilir.
# dipnot
Global Broadcast yayınlamak yerine LocalBroadCast yayınladım çünkü güvenlik, performans gibi avantajları var: http://developer.android.com/reference/android/support/v4/content/LocalBroadcastManager.html
## dipnot
Bu probleme çözüm olarak belki de daha pratik olarak, ilgili tüketici activity içine public static bir metod tanımlanıp, service'te işlem bitiminde çağrılabilir yahut herhangi bir yerde public static olarak tanımlanan bir callback tetiklenebilir fakat benim tavsiyem bu çözümlerden uzak durmanız zira bu çözümler kod akışını deyim yerideyse yaran, alabildiğine sert, acele çözümlerdir; kodun okunabilirliğini de, genişletilebilirliğini de, test edilebilirliğini de alır uzaaak diyarlara götürür.
Anlatımda oluşturduğum örnek android projesine github üzinden buraya tıklayarak ulaşabilirsiniz.
Bu blog girdisinde service kullanımını bir adım öteye taşıyınca sık karşılaşılan bir probleme çözüm getirmeye çalıştım, umarım faydalı oluştur, bol yeşil robotlu günler.
Hiç yorum yok:
Yorum Gönder