Intentチュートリアル

Androidでのアクティビティ間の連携

Androidではintentという形式でアクティビティ間の連携を取る。具体的には送り先とパラメータを詰めたIntentクラスを作成し、それをstartActivityメソッドで送りつける。Androidでは暗黙のintentと明示的なintentの二方式を用意しており、明示的なintentは送り先のアクティビティを指定して送信する。それに対して、暗黙的なintentはシステムに対してアクションとパラメータを送り、システムは登録されているアクティビティの中からアクションとパラメータの組み合わせを元に起動するアクティビティを決定する。まずは簡単な具体例(暗黙のintent)を見てみる。(ついでに画像ファイルの扱いも示す)

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
<!-- 画像ファイルを扱う場合はres/drawable/以下に画像ファイルxxxを配置し、@drawable/xxxで指定すれば良い。 -->
<ImageButton android:id="@+id/Button" android:src="@drawable/wallpaperrequest" android:layout_width="wrap_content" android:layout_height="wrap_content"></ImageButton>
</LinearLayout>
	

Androidの標準的なアクティビティ(マップやwebアクセス、ダイヤル、電話帳等)に対してintentを送る場合はandroid.content.Intent.以下に送り先が列挙されているのでそれを指定すれば良い。詳細についてはAndroidの公式サイトのIntentのリファレンスか、ローカルのAndroid SDKのドキュメントを読めば良い。送り先とパラメータの解説がなされている。ここでは、壁紙を設定するためのintentを送信する。

package com.suddenAngerSystem;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class Intent extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //ボタンを作成し、イベントハンドラを設定
        View button = this.findViewById(R.id.Button);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
    	//壁紙を変更するintentを作成
        android.content.Intent intent = new android.content.Intent(android.content.Intent.ACTION_SET_WALLPAPER);
        //intentを送信
        startActivity(intent);
    }
}
	

intentを受け取ってみる(明示的なintentの送受信)

ここではIntentを受け取るInnerIntentアクティビティとIntentを送信するIntentアクティビティの実例を通して、Intentの送受信を説明する。

また、ここでは複数のアクティビティを使用するが、アプリケーション中にアクティビティを追加する際にはアプリケーションのマニフェストファイル(AndroidManifest.xml)にアクティビティを登録する必要がある。(メインのアクティビティについてはeclilpseのプラグインによって自動的に登録されているため、登録する必要はない。)以下がそのマニフェストファイルになる。

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.suddenAngerSystem"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name=".Intent"
                  android:label="@string/app_name"
                  android:debuggable="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <!-- 以下を追加 android:nameにはアクティビティのクラス名を記載する。  -->
        <activity android:name=".InnerIntent">
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="3" />
</manifest>
	

送り元のソースは以下の通りとなる。明示的なintentの場合は送信元のコンテキストと送信先クラスを指定する。そしてここではputExtraを使用して追加情報の文字列を渡している。

package com.suddenAngerSystem;

import java.net.URI;

import android.app.Activity;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;

public class Intent extends Activity implements OnClickListener{
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        //ボタンを作成し、イベントハンドラを設定
        View button = this.findViewById(R.id.Button);
        button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        //内部インテントの起動
        android.content.Intent intent2 = new android.content.Intent(this, InnerIntent.class);
        final String str = "IntentクラスからInnerIntentを起動したよ!";
        intent2.putExtra("com.suddenAngerSystem.displayString", str);
        //intentを送信
        startActivity(intent2);

    }
}
	

intentを受け取る側はActivityクラスのgetIntentメソッドを使用すれば良い。また、intentに付加情報が設定されている場合はget~Extraメソッドを使えば取り出すことができる。

package com.suddenAngerSystem;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.TextView;

public class InnerIntent extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.innerintent);

        TextView text = (TextView)this.findViewById(R.id.Text);
        //インスタンス状態を記憶している場合はsavedInstanceStateからintentの値を取得可能だが、
        //そうでない場合はnullとなるため、getIntentでintentの中身を取得
        Intent intent = getIntent();
        //キーを使ってパラメータを取得
        final String var = intent.getStringExtra("com.suddenAngerSystem.displayString");
        text.setText(var);
    }

}
	

今まで説明してきたintentはintentの送信元から送信先へしか情報を送っていなかったが、ActivityクラスのstartActivityForResultメソッドを使用すれば、intentが送り先で成功したかどうかの情報を取得することができる。

ここでは明示的なintentの実装方式を説明したが、暗黙的なintentブロードキャストのintentサービスに対するintent、コンテンツプロバイダーを使用したintentについては別途説明する。また、putExtraを使ってしまうと明示的なinten以外で使用しづらくなってしまう可能性が高いため、柔軟なサービスを提供するためにはより抽象化された暗黙のintentでコンテンツプロバイダーを使用した方が良い。(ただし、それだけ複雑になるため、単純なインターフェースの場合やアプリケーション内部のインターフェースは明示的なintentの方が便利である。)

参考サイト

宿題

以下の様な機能を持つアプリケーションを作成せよ。

  1. ユーザーからのurl入力を受け付ける
  2. ユーザーがGoボタンを押すとブラウザが起動され、指定されたURLのwebサイトが表示される

以下の様なイメージ。環境によってはプロキシの設定が必要なため、外部にはアクセスできないようだ

解答例

コメントアウトしてあるので、ソースを確認すること。