情報科学屋さんを目指す人のメモ

方法・手順・解説を書き残すブログ。私と同じことを繰り返さずに済むように。

Androidアプリで最初に呼び出されるクラスを用意するまでのエラーとその対策メモ

Andoid開発 (1) Android (378) Eclipse (60) Java (38)

EclipseでとりあえずAndroidアプリを実行できるようにして、いざ空のAndroidプロジェクトを作ったところで、最初に呼び出されるクラスってどこで指定されているんだろうという疑問が湧いてきました。サンプルアプリを見ても今ひとつ分かりません。そして、検索してみても、初心者向けはサンプルを改造する記事が多く、最初からクラスを用意したりという話がなかなか見つかりませんでした。そこで、最初に呼び出されるクラスについて調べてやってみたことをメモしておきます。IDEにはEclipseを利用しています。

Activity

Androidで表示される画面のことはActivityと呼ばれ、単純なアプリは1つ以上のActivityから成り立っています。たとえば起動直後に画面を表示したい場合は、単純にはandroid.app.Activityクラスを継承したクラスを用意すればよいわけです(参考:Androidアプリ作成の基本“Activity”とは何か? (2/2) - @IT)。

起動するActivityをどこで指定しているのか

さて、アプリに関するメタデータは、AndroidManifest.xmlで指定されているらしく、この中で最初に呼び出すActivityも指定されているようだということはすぐわかりました。

実際にActivityを継承したクラスを作る

Package Explorerのsrcを右クリックして「New>Java Class...」で新しいクラスを作成します。このとき、PackageにはAndroid Projectを作成するときに指定したパッケージを、Superclassに「android.app.Activity」を指定すればいいみたいでした。

AndroidManifest.xmlにActivityを指定する

クラスを用意したら、AndroidManifest.xmlをダブルクリックして、「Applicationタブ」を選択します。タブが上部ではなく下部に表示されている点に注意。

「Applicationタブ」内の下の方に「Application Nodes」というスペースがあるので、そこの「Add...」をクリックします。

そこで、「Create a new element at the top level, in Application.」と尋ねられるので、数ある選択肢の中から「Activity」を選択して「OK」(その他の選択肢:Activity Alias, Meta Data, Provider, Receiver, Service, Uses Library)

すると、右に「Attributes for Activity」が表示されるので、「Name」の横にある「Browse...」から、先ほど作成したActivityを継承したクラスを指定します。すると、Nameにそのクラス名が入力されるはずです。

実行してみる

この中身のすっからかんなAndroidアプリの起動設定を「Run>Run Configurations...」で作成し、実際にエミュレータ上で実行してみました。すると、アプリケーション自体がエミュレータにコピーされたことにはされたようなのですが、次のようなエラーが発生してしまいました。

No Launcher activity found!
The launch will only sync the application package on the device!

つまり、最初に呼び出して欲しいクラス(Activity)が呼び出してもらえてないのです。

なぜActivityが実行されないのか

そこで、また調べてみると、「android - What does it mean "No Launcher activity found!" - Stack Overflow」が見つかりました。これによると、ただActivityをAndroidManifest.xmlに追加するだけではダメで、「intent-filter」を用意して上げる必要があるようなのです。そこには、次のようなサンプルが掲載されていました。

<application android:label="@string/app_name" android:icon="@drawable/icon">
    <activity android:name="ExampleActivity"
              android:label="@string/app_name">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

そこで、以前作成したAndroid Sample ProjectのAndroidManifest.xmlを見てみると、たしかにこちらも、そのようになっていました。そこで、この「intent-filter」を追加してみます。

ManifestにIntent Filterを追加する

またEclipseでAndroidManifest.xmlを開き、先ほど登録していたActivityをクリックした状態で「Add..」をクリックします。すると今度は「Intent Filter」と「Meta Data」しか選択肢に表示されないので、今度は「Intent Filter」を選択して「OK」をクリックします。

次に、追加された「Intent Filter」を選択した状態で、また「Add...」をクリックします。すると今度は「Action」「Category」「Data」の三つが表示されるので、「Action」を選択して「OK」をクリックします。すると、右側の「Attributes for Action」に「Name」の入力欄が表示されるので、「android.intent.action.MAIN」を選択します。

続いてもう一度「Intent Filter」を選択して「Add...」をクリックし、今度は「Category」を選択して「OK」をクリックします。そして、右の「Name」で「android.intent.category.LAUNCHER」を選択します。

これで、「Application Nodes」には、次のように表示されるはずです。

 ClassName (Activity)
    [I] Intent Filter
        [A] android.intent.action.MAIN (Action)
        [C] android.intent.category.LAUNCHER (Category)

再び実行してみる

AndroidManifest.xmlを保存して再び実行してみると、先ほどのエラーは表示されませんでした。

Starting activity net.did2memo.... on device emulator-...

まぁ、デフォルトのレイアウトが表示されるだけですが、Androidアプリのブートストラップ周りがすこし理解できた気になりました。

まとめ

つまり、次のようにまとめることができます。

  • 最初に呼び出されるクラスはAndroidManifest.xmlで指定する。
  • 画面を表示するアプリの場合は、最初に呼び出されるクラスは「Activity」を継承したものになる。
  • その「Activity」は、「Application Nodes」で登録するだけでなく、「Intent Filter」として「android.intent.action.MAIN」と「android.intent.category.LAUNCHER」を指定して初めて、自動的に呼び出されるようになる

こんなところでしょうか。Activityを使わないアプリケーションの場合はまだよく分かりませんが、似たような作法になるのではないかと思っています。

感想

簡単に参照できるサンプルアプリの存在の重要性を実感させられました。

コメント(1)

  1. sasa
    2014年3月1日(土) 12:06

    本やチュートリアルサイトでプロジェクトの作成時よく
    『「Create activity」にチェックを入れる』
    とあるのですが、入れなかったらどうなるだろうという
    好奇心の結果ここにたどり着きました。
    投稿されてから2年半経った今でも同じエラーメッセージだったので問題なく解決しました!
    ありがとうございます。

新しいコメントを投稿