読者です 読者をやめる 読者になる 読者になる

プログラマってこんなかんじ??

アプリ作ったり歌ったりしてます

Intentの作り方

android

Activity/Service起動用のIntentを作るとき、
皆どうやってるのだろう、とふと疑問。


例えば Activity#onCreate 内で
「Service(test.intent.TestService)起動用のIntent」 を作るとする。
基本的な作り方はこんなかんじになるのかな?

@Override
public void onCreate(Bundle savedInstanceState) {
    〜

    // コンストラクタのみ で作る場合
    Intent intent1 = new Intent(this, TestService.class);
    Intent intent2 = new Intent(getApplicationContext(), TestService.class);

    // コンストラクタ(引数なし)+setClassName で作る場合
    String packageName = getPackageName();
    String className = TestService.class.getCanonicalName();
    Intent intent3 = new Intent();
    intent3.setClassName(packageName, className);
}


自分の場合は intent1、2 みたいにコンストラクタ1行で済ませることが多い。
web上のサンプル見てもこのパターンが多い気がする。
通常はこれでいいはず。楽だし。




ここで出た疑問。
ApplicationContext を渡す必要があるのだろうか。




Intent のソースを確認してみたところ、
本来は ApplicationContext を引数に渡す必要などなく、
最低限必要なのはこれ↓↓だけだった。


Intent作成に必要な情報

  1. アプリケーションのパッケージ名
  2. 起動するクラス名


1は AndroidManifest.xmlタグのpackage属性指定値。
起動するクラス(TestService)のパッケージ名ではない。
2は 起動するActivity/Service等のクラス名(パッケージ名まで含む)。


引数に渡された ApplicationContext は、内部で
「アプリケーションのパッケージ名」 を取得するために使ってるだけ。


まーつまり intent1、2、3 はどれも同じなので、
作りたい作り方でおk、ということでしたw


Intent.java(抜粋)

public Intent() {
}

public Intent(Context packageContext, Class<?> cls) {
    mComponent = new ComponentName(packageContext, cls);
}

public Intent setClassName(Context packageContext, String className) {
    mComponent = new ComponentName(packageContext, className);
    return this;
}


ComponentName.java(抜粋)

public ComponentName(String pkg, String cls) {
    if (pkg == null) throw new NullPointerException("package name is null");
    if (cls == null) throw new NullPointerException("class name is null");
    mPackage = pkg;
    mClass = cls;
}

public ComponentName(Context pkg, String cls) {
    if (cls == null) throw new NullPointerException("class name is null");
    mPackage = pkg.getPackageName();
    mClass = cls;
}

public ComponentName(Context pkg, Class<?> cls) {
    mPackage = pkg.getPackageName();
    mClass = cls.getName();
}


話変わって。


intentって文字列定義みたいなもんだから、
できれば 「static final」 定義で、static初期化子 内で作っておきたいなー、
なんて自分は思ってたりする。後から編集しないようなintentは特に。


でも 「アプリケーションのパッケージ名」 は
static初期化子 内で動的に取得できない。
ということは、こんなかんじで固定値定義するしかないのか??

private static final Intent intent;
static {
    String packageName = "test.intent";
    String className = TestService.class.getCanonicalName();
    intent = new Intent();
    intent.setClassName(packageName, className);
}


うーん。微妙。