2013年5月26日日曜日

[Android]アプリケーションのActivityを全て終了してアプリを終了する

ある Activityからアプリケーションを終了しようとした場合、別の Activityが起動してあったりするとうまくいかなかったりします。

この場合、BroadcastRecieverを使えば、自分のアプリの Activityだけを終了させることができます。

ただ、BroadcastRecieverは外部アプリケーションからの Broadcastも受信できてしまうので、今回のケースのようなアプリケーション内で完結するような Broadcastの場合は LocalBroadcastManagerを使用したほうがよいです。

LocalBroadcastManager | Android Developers

LocalBroadcastManagerを使うことで、アプリケーション内で完結する Broadcastを送信したり、アプリケーション内でのみ動作する BroadcatRecieverを登録することができます。

で、アプリケーション終了の方法でが、全ての Activityに Reciverを登録しておき、終了処理を行う Activityから登録した IntentFiterの Broadcast を送信します。
Reciverの中では onReciveで Activity の finish()の呼び出しと Recieverの解除を行うだけです。

以下、サンプルコードです。
・MainActivity
package jp.inara.appfinishsample;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;

public class MainActivity extends Activity {

    BroadcastReceiver mReceiver;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        findViewById(R.id.button1).setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, SecondActivity.class);
                startActivity(intent);
            }
        });
        
        // BroadcastRecieverを LocalBroadcastManagerを使って登録
        IntentFilter intentFilter = new IntentFilter();
        intentFilter.addAction("jp.inara.appFinishSample.APP_FINISH");
        mReceiver = new BroadcastReceiver() {
            @Override
            public void onReceive(Context context, Intent intent) {
                LocalBroadcastManager.getInstance(getApplicationContext()).unregisterReceiver(mReceiver);
                finish();
            }
        };
        LocalBroadcastManager.getInstance(getApplicationContext()).registerReceiver(mReceiver, intentFilter);
    }
}

・SecondActivity
package jp.inara.appfinishsample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class SecondActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
        Button finishButton = (Button) findViewById(R.id.finish_button);
        finishButton.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                // LocalBroadcastManagerを使ってBroadcastを送信
                Intent appFinishIntent = new Intent();
                appFinishIntent.setAction("jp.inara.appFinishSample.APP_FINISH");
                LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(appFinishIntent);
                finish();
            }
        });
    }
}

ただ、BroadcastManagerはそもそも Serviceから Activityを呼び出したりする時に使ったりするものなので、この使い方が間違っている可能性大です。。。

2013年5月3日金曜日

[android][ListView]FooterViewのハマりどころ

ListViewのFooterの設定をした際に色々ハマったのでメモ。

addFooterView と removeFooterView に指定するインスタンス


addFooterView と removeFooterView に指定するインスタンスは同一のインスタンスである必要があるみたいです。
xml リソースから View を生成している場合、View を使うタイミングで findViewById で View を取得したりすると思いますが、この場合はインスタンス自体は別になってしまうので addFooterView で追加した Footer を removeFooterView で削除することはできません。
addFooter する View はメンバ変数などで保持していく必要があるみたいです。

Footerに指定するViewをXMLから生成する場合


Footerに指定するViewをXMLから生成する場合、root の View に layout_margin を設定してもうまく設定されないようです。 marginの設定をしたい場合は rootView の配下の View に対して設定する必要があります。つまり、

LinearLayout ー Button 

のような Layout を Footer に設定する場合、root の LinearLayoutに margin を設定してもうまく設定されません。
もし LinearLayout に margin を 設定した場合は、

LinearLayout ー LinearLayout  ー Button 

のような Layout にし、子の LinearLayout に margin を設定するとうまく設定されるみたいです。
# ただしこの方法だと Lint から怒られます。もっと良い方法が本当はあるのかも。

こういうのは Reference 見るとちゃんと書いてあったりするのかなー??