Діяльність <Назва програми> просочилася ServiceConnection <ServiceConnection Name> @ 438030a8, яка спочатку була пов'язана тут


134

Я працюю над своїм першим додатком для Android. У моєму додатку три дії, і користувач перемикається вперед і назад досить часто. У мене також є віддалений сервіс, який обробляє з'єднання telnet. Програми повинні прив'язуватися до цієї послуги, щоб надсилати / отримувати повідомлення telnet.

Редагувати Дякую BDLS за інформативну відповідь. Я переписав свій код з огляду на ваше роз’яснення щодо різниці між використаннямbindService()як автономної функції або післяstartService(), і тепер я отримую повідомлення про помилку протікання лише з перервами при використанні кнопки «назад» для переходу між діями.

Моя зв'язок діяльність має наступні onCreate()і 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()

Таким чином, послуга запускається при запуску діяльності, і припиняється, коли діяльність знищується, якщо не було здійснено успішне з'єднання telnet ( connectStatus == 0). Інші дії пов'язуються з сервісом лише в тому випадку, якщо було встановлено успішне з'єднання ( connectStatus == 1збережено до загальних налаштувань). Ось їх onResume()і 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()

Таким чином, прив'язка відбувається onResume()так, що вона підбере змінений стан з активності з'єднання, а у onDestroy()функції - при незв'язуванні.

Завершити редагування

Але я все одно отримую повідомлення про помилку витоку пам'яті "Активність просочилася ServiceConnection @ 438030a8, яка спочатку була пов'язана тут" під час переключення діяльності. Що я роблю неправильно?

Заздалегідь дякую за будь-які поради чи вказівки !!!

Наступне повідомлення про помилку (з переглянутого коду):

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

Відредагуйте другу
подяку ще раз bdls за ваші пропозиції. Я зробив так, як ви запропонували, і додавonUnBind()перевагу до служби. onUnBind()насправді спрацьовує лише тоді, коли всі клієнти відключаються від послуги, але коли я натискаю кнопку додому, вона виконується, тоді з'являється повідомлення про помилку! Це не має для мене сенсу, оскільки всі клієнти не були пов'язані з сервісом, тож як один знищений витік сервісного з’єднання? Перевір:

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

Я думав, що це може бути щось подібне, як ви сказали, де прив'язка до послуги не завершена, коли unbindService()викликається, проте я намагався викликати метод у службі, коли я робив резервну копію кожної діяльності, щоб перевірити, чи прив'язка завершена, і всі вони перейшли через прекрасне.

Взагалі така поведінка не схожа на те, як довго я тримаюсь у кожній діяльності. Після того, як перша активність просочується своїм службовим зв’язком, проте, всі вони роблять так, як я повертаюся через них після цього.

Ще одна річ, якщо я ввімкнув "Негайно знищити діяльність" в Dev Tools, це запобігає цій помилці.

Будь-які ідеї?


Чи можете ви додати код LightfactoryRemote.onCreate ()? (com.wingedvictorydesign.LightfactoryRemote.LightfactoryRemote.onCreate (LightfactoryRemote.java:97))
tbruyelle

Відповіді:


57

Ви не надали жодного свого коду LightFactoryRemote, тому це лише презумпція, але це схоже на проблему, яку ви бачили, якби ви bindServiceсамостійно використовували метод.

Для того, щоб послуга продовжувала працювати, навіть після того, як діяльність, яка розпочалася, вона мала onDestroyназву свого методу, слід спочатку скористатися startService.

Документи Android для стану startService :

Використання startService () переосмислює термін служби служби за замовчуванням, яким керує bindService (Intent, ServiceConnection, int): вона вимагає, щоб служба продовжувала працювати до виклику stopService (Intent), незалежно від того, чи підключені до неї будь-які клієнти.

Тоді як для bindService :

Послуга вважатиметься необхідною системою лише до тих пір, поки існує контекст виклику. Наприклад, якщо цей контекст - це діяльність, яка зупинена, сервісу не потрібно буде продовжувати працювати, поки активність не буде відновлено.


Отже, те, що сталося, - це діяльність, яка зв'язала (і тому почала) послугу, була зупинена, і, таким чином, система вважає, що служба більше не потрібна і викликає цю помилку (а потім, ймовірно, припиняє службу).


Приклад

У цьому прикладі послугу слід продовжувати працювати незалежно від того, виконується виклик.

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

Перший рядок запускає послугу, а другий прив'язує її до активності.


Я запускаю службу за допомогою START_STICKY, і вона також починається з наміру завантаження. Якщо я закликаю StartService, він створює інший екземпляр послуги, і я не хочу одночасно працювати 2 служби. Як я можу виправити помилку в цьому випадку?
opc0de

16
@ opc0de, ні, ви не створюєте іншої послуги, коли ви телефонуєте startService () двічі. Послуги за своєю суттю логічно одинакові. Незалежно від того, скільки разів ви її запускаєте, працює лише одна послуга.
mahkie

2
Яке рішення для продовження обслуговування у фоновому режимі для музичного плеєра?
Ананд Савяні


31

Ви пов'язуєте, onResumeале розв'язуєте onDestroy. Ви повинні зробити від’єднання onPauseзамість цього, щоб завжди були відповідні пари дзвінків / зв'язувань. Ваші періодичні помилки полягатимуть там, коли ваша діяльність призупинена, але не знищена, а потім відновиться знову.


13

Вам слід лише від’єднати послугу в onDestroy(). Потім, попередження піде.

Дивіться тут .

Як намагається пояснити документ про активність, існують три основні групи зв'язування / відключення: onCreate () і onDestroy (), onStart () і onStop (), onResume () і onPause ().


7
як ви могли б мати eyperienced onDestroy майже ніколи не дзвонили з операційної системи
martyglaubitz

Дивіться тут посилання вперед до забороненого вмісту -> Попередження про заборонений вміст. Хтось може отримати доступ? Кнопка «Продовжити до групи» просто оновлює сторінку і показує те саме попередження для мене.
Blaze Gawlik

11

Ви згадуєте, що користувач досить швидко перемикався між видами діяльності Можливо, ви телефонуєте unbindServiceдо встановлення з'єднання з послугою? Це може призвести до того, що не вдасться від’єднати, а потім протікати зв'язування.

Не зовсім впевнений, як ви могли це впоратися ... Можливо, коли onServiceConnectedвам дзвонять, ви могли б зателефонувати, unbindServiceякщо onDestroyвже дзвонили. Не впевнений, чи все це спрацює.


Якщо ви ще цього не зробили, ви можете додати до своєї послуги метод onUnbind. Таким чином ви можете точно бачити, коли ваші класи відключаються від нього, і це може допомогти при налагодженні.

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

2

Спробуйте використовувати unbindService () в OnUserLeaveHint (). Це запобігає сценарію витоку ServiceConnection та інших винятках.
Я використовував його в своєму коді і працює чудово.


1

Ви можете просто керувати ним за допомогою булевого сигналу, тому ви можете відкликати лише відкликання, якщо було виконано прив'язку

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;
    }
}

Якщо ви хочете від’єднати його, лише якщо він був підключений

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

Кожен сервіс, який пов'язаний із діяльністю, повинен бути від’єднаний під час закриття програми.

Тому спробуйте використовувати

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

0

Я читав про Android Service зовсім недавно і отримав шанс глибоко пірнати на ньому. Я зіткнувся з витоком сервісу, оскільки в моїй ситуації це сталося тому, що у мене була служба без зв'язків, яка починала приєднану службу, але в цьому мою необмежену службу замінює активність .

Тож коли я зупиняв свою необмежену службу, використовуючи stopSelf (), витік стався, причиною цього було те, що я припиняв батьківську службу, не розв'язуючи прив'язану послугу. Тепер прив’язана служба працює, і вона не знає, кому вона належить.

Легкий і прямий виправлення вперед - вам слід зателефонувати unbindService (YOUR_SERVICE); у функції onDestroy () вашого батька Діяльність / Служба. Таким чином життєвий цикл забезпечить припинення чи очищення пов'язаних служб до того, як активність / послуги вашого батька знизяться.

Існує ще одна різновид цієї проблеми. Іноді у вашому зв’язаному сервісі ви хочете, щоб певні функції працювали лише в тому випадку, якщо служба зв'язана, і ми в кінцевому підсумку ставимо прив’язаний прапор до onServiceConnected, як:

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

Це добре працює до цих пір, але проблема виникає, коли ми розглядаємо функцію onServiceDisconnected як зворотний виклик для виклику unbindService , ця документація викликається лише тоді, коли служба вбита або зламається . І ви ніколи не отримаєте цей зворотний виклик у тій самій нитці . Отже, ми закінчуємо щось таке:

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

Що створює велику помилку в коді, оскільки наш зв'язаний прапор ніколи не повертається до значення false, і коли ця послуга знову підключається знову більшість разів true. Отже, щоб уникнути цього сценарію, слід встановити значення boundfalse, коли ви телефонуєтеunbindService .

Це докладніше висвітлюється в блозі Еріка .

Сподіваюся, що коли-небудь сюди завітав, його цікавість задовольнила.


0

ця помилка трапляється, коли ви збираєтеся зв’язати обмежену послугу. Отже, золь повинен бути: -

  1. в сервісне підключення додайте serviceBound, як показано нижче:

    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

        if (serviceBound) {
            unbindService(serviceConnection);
        }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.