0

ユーザーの操作でそれ自体のインスタンスをさらに起動するアクティビティがあります。このアクティビティは、Bluetooth 接続を維持するサービスにバインドします。現在、これは次のように実現されています。

@Override
public void onResume()
{
    super.onResume();
    //bind the activity to the service when it is not bound yet.
    if (!this.isBound)
    {
        //Application context, because the Connection shall be kept over configuration change, and the activity will be replaced then.
        Intent serviceIntent = new Intent(this.getApplicationContext(), ConnectionService.class);
        bindService(serviceIntent, this.connection, Context.BIND_AUTO_CREATE);
        this.isBound = true;
    }
    else
    {
        this.connection = (ServiceConnection)getLastNonConfigurationInstance();
    }
    this.visible = true;
}

/**
 * Saves the bound state.
 */
@Override
public void onSaveInstanceState(Bundle outState)
{
    outState.putBoolean("isBound", this.isBound);
}

/**
 * Loads the bound state.
 */
@Override
public void onRestoreInstanceState(Bundle inState)
{
    this.isBound = inState.getBoolean("isBound");
}

/**
 * Called by system, gives the current ServiceConnection to the system to be retrieved again after restart.
 */
@Override
public Object onRetainNonConfigurationInstance() {
    return this.connection;
}

@Override
public void onPause()
{
    //unbind the activity to the service when it is finishing.
    super.onPause();
    this.visible = false;
    if (this.isFinishing() && this.isBound)
    {
        unbindService(this.connection);
        this.isBound = false;
    }
}

今私の問題は次のとおりです。アプリの実行中に向きを変更すると、戻るボタンを押すまですべて問題ありません。それで

07-05 12:07:03.039: E/ActivityThread(17850): Activity mm.android.prototype.uilayer.DatapointActivity has leaked ServiceConnection mm.android.prototype.uilayer.DatapointActivity$1@408bcbb8 that was originally bound here  

07-05 12:07:03.039: E/ActivityThread(17850): android.app.ServiceConnectionLeaked: Activity mm.android.prototype.uilayer.DatapointActivity has leaked ServiceConnection mm.android.prototype.uilayer.DatapointActivity$1@408bcbb8 that was originally bound here

とログに書かれており、unbind コマンドの onPause() メソッドでアプリがクラッシュします。Google フォーラムで Dianne Hackborn の投稿を読んだことがありますが、ServiceConnection に頼ることはできませんが、それに対処する方法が見つかりませんでした。このエラーを解消したり、アプリがこのように動作する理由を説明したりできますか?

4

1 に答える 1

2

ServiceConnection を静的にして、myActivity のすべてのインスタンスで再利用することで解決しました。また、インスタンスをカウントする静的カウンターを追加し、最後のインスタンスが閉じるとアンバインドします。これにより、構成変更の問題も解決されます。

private boolean isBound = false;

private static int bindCount = 0;

// handles the service connection.
protected static ServiceConnection connection = new ServiceConnection(){
// ...
}

@Override
public void onResume()
{
    super.onResume();
    //bind the activity to the service when it is not bound yet.
    if (!this.isBound)
    {
        if (bindCount == 0) {
            //Application context, because the Connection shall be kept over configuration change, and the activity will be replaced then.
            Intent serviceIntent = new Intent(this.getApplicationContext(), ConnectionService.class);
            bindService(serviceIntent, DatapointActivity.connection, Context.BIND_AUTO_CREATE);
            this.isBound = true;
        }
        bindCount++;
        this.isBound = true;
    }
    this.visible = true;
}

/**
 * Saves the bound state.
 */
@Override
public void onSaveInstanceState(Bundle outState)
{
    outState.putBoolean("isBound", this.isBound);
}

/**
 * Loads the bound state.
 */
@Override
public void onRestoreInstanceState(Bundle inState)
{
    this.isBound = inState.getBoolean("isBound");
}

@Override
public void onPause()
{
    //unbind the activity of the service when it is finishing.
    super.onPause();
    this.visible = false;
    if (this.isFinishing())
    {
        if(bindCount <= 1 && this.isBound )
        {
            unbindService(DatapointActivity.connection);                
        }
        bindCount--;
    }

}
于 2012-07-05T12:51:22.230 に答える