Androidアプリの4大要素とインテント 明示的なIntent

この記事は2013年4月15日に書かれたものです。内容が古い可能性がありますのでご注意ください。


1
Androidアプリの4大要素とインテント
インテント(明示的なIntent)
Intent(インテント)は各コンポーネント間を紐付けるための仕組みです。コンポーネント間(たとえば画面間)でデータの受け渡しをするためのものと言ったほうがわかりやすいかもしれません。Intentは”明示的なIntent”と”暗黙的なIntent”に分類することができ、この節では”Intentの概要”、および”明示的なIntent”を紹介します。
Intent概要
IntentはAndroidアプリケーションの様々な場面で利用され、各コンポーネントを紐付けるための仕組みのことです。
画面間(あるActivityとまた別のActivity)やアプリ間(あるアプリのActivityと他のアプリのActivity)、ActivityだけではなくActivityとサービス間などでも用いられ、それらの間でデータの受け渡しなどを担います。
他のアプリケーションやサービスとデータのやりとりするためには、通常はソケットやパイプ、共有メモリ等のプロセス間通信の仕組みを使わなければなりませんが、Intentはこのようなプロセス間通信の仕組みの1つとしてAndroidによって提供されています。

 

Intentが使用される最も代表的なケースは同一アプリ間のActivity移動、すなわち画面遷移です。


この例では一覧表示用Activity(一覧Activity)と詳細表示用Activity(詳細Activity)があり、一覧ActivityでItemをクリックすると詳細Activityに画面遷移します。一覧ActivityからIntentが飛び、詳細Activityが受け取るイメージです。
詳細Activityでは、どのItemを表示するのかを知らないと表示することができません。ですので、IntentにはどのItemを表示するか分かるような情報、一般的にはIDのような一意なデータ(重複する値がないデータ)が含まれているわけです。
このような同一アプリ間のActivity移動に用いられるIntentは”明示的なIntent”を呼ばれています。

 

他に以下のようなケースでもIntentは使用されます。一般的に1,2が明示的なIntentとなり、3,4は暗黙的なIntentと呼ばれています。
暗黙的なIntentに関しては別節で詳しく紹介します。

  1. MainActivityに画面遷移したい
  2. ID=50のデータを削除したい
  3. 03-1234-5678へ電話をかけたい
  4. 新宿の地図を表示したい

Intentクラス(明示的なIntent)
インテントはIntentクラスを用います。Intentクラスには4つのコンストラクタがありますが、明示的なIntentで使用するコンストラクタは1つだけです。

コンストラクタ 概要
Intent(Context packageContext, Class cls) 宛先クラスを明示的に指定してインテントを作成する
 

第1引数のContextクラスはAndroidアプリの環境情報をAndroid全体で受け渡しするためのインタフェースです。Contextクラスを通してアプリケーションのリソースファイルへのアクセスや、アプリケーションレベルのオペレーション(アクティビティの起動、ブロードキャスト、インテントの受信など)を行うことができます。
Androidアプリでは様々な場面でこのContextオブジェクトを使用する必要がありますが、ActivityはContextクラスを継承しているため、Activity≒Contextとして利用することができます。
つまり、Activityクラス上でIntentクラスをインスタンス化する場合は、thisを指定すれば良いことになります。

 

明示的なIntentでは、Intentは指定した相手にしか送られず、指定した宛先以外のオブジェクトがそのインテントに反応することはありません。以下のように使用します。

Intent intent = new Intent(this, MainActivity.class);
 

IntentにIDなどの付加情報を追加するには以下のメソッドを用います。

戻り値 メソッド 処理内容
Intent putExtra(String name, boolean value) インテントに付加情報を追加する
Intent putExtra(String name, int value) インテントに付加情報を追加する
Intent putExtra(String name, long value) インテントに付加情報を追加する
Intent putExtra(String name, String value) インテントに付加情報を追加する
Intent putExtra(String name, Bundle value) インテントに付加情報を追加する
 

putExtra()メソッドはここで紹介した5つ以外にも異なる引数のメソッドが多数定義されています。詳しくは公式HPを参照下さい。
http://developer.android.com/reference/android/content/Intent.html

 

Intentを受け取ったActivityでは、Activityクラスに定義されているgetIntent()メソッドを使用することで受け取ったIntentオブジェクトを取得することができます。
そのIntentから付加情報を取り出すにはIntentクラスに定義されているgetXXXExtra()メソッドを使用します。(XXXには対応するデータ型が入ります。)
以下のメソッドはその一部です。

戻り値 メソッド 処理内容
boolean getBooleanExtra(String name, boolean defaultValue) インテントからbooleanの付加情報を取り出す
int getIntExtra(String name, int defaultValue) インテントからintの付加情報を取り出す
long getLongExtra(String name, long defaultValue) インテントからlongの付加情報を取り出す
String getStringExtra(String name) インテントからStringの付加情報を取り出す
Bundle getBundleExtra (String name) インテントからBundleの付加情報を取り出す
 

getXXXExtra()メソッドも異なる引数のメソッドが多数定義されています。詳しくは上記の公式HPを参照下さい。

 

では、実際の使用例を見てみましょう。
まずは画面遷移元のActivityです。

Intent intent = new Intent(this, MainActivity.class);
intent.putExtra("COUNT", 100);
startActivity(intent);

Intentオブジェクトを作成した後、付加情報としてint型の整数”100”を設定しています。
putExtra()メソッドの第1引数にはキーとなる文字列を指定します。値を取り出すときに、ここで指定したキーでどの値を取り出すかを識別します。
startActivity()メソッドの引数に作成したIntentを渡すことで、MainActivityが起動し画面遷移します。

 

次に画面遷移先のActivityです。

Intent intent = getIntent();
int i = intent.getIntExtra("COUNT", 0);

getIntent()メソッドで受け取ったIntentを取り出し、getIntExtra()メソッドで付加されているintデータを取り出しました。
第1引数には付加情報を設定したときに指定したキー文字列を、第2引数には値が付加されていない場合のデフォルト値を指定します。
第1引数は必須ですが、メソッドによっては第2引数が省略されているものもあります。

 

この例の場合は、name=“COUNT”として付加(IntentにputExtra())されていたintの付加情報を取り出しています。もし値が付加されていなかった場合は、デフォルト値の0を取得することになります。

 

また、独自クラスのオブジェクトをIntentを使って受け渡しすることも可能です。その際は以下の点に留意しましょう。

  • putExtra()の引数に渡すオブジェクトを指定する
  • 独自クラスにはSerializableインタフェースを実装する
  • Intentを受け取る側はgetSerializableExtra()を使用する。

明示的なインテントを利用したBMI計算アプリ
簡単なBMI計算アプリを作ってみましょう。

まずは、MainActivityからです。
”res/layout/activity_main.xml”

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="身長(cm)" />
 
    <EditText
        android:id="@+id/editText1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
 
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="体重(kg)" />
 
    <EditText
        android:id="@+id/editText2"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
 
    <Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="明示的インテント" />
</LinearLayout>

LinearLayoutの子要素として、5つのViewが定義されています。ラベルである”TextView”を2つ、入力フィールドである”EditText”を2つ、”Button”を1つです。
EditTextは入力した値をJavaプログラム側から参照する必要があるので、”android:id”を設定しています。

 

”src/com.example.intent/MainActivity.java”

package com.example.intent;
// 中略
public class MainActivity extends Activity {
    private EditText textHeight;
    private EditText textWeight;
 
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        textHeight = (EditText)findViewById(R.id.editText1);
        textWeight = (EditText)findViewById(R.id.editText2);
 
        Button button1 = (Button)findViewById(R.id.button1);
        button1.setOnClickListener(new OnClickListener() {
 
            public void onClick(View v) {
                Intent intent = new Intent(MainActivity.this, ResultActivity.class);
 
                intent.putExtra("HEIGHT", Integer.parseInt(textHeight.getText().toString()));
                intent.putExtra("WEIGHT", Integer.parseInt(textWeight.getText().toString()));
 
                startActivity(intent);
            }
        });
 
    }
}

ButtonをクリックするとResultActivityに画面遷移するアプリですので、Buttonオブジェクトにリスナーを設定します。クリックした時の処理はOnClickListenerインタフェースのonClick()メソッド内に記述しました。匿名クラスを使っていますね。
Buttonがクリックされたときの処理は18から23行目となります。Intentを作成、付加情報の設定、startActivity()メソッドの呼び出しを順に行なっています。
付加情報にはEditTextに入力されている身長と体重を、それぞれname=”HEIGHT”とname=”WEIGHT”として設定しています。このnameは取り出すときに値の識別に利用します。

 

次は、ResultActivityです。”res/layout/”フォルダ以下に新しくXMLファイルを作成します。
”res/layout/activity_result.xml”

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <TextView
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="あなたのBMIは" />
 
    <TextView
        android:id="@+id/textView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" />
 
</LinearLayout>

ResultActivityの画面レイアウトは単純です。LinearLayoutの子要素には2つのTextViewが定義されているだけです。
1つ目のTextViewは単に”あなたのBMIは”と表示しているだけなので”android:id”は設定されていませんが、2つ目のTextViewには”android:id”が設定されています。これはBMIの計算結果を表示するためにJavaプログラムから参照する必要があるためです。

 

”src/com.example.intent/ResultActivity.java”

package com.example.intent;
// 中略
public class ResultActivity extends Activity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.result);
        Intent intent = getIntent();
 
        int height = intent.getIntExtra("HEIGHT", 0);
        int weight = intent.getIntExtra("WEIGHT", 0);
        int bmi = 10000 * weight / height / height;
 
        TextView textView = (TextView)findViewById(R.id.textView1);
        textView.setText(String.valueOf(bmi));
    }
}

9行目でIntentの取り出しを行なっています。
11行目、12行目でそのIntentから付加情報の取り出しを行い、13行目でBMIの計算を行なっています。
ここでは、MainActivityで付加情報を設定した時のnameと同じ値(”HEIGHT”、”WEIGHT”)をgetIntExtra()メソッドの第1引数に設定しているところがポイントです。
あとは、15から16行目で計算結果をTextViewに表示させています。

 

最後にマニフェストファイルです。
新しいActivity(ResultActivity)を追加しているため、マニフェストファイルへの追記が必要となります。
”AndroidManifest.xml”

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.intent"
    android:versionCode="1"
    android:versionName="1.0" >
 
    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="15" />
 
    <application
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/title_activity_main" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
 
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".ResultActivity"></activity>
    </application>
 
</manifest>

追加しているのは、23行目のみです。
注意すべき点は、”ResultActivity”の前に”.”(ピリオド)です。本来、”android:name”属性には完全修飾クラス名を記述しなくてはいけないのですが、そのActivityが2行目で定義しているパッケージと同一パッケージに所属する場合は、”.”(ピリオド)で省略することができるというルールになっています。
ですので、23行目を下記のように記述しても問題ありません。

<activity android:name="com.example.intent.ResultActivity">

  • このエントリーをはてなブックマークに追加

PAGE TOP