Mobil Programlama

Android

Cihazı Uyanık Tutmak

Lisans: Creative Commons 26.11.2020 tarihinde güncellendi
Bakabileceğiniz Etiketler: Eğitmen: Geleceği Yazanlar Ekibi

Bir Android cihaz boşta kaldığında, bataryayı bitirmemek için olabildiğince hızlı bir şekilde uykuya dalar. Uygulamalar zaman zaman ekranı açık tutmaya, işlerini tamamlamak için işlemciyi çalışır halde tutmaya ihtiyaç duyarlar.

Cihazı uyanık hale getirme konusu üzerindeki yaklaşım uygulamanızın ihtiyaçlarına bağlıdır. En genel kabul görmüş kural, uygulamanızın sistem kaynaklarına olan etkisini en aza indirmek için mümkün olabildiğince "tutumlu" bir yaklaşım tercih etmektir. Bu belgedeki bölümlerde, cihazın varsayılan uyku davranışının uygulama gereksinimlerinizle uyuşmadığı yerlerde durumu nasıl yöneteceğinizi açıklanıyor.

Bildiğiniz üzere farklı Android cihazlarının farklı uyku davranışları vardır. Hepsinin ekranı üreticinin veya kullanıcının ayarladığı sürede kapanır. Hepsi farklı durumlarda derin uykuya geçer.

 

Ekranı açık tutmak

Oyunlar veya video oynatıcı uygulamalar gibi belli uygulamaların ekranı açık tutması gerekir. Uygulamanızda böyle bir ihtiyacınız varsa bunun en iyi yolu, Activity'niz içinde FLAG_KEEP_SCREEN_ON bayrağını kullanmaktır.

NOT: Bu bayrağı sadece Activity'de kullanabilirsiniz. Service ya da başka bileşenlerde kullanamazsınız.

Bir örneğe bakalım:

public class MainActivity extends Activity {
  @Override
  protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  }

Bu yaklaşımın en güzel yanı WakeLock'lara (İşlemciyi açık tutmak konusunda açıklanıyor) benzememesi ve dolayısıyla özel bir izin gerektirmemesi. Bir yandan da bu yaklaşımla ekranı açık tuttuğunuzda, kullanıcı, uygulamalar arasında dolaşırken, sistem bu süreci daha kolay yönetebilir durumdadır ve uygulamanızın kullanmadığı kaynakları (ekran vs.) serbest bırakmak konusunda ekstradan bir şey yapmanızı gerektirmez.

Ekranı açık tutmanın bir diğer yolu yukarıda yapılan işlemi uygulamanın XML layout'unda yapmak. Bunun için android:keepScreenOn özniteliğini kullanabilirsiniz:

 

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:keepScreenOn="true">
    ...
</RelativeLayout>

 

android:keepScreenOn="true" ile FLAG_KEEP_SCREEN_ON bayrağını kullanmak arasında bir fark yok. Uygulamanız için hangisini kullanmak daha doğruysa onu kullanabilirsiniz. Activity içinde bayrağı gerektiği zaman kullanmak, yine istediğiniz zaman o bayrağı kaldırma fırsatı verdiği için ekranı "serbest bırakma" konusunda avantaj sağlar.

NOT: Çalışan uygulamanız için ekranı açık bırakmaya ihtiyaç duymadığınızda (örneğin belli bir sürede uygulamanız çalışmadan arkada beklediğinde ekranı uyanık tutma işine ara vermek istediğinizde) FLAG_KEEP_SCREEN_ON bayrağını ortadan kaldırmak gibi ekstradan bir işlem yapmak zorunda değilsiniz. Android'in pencere yöneticisi, uygulamanız arka plana gittiğinde veya ön plana geldiğinde gerçekleşmesi gereken doğru şeyi yapmakla yükümlüdür. Dolayısıyla sizin yerinize bunu o yapacaktır. Yine de bu bayrağı bilerek silmek isterseniz ve ekranın tekrar uygun şartlarda kapanmasını isterseniz clearFlags() metodunu kullanabilirsiniz:

getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON).

 

İşlemciyi açık tutmak

Cihaz uykuya dalmadan önce bitirmeniz gereken işleri tamamlamak için işlemciyi çalışır durumda tutmanız gerekebilir. Android, aksine bir şey yapmazsanız derin uykuya geçecekse her şeyi "dondurur". İşlemciyi çalışır durumda tutma amacıyla PowerManager servisinin "wakelock" olarak adlandırılan özelliğini kullanabilirsiniz. Wake lock'ları "uyku önleyiciler" gibi düşünebilirsiniz. Wakelock'lar uygulamanızı çalıştırdığınız cihazın güç durumunu kontrol etmenizi sağlar.

Wakelock oluşturmanın ve ayakta tutmanın cihazın bataryasını tüketme üzerinde güçlü etkileri vardır. Bu nedenle Wakelock'ları sadece ama sadece gerekli olduğunda kullanın ve mümkün olduğu kadar kısa sürede elinizde tutun. Örneğin, bir Activity içinde asla Wakelock kullanmayın. Çünkü Activity UI'ı ilgilendiren bir bileşendir. Bunun yerine yukarıda açıklandığı gibi eğer Activity'niz açıkken ekranın açık olmasını istiyorsanız FLAG_KEEP_SCREEN_ON bayrağını kullanın.

Şu işlerde Wakelock kullanmaktan daha iyi alternatifler var:

  • Uygulamanız uzun süren HTTP indirme işleri yapıyorsa DownloadManager kullanın.
  • Uygulamanız dışarıdaki bir sunucudan gelen verileri eşlemeyle uğraşıyorsa Sync Adapter kullanın.
  • Uygulamanız arka plan servislerine dayalı çalışıyorsa, belli aralıklarla bu servisleri tetiklemek için tekrarlanan uyarılar (alarm) veya Google Cloud Messaging kullanın.

Wakelock kullanmak için haklı sebeplerden biri örneğin şu olabilir: Bir arka plan servisiniz olduğunu varsayalım. Ekran kapalı olduğu sırada işini yapmak için işlemcinin açık olmasını gerektiriyor. O zaman Wakelock alabilirsiniz. Yine de bu işlemi batarya üzerine olan etkilerinden dolayı olabildiğince az yapılmalıdır.

Wakelock kullanmak için ilk adım, uygulamanızın manifest dosyasına WAKE_LOCK iznini eklemektir.

 

<uses-permission android:name="android.permission.WAKE_LOCK" />

 

Eğer uygulamanızın bazı işlerini yapması için servis(leri) kullanan bir broadcast receiver'ı varsa (aşağıdaki "WakefulBroadcastReceiver'ı Kullanmak" bölümünde anlatıldığı gibi) bir WakefulBroadcastReceiver ile Wakelock'ları yönetebilirsiniz. Bu tercih ettiğimiz bir yaklaşım. Eğer uygulamanızda bu tasarım desenini uygulamak istemezseniz de Wakelock'u şu örnekteki gibi doğrudan ayarlayabilirsiniz:

PowerManager powerManager = (PowerManager) getSystemService(POWER_SERVICE);
Wakelock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
        "MyWakelockTag");
wakeLock.acquire();

Wakelock'u serbest bırakmak için wakelock.release() metodunu çağırabilirsiniz. Bu metot, CPU'ya yaptığınız isteği boşa çıkarır. Bir wakelock'u serbest bırakma konusundaki dikkat etmeniz gereken en önemli husus, batarya tüketiminin önüne geçmek için uygulama sonlanırken serbest bırakmaktır.

 

WakefulBroadcastReceiver'ı kullanmak

Bir broadcast receiver'ı bir servisle bir arada kullanarak arka plandaki işin yaşam döngüsünü yönetebilirsiniz. Bir WakefulBroadcastReceiver, uygulamanız için PARTIAL_WAKE_LOCK (kısmi wakelock) oluşturma ve yönetme işini üstlenen özel bir broadcast receiver'dır. WakefulBroadcastReceiver, (tıpkı IntentService gibi) bir Service nesnesine işleri taşır ve bunu yaparken taşıma sırasında cihaz uyku moduna geçemez. Bir servise iş taşırken wakelock'u aktif tutmak istemiyorsanız, iş bitirilmeden önce cihazın uykuya geri dönmesine olanak verebilirsiniz ancak elinize, yaptığı işi bitirmemiş (gelişigüzel bir yere kadar çalışmış ve istemediğiniz) uygulamanızın sonucu kalabilir.

WakefulBroadcastReceiver kullanmanın ilk adımı onu tıpkı diğer broadcast receiver'lar için yaptığınız gibi manifest dosyasına eklemektir:

<receiver android:name=".MyWakefulReceiver"></receiver>

Aşağıdaki kod parçasında MyIntentService isimli servis startWakefulService() metoduyla başlatılıyor. Bu metod servis başladığında Wakelock alan WakefulBroadcastReceiver hariç startService() ile neredeyse aynı. Ayrıca startWakefulService() metoduna parametre olarak geçilen Intent, Wakelock hakkında ekstra tanımlama bilgisi içerir:

public class MyWakefulReceiver extends WakefulBroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // Servisi başlatır ve servis çalışırken cihazı uyanık tutar.
        // Bu 'service' isimli Intent de servise ulaştırılacak.
        Intent service = new Intent(context, MyIntentService.class);
        startWakefulService(context, service);
    }
}

Buradaki MyIntentService isimli servis, işini bitirdiğinde Wakelock'u serbest bırakmak için MyWakefulReceiver.completeWakefulIntent() metodunu çağırır. Aşağıdaki kod parçasında gördüğünüz completeWakefulIntent() metodundaki Intent, yukarıdaki örnekte gönderdiğiniz Intent ile aynıdır.

public class MyIntentService extends IntentService {
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager mNotificationManager;
    NotificationCompat.Builder builder;
    public MyIntentService() {
        super("MyIntentService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();

        // Burada işlemciyi çalışır halde tutmayı gerektirecek bir iş yapabilirsiniz
        // ...
        // WakefulBroadcastReceiver'ın sağladığı wakelocku serbest bırakalım

        MyWakefulReceiver.completeWakefulIntent(intent);
    }
}

 

Bu sayfadaki parçalar Android Open Source Project kapsamında oluşturulmuş ve paylaşılmış içeriğin küçük değişiklikler yapılmış hâlidir ve Creative Commons 2.5 Attribution License'ta belirlenen koşullara göre kullanılmıştır.

Bu eğitim içeriğinin orijinal hâline buradan ulaşabilirsiniz: Keeping Device Awake