<Uygulama Adı> etkinliği, başlangıçta buraya bağlı olan ServiceConnection <ServiceConnection Name> @ 438030a8'i sızdırdı


134

İlk Android uygulamam üzerinde çalışıyorum. Uygulamamda üç etkinliğim var ve kullanıcı oldukça sık geçiş yapıyor. Ayrıca bir telnet bağlantısını yöneten bir uzak servisim var. Telnet mesajlarını göndermek / almak için uygulamaların bu hizmete bağlanması gerekir.

Düzenle Bilgilendirici cevabınız için teşekkür ederiz BDLS. Kodumu,bindService()bağımsız bir işlev olarak veya sonrasındakullanmak arasındaki farkla ilgili açıklamanızın ışığında yeniden yazdımstartService()ve şimdi yalnızca faaliyetler arasında geçiş yapmak için geri düğmesini kullandığımda sızıntı hata mesajını aralıklı olarak alıyorum.

Bağlantı etkinliğim şunları içeriyor onCreate()ve onDestroy():

/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    /*
     * Initialize the ServiceConnection.  Note that this is the only place startService() is run.
     * It is also the only time bindService is run without dependency on connectStatus.
     */
    conn = new TelnetServiceConnection();
    //start the service which handles telnet
    Intent i = new Intent();
    i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
    startService(i);
    //bind to the service
    bindService(i, conn, 0);

    setContentView(R.layout.connect);
    setupConnectUI();

}//end OnCreate()

@Override
protected void onDestroy() {
    super.onDestroy();

    //unbind the service and null it out
    if (conn != null) {
        unbindService(conn);
        conn = null;
        }

    if(connectStatus == 0) {
        //stop the service
        Intent i = new Intent();
        i.setClassName( "com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService" );
        stopService(i);
        Log.d("LightfactoryRemote", "Connect onDestroy() attempted to stop service");
        }

    Log.d("LightfactoryRemote", "Connect onDestroy()");
    }//end onDestroy()

Böylece hizmet, etkinlik başladığında başlatılır ve başarılı bir telnet bağlantısı yapılmadıysa etkinlik yok edildiğinde durdurulur ( connectStatus == 0). Diğer etkinlikler, yalnızca başarılı bir bağlantı yapıldığında ( connectStatus == 1paylaşılan tercihlere kaydedildiğinde) hizmete bağlanır . İşte onların onResume()ve onDestroy():

@Override
protected void onResume() {
    super.onResume();

    //retrieve the shared preferences file, and grab the connectionStatus out of it.
    SharedPreferences settings = getSharedPreferences(PREFS_NAME, MODE_WORLD_WRITEABLE);
    connectStatus = settings.getInt("connectStatus", 0);

    Log.d("LightfactoryRemote", "Focus onResume with " + connectStatus);

    //if a telnet connection is active, start the service and bind to it
    if (connectStatus == 1) {
        conn = new TelnetServiceConnection();
        Intent i = new Intent();
        i.setClassName("com.wingedvictorydesign.LightfactoryRemote", "com.wingedvictorydesign.LightfactoryRemote.TelnetService");
        bindService(i, conn, 0);
        //TODO write restore texview code
        }//end if
    }//end onResume

@Override
protected void onDestroy() {
    super.onDestroy();
    //unbind the service and null it out.
    if (conn != null) {
        Log.d("LightfactoryRemote", "Focus onDestroy() attempted to unbind service");
        unbindService(conn);
        conn = null;
        }
    Log.d("LightfactoryRemote", "Focus onDestroy()");
    }//end onDestroy()

Dolayısıyla, bağlanma onResume(), değiştirilen durumu bağlantı etkinliğinden alacak ve onDestroy()işlevde gerekirse bağlanmayacak şekilde gerçekleşir.

Düzenlemeyi Sonlandır

Ancak, etkinlikler arasında geçiş yaparken aralıklı olarak "Etkinlik, başlangıçta buraya bağlı olan ServiceConnection @ 438030a8'i sızdırdı" hata mesajını hala alıyorum. Neyi yanlış yapıyorum?

Herhangi bir ipucu veya işaretçi için şimdiden teşekkürler !!!

Tam hata mesajı aşağıdaki gibidir (revize edilmiş koddan):

01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onStop()
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy() attempted to unbind service
01-02 22:04:26.642: DEBUG/LightfactoryRemote(2024): Focus onDestroy()
01-02 22:04:26.672: ERROR/ActivityThread(2024): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@439e51e8 that was originally bound here
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:927)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:822)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ApplicationContext.bindService(ApplicationContext.java:842)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.content.ContextWrapper.bindService(ContextWrapper.java:319)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.Activity.performResume(Activity.java:3559)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2838)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2866)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2420)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.access$2100(ActivityThread.java:116)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1794)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.os.Looper.loop(Looper.java:123)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at android.app.ActivityThread.main(ActivityThread.java:4203)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at java.lang.reflect.Method.invokeNative(Native Method)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at java.lang.reflect.Method.invoke(Method.java:521)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:549)
01-02 22:04:26.672: ERROR/ActivityThread(2024):     at dalvik.system.NativeStart.main(Native Method)
01-02 22:04:26.692: WARN/ActivityManager(558): Unbind failed: could not find connection for android.os.BinderProxy@43c509a8


Önerileriniz için 2. Teşekkürler bdl'lerini bir kez daha düzenleyin. Önerdiğiniz gibi yaptımonUnBind()ve hizmetebirgeçersiz kılmaekledim. onUnBind()aslında yalnızca tüm istemcilerin hizmetten bağlantısı kesildiğinde tetikleniyor, ancak ana sayfa düğmesine bastığımda çalıştırılıyor, ardından hata mesajı çıkıyor! Tüm istemciler hizmetten ayrıldığından, bu bana mantıklı gelmiyor, peki yok edilen kişi bir hizmeti nasıl sızdırabilir? Bunu kontrol et:

01-03 19:38:30.837: DEBUG/LightfactoryRemote(1118): Focus onPause()1
01-03 19:38:31.577: WARN/IInputConnectionWrapper(1118): showStatusIcon on inactive InputConnection
01-03 19:38:31.587: DEBUG/LightfactoryRemote(1118): Focus onStop()
01-03 19:38:31.600: DEBUG/LightfactoryRemote(1118): Focus onDestroy() attempted to unbind service
01-03 19:38:31.607: DEBUG/LightfactoryRemote(1118): Focus onDestroy()
01-03 19:38:31.677: DEBUG/LightfactoryRemote(1125): TelnetService onUnBind()
01-03 19:38:31.727: ERROR/ActivityThread(1118): Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118): android.app.ServiceConnectionLeaked: Activity com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote has leaked ServiceConnection com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote$TelnetServiceConnection@435baeb0 that was originally bound here
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$PackageInfo$ServiceDispatcher.<init>(ActivityThread.java:886)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$PackageInfo.getServiceDispatcher(ActivityThread.java:781)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ApplicationContext.bindService(ApplicationContext.java:820)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.content.ContextWrapper.bindService(ContextWrapper.java:307)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onResume(LightfactoryRemote.java:102)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.Instrumentation.callActivityOnResume(Instrumentation.java:1225)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.Activity.performResume(Activity.java:3530)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.performResumeActivity(ActivityThread.java:2619)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:2647)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2287)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.access$1800(ActivityThread.java:112)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1692)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.os.Handler.dispatchMessage(Handler.java:99)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.os.Looper.loop(Looper.java:123)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at android.app.ActivityThread.main(ActivityThread.java:3948)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at java.lang.reflect.Method.invokeNative(Native Method)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at java.lang.reflect.Method.invoke(Method.java:521)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:782)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:540)
01-03 19:38:31.727: ERROR/ActivityThread(1118):     at dalvik.system.NativeStart.main(Native Method)
01-03 19:38:31.777: WARN/ActivityManager(564): Unbind failed: could not find connection for android.os.BinderProxy@4370f8a8

Söylediğiniz gibi, hizmete bağlanmanın unbindService()çağrıldığında tamamlanmadığı bir şey olabileceğini düşündüm , ancak bağlamanın tamamlandığını doğrulamak için her aktiviteyi destekledikçe hizmette bir yöntem çağırmayı denedim ve hepsi gitti iyi aracılığıyla.

Genel olarak, bu davranış her aktivitede ne kadar kaldığımla ilgili görünmüyor. Ancak ilk etkinlik serviceConnection'ı sızdırdığında, hepsi ondan sonra geri döndüğüm gibi yapıyorlar.

Diğer bir şey, Dev Tools'da "Etkinlikleri hemen yok et" seçeneğini açarsam, bu hatayı önler.

Herhangi bir fikir?


LightfactoryRemote.onCreate () kodunu ekleyebilir misiniz? (com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onCreate (LightfactoryRemote.java:97))
tbruyelle

Yanıtlar:


57

Kodunuzun hiçbirini LightFactoryRemotekaynağından sağlamadınız, bu nedenle bu yalnızca bir varsayımdır, ancak bindServiceyöntemi kendi başına kullanıyor olsanız göreceğiniz türden bir soruna benziyor .

Bir hizmetin çalışmaya devam etmesini sağlamak için, başlatılan etkinlik onDestroyyöntemini çağırdıktan sonra bile , önce kullanmalısınız startService.

StartService durumu için android dokümanlar :

StartService () kullanımı, bindService (Intent, ServiceConnection, int) tarafından yönetilen varsayılan hizmet ömrünü geçersiz kılar: herhangi bir istemcinin bağlı olup olmadığına bakılmaksızın, stopService (Intent) çağrılana kadar hizmetin çalışır durumda kalmasını gerektirir.

BindService için ise :

Hizmet, yalnızca çağıran bağlam var olduğu sürece sistem tarafından gerekli kabul edilecektir. Örneğin, bu Bağlam durdurulmuş bir Aktivite ise, Aktivite devam ettirilene kadar hizmetin çalışmaya devam etmesi gerekmeyecektir.


Öyleyse olan şey, hizmeti bağlayan (ve dolayısıyla başlatan) faaliyet durdurulmuş ve bu nedenle sistem hizmetin artık gerekli olmadığını düşünerek bu hataya neden olur (ve muhtemelen hizmeti durdurur).


Misal

Bu örnekte, arama etkinliğinin çalışıp çalışmadığına bakılmaksızın hizmet çalışır durumda tutulmalıdır.

ComponentName myService = startService(new Intent(this, myClass.class));
bindService(new Intent(this, myClass.class), myServiceConn, BIND_AUTO_CREATE);

İlk satır servisi başlatır ve ikincisi onu aktiviteye bağlar.


Hizmeti START_STICKY kullanarak başlatıyorum ve aynı zamanda önyükleme amacı ile başlatılıyor. StartService'i çağırırsam, hizmetin başka bir örneğini oluşturur ve aynı anda 2 hizmetin çalışmasını istemiyorum. Bu durumda hatayı nasıl düzeltebilirim?
opc0de

16
@ opc0de, hayır startService () öğesini iki kez aradığınızda başka bir hizmet oluşturmuyorsunuz. Hizmetler, doğası gereği mantıksal olarak tekildir. Kaç kez başlatırsanız başlatın, yalnızca bir hizmet çalışır.
mahkie

2
Müzik çalar için arka planda devam eden servis için çözüm nedir?
Anand Savjani

45

Kullanabilirsiniz:

@Override
public void onDestroy() {
    super.onDestroy();

    if (mServiceConn != null) {
        unbindService(mServiceConn);
    }
}

Mükemmel. İşte bu.
Seltsam

31

İçeri bağlanan onResumeancak unbind içinde onDestroy. Bunun onPauseyerine çözme işlemini yapmanız gerekir , böylece her zaman eşleşen bağlama / çözme çağrıları çiftleri olur. Aralıklı hatalarınız, etkinliğinizin duraklatıldığı, ancak yok edilmediği ve ardından yeniden başlatıldığı yerde olacaktır.


13

Yalnızca içinde hizmetin bağlantısını kaldırmanız gerekir onDestroy(). Ardından uyarı gider.

Buraya bakın .

Activity doc açıklamaya çalıştığı gibi, kullanacağınız üç ana bağlama / çözme grubu vardır: onCreate () ve onDestroy (), onStart () ve onStop () ve onResume () ve onPause ().


7
onDestroy'da deneyimlemiş olabileceğiniz gibi , işletim sisteminden hemen hemen hiç
aranmıyor

Yasaklanmış içeriğe yönlendirmek için buraya bakın -> Yasaklı İçerik Uyarısı. Herkes erişebilir mi? "Gruba Devam Et" butonu sadece sayfayı yeniliyor ve benim için aynı uyarıyı gösteriyor.
Blaze Gawlik

11

Kullanıcının Etkinlikler arasında oldukça hızlı geçiş yaptığından bahsediyorsunuz. unbindServiceServis bağlantısı kurulmadan önce arıyor olabilir misiniz ? Bu, bağın çözülmemesi ve ardından bağlanmanın sızdırılması etkisine sahip olabilir.

Değil tamamen emin zaman belki ... Bu kaldırabileceğinden nasıl onServiceConnectedsen diyebiliriz denir unbindServiceeğer onDestroyzaten adı olmuştur. Yine de işe yarayıp yaramayacağından emin değilim.


Henüz yapmadıysanız, hizmetinize bir onUnbind yöntemi ekleyebilirsiniz. Bu şekilde, sınıflarınızın tam olarak ne zaman ayrıldığını görebilirsiniz ve hata ayıklamaya yardımcı olabilir.

@Override
public boolean onUnbind(Intent intent) {
    Log.d(this.getClass().getName(), "UNBIND");
    return true;
}

2

OnUserLeaveHint () içinde unbindService () kullanmayı deneyin. ServiceConnection sızan senaryosunu ve diğer istisnaları önler.
Kodumda kullandım ve iyi çalışıyor.


1

Sadece bir boole ile kontrol edebilirsiniz, böylece sadece bağlama yapılmışsa unbind çağırırsınız.

public void doBindService()
{
    if (!mIsBound)
    {
        bindService(new Intent(this, DMusic.class), Scon, Context.BIND_AUTO_CREATE);
        mIsBound = true;
    }
}

public void doUnbindService()
{
    if (mIsBound)
    {
        unbindService(Scon);
        mIsBound = false;
    }
}

Yalnızca bağlıysa bağlantısını çözmek istiyorsanız

public ServiceConnection Scon = new ServiceConnection() {

    public void onServiceConnected(ComponentName name, IBinder binder)
    {
        mServ = ((DMusic.ServiceBinder) binder).getService();
        mIsBound = true;
    }

    public void onServiceDisconnected(ComponentName name)
    {
        mServ = null;
    }
};

0

Etkinliğe bağlı olan her hizmetin, uygulama kapatıldığında bağlantısı kaldırılmalıdır.

O yüzden kullanmayı dene

 onPause(){
   unbindService(YOUR_SERVICE);
   super.onPause();
 }

0

Son zamanlarda Android Hizmeti hakkında bir şeyler okudum ve derinlemesine inceleme şansı buldum. Ben bir vardı çünkü olanlar benim durum için bir servis sızıntısı, karşılaştığım ilişkisiz bir başlangıç oldu Service bağlı Servisi, ancak bu benim ilişkisiz Hizmet bir değiştirilir Activity .

Dolayısıyla, stopSelf () kullanarak bağlanmamış Hizmetimi durdurduğumda sızıntı meydana geldi, bunun nedeni bağlı hizmetin bağını kaldırmadan üst hizmeti durdurmamdı . Artık bağlı hizmet çalışıyor ve kime ait olduğunu bilmiyor.

Kolay ve basit çözüm, unbindService (YOUR_SERVICE) çağırmanız gerektiğidir ; senin içinde OnDestroy () Ebeveyninizin Faaliyet / Hizmet fonksiyonu. Bu şekilde yaşam döngüsü, bağlı hizmetlerin, ana Faaliyetiniz / Hizmetleriniz düşmeden önce durdurulmasını veya temizlenmesini sağlayacaktır.

Bu sorunun bir başka çeşidi daha var. Bazen bağlı hizmetinizde belirli işlevlerin yalnızca hizmet bağlıysa çalışmasını istersiniz , bu nedenle onServiceConnected'a aşağıdaki gibi bir bağlı bayrak koyarız :

public void onServiceConnected(ComponentName name, IBinder service) {
            bounded = true;
            // code here
        }

Bu, buraya kadar iyi çalışıyor, ancak sorun, onServiceDisconnected işlevini unbindService işlev çağrısı için bir geri arama olarak ele aldığımızda ortaya çıkıyor , bu belgelerle yalnızca bir hizmet öldürüldüğünde veya çöktüğünde çağrılıyor . Ve bu geri aramayı asla aynı ileti dizisinde alamayacaksınız . Bu nedenle, şöyle bir şey yapıyoruz:

public void onServiceDisconnected(ComponentName name) {
            bounded = false;
        }

Bu, kodda büyük bir hata yaratır, çünkü bağlı bayrağımız asla yanlışa sıfırlanmaz ve bu hizmet çoğu zaman tekrar bağlandığında olur true. Bu nedenle, bu senaryodan kaçınmak boundiçin, aradığınız anda yanlış olarak ayarlamalısınız unbindService.

Bu, Erik'in blogunda daha ayrıntılı olarak ele alınmıştır .

Umarım buraya gelenler merakını tatmin eder.


0

bu hata, sınırlı bir hizmeti bağlayacağınız zaman ortaya çıkar. yani sol şöyle olmalıdır: -

  1. servis bağlantısında aşağıdaki gibi serviceBound ekleyin:

    private final ServiceConnection serviceConnection = new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        // your work here.
    
        serviceBound = true;
    
    }
    
    @Override
    public void onServiceDisconnected(ComponentName name) {
    
        serviceBound = false;
    }

    };

  2. onDestroy hizmetinin bağlantısını çöz

        if (serviceBound) {
            unbindService(serviceConnection);
        }
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.