【Android】インテントが反応しない?暗黙的インテントを使う場合の注意点【Intent】

header16

まず初めに

みなさん、こんにちは。はねすけと申します。

今回はAndroidアプリを開発する上での注意事項についてご紹介したいと思います。
テーマは「暗黙的インテントの注意点」です!

Androidアプリでは画面遷移の際に「インテント」という要素を使用するということは、Androidアプリ開発エンジニアの皆さんなら周知の事実かと思います。
そんなインテントを使用する上で自分自身がハマった箇所があったので、備忘もかねて記事にしておきたいと思います。
それでは早速行ってみましょう!

こんな方はぜひ読んでみてくださいね

・Androidアプリの開発を行う予定・現在行っている方

・Androidアプリ開発において、画面遷移の設定方法で悩んでいる方

基本情報振り返り

header16-1

Android Studio

本題に入る前に関連した情報を少し整理しておきましょう。
ここで確認しておきたいのは「Android Studio」についてです。
Android Studioとは、Googleが提供するIDE(統合開発環境)のことを指しています。簡単に言うと、Androidのスマホアプリなどを開発するためのソフトウェアです。
おそらくAndroidアプリを開発する際には最適なIDEではないでしょうか。(iOSのアプリ開発には使用できませんので、その際には別のIDEを使用しましょう) ともかく今回の開発についてもAndrod Studioを使用して進めております。

以下の記事でAndrod Studioのインストール・起動に関してご紹介しておりますので、まだ使ったことがないという方はぜひ参考にして使ってみてください。

header13【開発】Androidアプリでボタンの色を動的に変更するには?実例も交えてわかりやすく解説します【button】

インテント

次にインテント(Intent)について確認しておきましょう。一般的にはインテント=意図という意味の言葉なのですが、プログラミング的には2つ、①明示的インテント・②暗黙的インテントという2つの意味で使用されます。

遷移先の画面が決まっていて宣言時に遷移するActivityを指定しているインテント明示的インテントと言います。

それに対して表示したいデータと行いたいアクションを指定することで、システム側で合致するActivityを探す仕組みのインテントを「暗黙的インテント」といいます。

明示的インテントについては遷移先が決まっているため、ボタンを押してどこか別の画面に遷移したりするんだなとわかりやすいですね。では暗黙的インテントとはどういった際に使用し、何のために存在するのでしょうか。

イメージしやすいように例を見てみましょう。

intent_sample1

上画像は私が開発したゲームアプリのとある画面です(笑)
非常にシンプルな構成なのですが、赤枠のように4つ並んでいる画像ボタンの中から1つを選ぶという画面です。

intent_sample2

また同様に、画面下部にはメニュー要素としてTOP・HINT・NEXTというボタンが並んでいますね。これらはもちろん画面の遷移先は異なるのですが、押したボタンに対応したページに遷移するというほぼ共通の対応を行います。
明示的インテントを使用してそれぞれ別々に実装することももちろんできるのですが、その場合ソースコードはどうなるでしょうか。似たような役割をもつ、遷移先というごく一部の情報しか違わないソースが複数並ぶことになってしまいます。

プログラミングを行う上での考慮事項として「コードの共通化」というものがあります。簡単に言うと、コードでまとめて記載できるような内容はまとめて書きましょうね、ということです。
まとめて記載することで、以下のようなメリットを享受することができます。

保守性の向上…コードを共通化することで、変更や修正が発生した場合でも、それを一か所で行えます。共通のコードベースを修正すれば、複数の箇所で同じ変更を行う必要がなくなり、バグの修正や新機能の追加が容易になります。

開発効率の向上…一度書かれたコードを再利用することで、同じ機能やロジックを再実装する手間が省けます。これにより、開発者はより迅速にプロジェクトを進めることができ、開発サイクルが短縮されます。

一貫性の確保…共通のコードベースを使用することで、同じ機能やロジックがプロジェクト内で一貫して適用されます。これにより、予測可能で統一感のあるソフトウェアを維持しやすくなります。

品質の向上…共通化されたコードは再利用が前提となっており、その品質が向上していることが期待されます。一度修正されたバグは共通のコードに反映され、他の部分でも同じ問題が発生しにくくなります。

リファクタリングの容易性…コード共通化を行うことで、コードのリファクタリングがしやすくなります。共通の部分を改善すれば、それがプロジェクト全体に影響を与えるため、システム全体を改良しやすくなります。

コスト削減…共通のコードを再利用することで、新しい機能を実装する際に必要な開発時間が短縮されます。これにより、開発プロセス全体の効率が向上し、開発コストを削減できます。

コードの共通化を行うと非常にたくさんのメリットがあることがお判りいただけたと思います。
インテントに関してコードの共通化を実現するために使用するのが暗黙的インテントということなのです。

公式資料通りに動作しない?

header16-2

まずは基本の整理から

インテントがどういうものなのかは前章にて確認してきましたので、ここからは実際のコーディング目線でのお話に入っていきます。
暗黙的インテントをプログラミングで実現すると以下のようになります。

Java
public void openWebsite(View view) {
   //文字列を取得し、Uriオブジェクトにエンコード
   String url = mWebsiteEditText.getText().toString();
   Uri webpage  Uri.parse(url);

   //暗黙的インテントの宣言
   //特定のクラスを指定して送信するのではなく、アクションとアクションデータを指定
   Intent intent = new Intent(Intent.ACTION_VIEW, webpage);

   //resoleActivity()メソッドとAndroidパッケージマネージャを使用して暗黙的インテントを処理できるActivityを見つける
   if (intent.resolveActivity(getPackageManager()) != null) {
       startActivity(intent);
   } else {
       //該当するActivityが見つからなかった場合の処理
       Log.d("ImplicitIntents", "Can't handle this!");
   }
}

簡単に言うと上部分ではインテントの要素として、画面で入力された値(URL)からアクションデータを指定し、加えて画面に表示するために「Intent.ACTION_VIEW」というアクションを指定しています。
そして下部分でそれに合致するActivityが存在するかを探し、見つかれば処理を実行し、見つからなければログにそれを出力する、と言った具合です。

コード共通化の観点からも、パラメータからのアクションデータさえ受け取ってしまえば様々な画面への遷移に使用できるため、非常に効率的なコードとなっていますね。

これはGoogleが提供する開発資料にも載っていた基礎的な内容なのですが、私の環境でこれを実行しても一向に正常に指定したURLのWebページが表示されることはありませんでした。

原因はいったい何なのでしょうか?

バージョン差異を放置しない!

header16-3

原因はいつも細かいところに

結論から言いますと、原因は「targetSdkVersion」の設定にありました。

具体的にはtargetSdkVersionが29以下までは上記の記載だけで問題なく暗黙的インテントが動作するのですが、targetSdkVersionが30以上つまりAndroid 11.0以上の場合はうまく動作しないとの仕様になっています。

私が開発で使用しているエミュレータのtargetSdkVersionは30以上となっていたために動作していなかったのです。

対処方法

ではどうすれば良いかと言いますと、targetSdkVersionが30以上の場合には下の画像のように、「AndroidManifest.xml」に記載を追加する必要があります。

使用したいインテントアクションの分だけそれぞれ追加する必要があるのでご注意ください。
今回でいうと「Intent.ACTION_VIEW」というアクションを使用するために、「intent」タグの中の「action」タグの名前として「android.intent.action.VIEW」を設定しています。念のため、コードとしても下記に記載しておきますので、ご自由にお使いください。

<strong>AndroidManifest.xml</strong>
<queries>
    <intent>
        <acton android:name="android.intent.action.VIEW" />
        <data android:mineType="*/*" />
    </intent>
    <intent>
        <acton android:name="android.intent.action.CREATE_DOCUMET" />
        <data android:mineType="*/*" />
    </intent>
    <intent>
        <acton android:name="android.intent.action.OPEN_DOCUMENT" />
        <data android:mineType="*/*" />
    </intent>
</queries>

このように開発する上では環境のバージョン違いだけでも、参考資料と同じような動作をしないケースも多々あります。
もし開発する上で想定と異なるような動作をする場合には、要因としてバージョンごとの仕様差異についても考えるようにしてみてください!

まとめ

いかがだったでしょうか?

本日お伝えしたかった内容を簡単にまとめると以下のようになります。

ぜひ何らかの形でお役に立てれば幸いです。

それでは次の記事でまたお会いしましょう♪

本日のまとめ

・暗黙的インテントを活用することで共通化された有益なコードを作成できます。

・細かい違いを放置しない!原因はいつも細かい要素に眠っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です