ADTでプロジェクトを新たに作った時,デフォルトで1つのアクティビティが生成される.しかし,本格的なプログラムではいくつかのアクティビティを使用する.例えばスタート画面や設定画面,プレイ画面などがある.本稿では,複数のアクティビティを作り方のメモである.
アクティビティを追加するには次の3つのことを行わなければならない.
3つ目についてはなくても可能である.また,2つ目についてはファイルを分ける必要はない.しかし,本稿ではアクティビティ毎にファイルを分ける方針を取る.
レイアウトの生成は次のような手順で行う.
- [File]を選択.
- [New]を選択.
- [Android XML File]を選択
- レイアウト名を指定.
- レイアウトの種類を指定.
- [Next >]を選択.
- [Finish]を選択.
本稿では,レイアウトの種類は"RelativeLayout"を選択する.また,レイアウト名にはactivity_sub.xmlと付ける.
レイアウトの編集については,ここでは言及しない.
クラスの追加は次のようにして行うことができる.
- [File]を選択.
- [New]を選択.
- [Class]を選択.
- クラス名を指定.
- スーパクラスをandroid.app.Activityに指定.
本稿ではクラス名にSubActivityという名前を使用する.
出来上がったソースコードには,次のようなコードを追加する必要がある.
public class SubActivity extends android.app.Activity {
@Override
protected void onCreate(android.os.Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sub)
}
}
setContentView()で指定するidには,新たに生成したレイアウトのものを使用する.
AndroidManifest.xmlへの登録もレイアウトと同様GUIで編集できる.手順は次の通りである.
- [Application]タブを選択.
- "Application Nodes"の[Add]を選択.
- "Activity"を選んで[OK]を選択.
- "Attributes for Activity"の"Name"を指定.
もちろんXMLファイルを直接書き換えても良い.なお,AndroidManifest.xmlの設定を忘れてもコンパイルは支障がなく行えるが,実行中にエラー終了する.
アクティビティから別のアクティビティを実行するには,android.content.Intentを使用する.起動するアクティビティにデータを与えない場合,startActivity()を使用すれば良い.
android.content.Intent intent = new android.content.Intent(MainActivity.this, SubActivity.class);
startActivity(intent);
また,アクティビティの終了にはfinish()を使用する.
SubActivity.this.finish();
呼び出し先のアクティビティが終了すると,呼び出し元のアクティビティに制御が戻る.
呼び出し元アクティビティのデータ渡し
呼び出し先のアクティビティにデータを渡す時,startActivity()の代わりにstartActivityForResult()を使用する.そして,データを渡すにはputExtra()を使用する.putExtraは第1引数で指定した名前を鍵として,データを呼び出し先のアクティビティに渡す.また,第2引数はさまざまな型のものがある.
android.content.Intent intent = new android.content.Intent(MainActivity.this, SubActivity.class);
int i = 10;
intent.putExtra("integer", i);
startActivityForResult(intent, 0x01);
呼び出し先アクティビティのデータ受け取り
データを受け取るにはgetIntent()でandroid.content.Intentのデータを初期化する.そして,getExtra系の関数でデータを受け取ることができる.getExtra系の関数は"get + 型名 + Extra"の名前からなる.
android.content.Intent intent = getIntent();
int i = intent.getIntExtra("integer");
i *= 2;
呼び出し先アクティビティのデータ返却(渡し)
結果を呼び出し元返すには,setResult()で結果のタイプとandroid.app.Activityのインスタンスを指定する.
intent.putExtra("integer", i);
setResult(android.app.Activity.RESULT_OK, intent);
finish();
呼び出し元アクティビティのデータ受け取り
アクティビティを制御が戻った際に,onActivityResult()が呼び出される.onActivityResult()は,第1引数で呼び出し時にstartActivityForResult()で指定したアクティビティの識別コード,第2引数で結果のタイプ(呼び出し先アクティビティがsetResult()で指定した値),第3引数でandroid.content.Intentを受け取ることができる.
@Override
protected void onActivityResult(int request_code, int
result_code, android.content.Intent sub)
{
int i;
if (request_code==0x01 && result_code==MainActivity.this.RESULT_OK){
i = sub.getIntExtra("integer");
}
}
第1引数と第2引数の値を判別した後は,呼び出し先アクティビティのデータ受け取り同様getExtra系の関数を使用する.
android.content.Intentはユーザが作成したアクティビティ以外にも別のアプリのアクティビティなどを起動できる.例えば別のアプリで画像を選択させたいような場合,次のようにアクティビティを起動する.
android.content.Intent intent = new android.content.Intent(android.content.Intent.ACTION_GET_CONTENT);
intent.setType("image/*");
startActivityForResult(intent, 0x02);
このサンプルでは,intent初期化にandroid.content.Intent.ACTION_GET_CONTENTを与えているが,他にもいろいろなタイプがある.ただし,本稿ではこれ以上言及しない.
選択した画像のパスを取得する例を以下に示す.
private String path;
@Override
protected void onActivityResult(int request_code, int result_code, android.content.Intent sub)
{
super.onActivityResult(request_code, result_code, sub);
if (request_code==0x02 & result_code==android.app.Activity.RESULT_OK){
android.content.ContentResolver cr = MainActivity.this.getContentResolver();
android.database.Cursor c = cr.query(sub.getData(), new String[]{MediaStore.Images.Media.DATA}, null, null, null);
if (c!=null){
c.moveToFirst();
path = c.getString(0);
c.close();
}
}
}
単純にパスを取得するにはgetData()とgetPathを使うだけで良い.
path = data.getData().getPath();
しかし,これによって取得できるのはURIと呼ばれるパスである.一部の関数はそれだと都合が悪いので,本稿ではそれをディレクトリ階層のパスに変更する例を紹介した.