Действие <Имя приложения> просочилось в ServiceConnection <Имя_соединения> @438030a8, которое было первоначально связано здесь

Я работаю над своим первым Android-приложением. У меня есть три действия в моем приложении, и пользователь довольно часто переключается туда и обратно. У меня также есть удаленная служба, которая обрабатывает telnet-соединение. Приложениям необходимо связать эту службу, чтобы отправлять/получать сообщения telnet.

Edit Спасибо 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.wingedvictorydesig[email protected]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.wingedvictorydesig[email protected]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 [email protected]

Изменить второй
Еще раз спасибо bdls за ваши предложения. Я сделал так, как вы предложили, и добавила переопределение onUnBind() в службу. onUnBind() фактически срабатывает только тогда, когда все клиенты отключаются от службы, но когда я нажимаю кнопку "домой", она выполняется, а затем появляется сообщение об ошибке! Для меня это не имеет смысла, так как все клиенты были отключены от службы, поэтому как можно уничтожить утечку serviceConnection? Проверьте это:

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.wingedvictorydesig[email protected]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.wingedvictorydesig[email protected]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 [email protected]

Я думал, что это может быть что-то вроде того, что вы сказали, где привязка к службе не завершена при вызове unbindService(), однако я попытался вызвать метод в службе, когда я поддерживал каждое действие, чтобы проверить, что привязка является и все они прошли хорошо.

В общем, это поведение не похоже на то, как долго я остаюсь в каждом мероприятии. Однако, как только первая активность протекает в своем сервисе соединения, они все делают, когда я возвращаюсь через них.

Еще одна вещь, если я включу "Немедленно уничтожить действия" в Dev Tools, она предотвратит эту ошибку.

Любые идеи?

Ответ 1

Вы не указали какой-либо код из LightFactoryRemote, так что это только презумпция, но это похоже на проблему, которую вы бы увидели, если бы вы использовали метод bindService.

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

Андроидные документы для startService state:

Использование функции 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);

Первая строка запускает службу, а вторая связывает ее с активностью.

Ответ 2

Вы привязываетесь в onResume, но отвязываете в onDestroy. Вы должны сделать развязывание в onPause вместо этого, так что всегда есть пары парных вызовов bind/unbind. Ваши прерывистые ошибки будут там, где ваша активность приостановлена, но не уничтожена, а затем снова возобновлена.

Ответ 3

Вы можете использовать:

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

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

Ответ 4

Вам нужно только отменить службу в onDestroy(). Затем появится предупреждение.

Смотрите здесь.

Как поясняет деятельность Doc, существует три основных привязки /unbind группировки, которые вы будете использовать: onCreate() и onDestroy(), onStart() и onStop() и onResume() и onPause().

Ответ 5

Вы говорите, что пользователь переключается между действиями довольно быстро. Может ли быть, что вы вызываете unbindService до того, как соединение службы установлено? Это может привести к отказу от отсоединения, а затем утечке привязки.

Не совсем уверен, как вы могли бы справиться с этим... Возможно, когда вызывается onServiceConnected, вы можете вызвать unbindService, если onDestroy уже вызван. Не уверен, что это сработает.


Если вы еще этого не сделали, вы можете добавить метод onUnbind к своей службе. Таким образом, вы можете точно видеть, когда ваши классы отключаются от него, и это может помочь при отладке.

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

Ответ 6

Попробуйте использовать unbindService() в OnUserLeaveHint(). Он предотвращает утечку сценария ServiceConnection и другие исключения.
Я использовал его в своем коде и прекрасно работал.

Ответ 7

Каждая служба, связанная с активностью, должна быть отключена при закрытии приложения.

Поэтому попробуйте использовать

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

Ответ 8

Вы можете просто управлять им логическим, поэтому вы вызываете unbind только в том случае, если была создана привязка

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