Soru & Cevap

Bellekten Tamamen Kaldırılan Uygulama Çalışmaya Devam Ediyor ...

24.12.2013 - 04:55

Merhaba,

Service ile çalışan bir radyo uygulaması geliştiriyorum. Uygulama çalışırken home tuşuna basıp ardından da uygulamayı stoplamadan telefonun belleğinden kaldırdıgımda bir kac saniye kapalı kalıyor sonra calısmayı sürdürüyor. Bu sıkıntıyı nasıl aşabilirim?

Service im;

[code]

package com.denemeservis;

import java.io.IOException;

import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnBufferingUpdateListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.IBinder;
import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.widget.Toast;
public class DinlemeServisi extends Service {

    private final String url[] = { "http://85.95.248.115:8014/"};
    public static Boolean phoneRinging = false;
    private MediaPlayer player;
   

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.d("onStart", "onStart");
        dinlemeBaslasin();
        startPlaying();

        /*if(url[0] != null){
            intent.putExtra("http://85.95.248.115:8014/", 0);
        }if(url[1] != null){
            intent.putExtra("http://yayin2.yayindakiler.com:4056/", 1);
        }if(url[2] !=null){
            intent.putExtra("http://85.95.248.115:8008/", 2);
        }if(url[3] !=null){
            intent.putExtra("http://85.95.248.115:8006/", 3);
        }if(url[4] !=null){
            intent.putExtra("http://85.95.248.115:8018/", 4);
        }if(url[5] !=null){
            intent.putExtra("http://85.95.248.115:8002/", 5);
        }*/

        return Service.START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {

        return null;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d("onDestroy", "onDestroy");
        stopPlaying();
        if (player != null) {
            if (player.isPlaying()) {
                player.stop();
            }
            player.release();
        }
    }

    private void dinlemeBaslasin() {
        Log.d("dinlemeBaslasin", "dinlemeBaslasin");
        player = new MediaPlayer();
        try {
            player.setDataSource(url[0]);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        player.setOnBufferingUpdateListener(new OnBufferingUpdateListener() {

            @Override
            public void onBufferingUpdate(MediaPlayer mp, int percent) {
                Log.d("Buffering", "" + percent);
            }
        });

    }

    private void startPlaying() {
        Log.d("startPlaying", "startPlaying");
        player.prepareAsync();
        player.setOnPreparedListener(new OnPreparedListener() {

            @Override
            public void onPrepared(MediaPlayer mp) {
                Toast.makeText(getApplicationContext(), "Yayın Başladı",
                        Toast.LENGTH_SHORT).show();
                player.start();
                player.isLooping();
            }
        });
    }

    private void stopPlaying() {
        Toast.makeText(getApplicationContext(), "Yayın Durdu", Toast.LENGTH_SHORT)
                .show();
        Log.d("stopPlaying", "stopPlaying");
        player.stop();
        player.release();
        dinlemeBaslasin();
    }

}

[/code]
5 Görüntülenme

7 Cevap

Sitedeki sorulara cevap verebilmek için giriş yapın ya da üye olun.

picture-9853-1415485106.jpg
coder86
31.12.2013 - 04:31

Değerli İzzet Kerem Küsmezer ve Değerli Oytun Ern Şengül;

Cevaplarınız ve geniş anlatım için çok teşekkür ederim. Ancak ben bu sorunun önüne nasıl geçebilirim, bununla ilgili bir örnek yada tutorial varmı? Bu sıkıntıyı aşmayı nasıl öğrenebilirim ve ileride diğer projelerde bunu nasıl kullanabilirim? :)

picture-242-1392640755.jpg
oytuneren
31.12.2013 - 12:14

Hadi başlayalım o zaman :)

@Kerem,

Servis tabii ki çekirdeğin bir özelliği ve son derece de normal bir durum. Ancak sıkıntı işletim sisteminin ihtiyaçlarıyla çekirdeğin ne oradan bu ihtiyaçlara cevap vermesiyle alakalı bir durum.

Android, JVM kullandığı için arka planda çalıştırması gerken uygulamalarda daha fazla RAM'e ihtiyaç duyuyor. Bu da Linux çekirdeğinin olağan low memory killer yapısına uymuyor. Normalde çekirdekten beklenen bu gibi durumlarda process'i kill etmesidir. Ancak kill ettikten sonra uygulamayı her seferinde runtime'da çalıştırmak, donanıma ve direkt Android'de JVM'e bağlı olarak daha geç başlatılacağı için, işletim sistemi hiç bu (OOM)'e girmek istemiyor ve her zaman daha fazla RAM tutuyor. Ya da bazı noktalarda tutuyor gibi de gösterebiliyor.

Asıl olan, olması gereken ya da performans bakımından daha iyi sonuçlar alabileceğiniz yapı (bu tamamen stratejik bir karardır ve Google bu noktada doğru bir karar vermiş olabilir başlangıç açısından) örneğin herhangi bir GNU/Linux sistemde olduğu gibi, isterseniz kill edebilmenizdir. Daha öncede bahsettiğim gibi sonuçta yazdığınız uygulamaların derlenme sürelerine ve daha birçok etmene bağlı olarak bu stratejik olarak verebileceğiniz bir karadır, tartışma ancak bu noktada olabilir.

Sonuç olarak, arkadaşın yazdığına bir alternatif olarak tekrar belirteyim. Bir GNU/Linux işletim sisteminiz varsa, bu masaüstünde Ubuntu olabilir ya da mobilde MeeGo, siz yazdığınız uygulamayı ister kill ettirebilir isterseniz de, istediğiniz oranda arkada çalıştırabilir ve başka uygulamalarda da kullanabilirsiniz. (Tabi bazı genel Linux çekirdeği standartlarına uymanız ya da dbus'da bazı ayarlamalar yaparsanız. Ayrıca aklıma gelmişken mainline linux çekirdeğinde bu gibi sebeplerden, özellikle Andorid ve embedded sistemci arkadaşların istekleri doğrultusunda kdbus adında yeni bir dbus oluşturuluyor.) Hatta bunu Linux olmayan bir mobil işletim sistemi BlackBerry 10'da bile yapabilirsiniz. Yalnız BlackBerry 10'da çekirdeğe bu kadar müdale izni olmadığı gibi, dbus ayarlamaya gerek de yok, zira zaten dbus'da yok.

İzzet Kerem Küsmezer
31.12.2013 - 01:38
Oytun, Android'de JVM yok :)
Oytun Eren Şengül
31.12.2013 - 07:42
Ya Keremcim, o kadar yazı yazdık, içinden onu mu çıkardın :) Kusura bakmayın arkadaşlar, JVM kısımlarında Dalvik'i kast etmiştim.
picture-483-1374012946.jpg
kerem.kusmezer
30.12.2013 - 06:20

Oytun,

http://www.oracle.com/technetwork/articles/servers-storage-dev/oom-killer-1911807.html

buraya da bakacak olursan, low memory killer direkt bir kernel servisi ve problemin açıkçası dalvik ile çok alakası yok. 

picture-242-1392640755.jpg
oytuneren
29.12.2013 - 09:55

Bu durumun yaşanmasının temel sebebi, daha önce @İzzetKeremKüsmezer ile de defalarca tartıştığımız, Android'in mainline linux çekirdeğinden farklı bir çekirdek kullanması (son zamanlara kadar) ve Android'in Java'ya ve dolayısıyla JVM'e olan bağımlılığıdır.

Mainline Linux çekirdeği kullanan bir işletim sisteminde, örneğin Ubuntu'da, C ile yazdığınız bir uygulamada bu bahsettiğinizi rahatlıkla gerçekleştirebilirsiniz.

Nurettin
29.12.2013 - 10:38
Java tarafında bu sıkıntıyı aşmanın herhangi bir yolu yok sanırsam. Birde Android ' in yeni SDK sı ART ile acaba bu sıkıntıya çözüm olacak mı? Teşekkürler.
Oytun Eren Şengül
30.12.2013 - 04:25
ART bu soruna değil ama bu soruna bağlı sistemin genel çalışmasına epey etkili olacaktır. Uygulamanıza bu noktada bir etkisi olup olamayacağını açıkçası geldikten sonra bakmak lazım.
picture-483-1374012946.jpg
kerem.kusmezer
27.12.2013 - 01:35

İki üç gün içinde bu konuyla ilgili olarak bir blog yazım yayınlanacak, sorun için tekrardan teşekkür ederim.

Nurettin
27.12.2013 - 06:59
Bloğunuzu takibe başlıycam :)
picture-483-1374012946.jpg
kerem.kusmezer
27.12.2013 - 01:21

Detaylı bilgiye aşağıdaki link'tende ulaşabilirsin.

http://elinux.org/Android_Notes#oom_killer_info

picture-483-1374012946.jpg
kerem.kusmezer
26.12.2013 - 03:06

Bu Android'in MemoryManagement yapısından kaynaklanıyor.

Android'de bir process'i başlattığın zaman içindeki Servis , Activity vs.'yi çağırdığında, servis kapatıldıktan sonra onu host eden process kill edilmez ( Daha hızlı startup time) , Linux kernel ancak bu processleri LVM ( Low Memory Killer ) içinde uygulamanın içindeki yapılara göre tanımlanmış limitlerin altında kaldığında gerekli olduğu durumlarda kapatır. Bu davranış Android için tamamen normaldir.

Aşağıdaki makalelerde niye böyle olduğunu okuyabilirsin.

Kolay Gelsin.

http://www.droid-life.com/2011/06/02/revisiting-android-task-killers-and-why-you-dont-need-one/