#navi_header|技術| ドキュメントが曖昧で間違えやすい箇所のメモ。 #more|| #outline|| ---- * AndroidManifest.xml関連 ** の"android:name"属性 例: | の"package"属性 | foo.bar | | ActivityクラスのFQCN(Fully Qualified Class Name) | foo.bar.activities.ActivityX | この時、の"android:name"属性でActivityXを指定したい時の正誤パターン。 正: 誤: 説明: "android:name"属性は、"."から始める場合はpackage部分を省略した表記として解釈される。 従ってpackageが"foo.bar"なら、"foo.bar.activities.ActivityX"からpackageを除去した".activities.ActivityX"を指定する。 それ以外は全て間違って解釈される。 Activityのクラスがpackageの直下にあるのなら、".クラス名"にすればよい。 例: "foo.bar.Main" → 間違えやすい背景: Androidの公式ドキュメントに出てくる"package名"の殆どは AndroidManifest.xml の""の"package"属性で指定した値を指している。 ''Javaのクラス名で扱う"package"で考えると、ズレが生じて間違える元になる。'' 例えばActivityに指定したいクラスが"foo.bar.baz.Main"とすれば、Javaの世界での"package"は"foo.bar.baz"となる。しかしのpackage属性で"foo.bar"が指定されていれば、Androidアプリの世界での"package名"は"foo.bar"となる。 公式ドキュメント上での説明: - | Android Developers -- http://developer.android.com/guide/topics/manifest/activity-element.html#nm ** の"android:name"属性 この場合、""の"android:name"属性もpackageで始める。 正: 誤: 説明: 公式ドキュメントには >The name must be unique, so it ''should'' use Java-style scoping とあり、MUSTとは書かれていない。このため、タイピング数を少なくしようとpackage名を省略すると、SecurityExceptionの発生に頭を悩ませることになる。 将来的に実装がどう変わるのか不明なので、本記事で"MUST"と断言することは出来ない。ただし、実際にトラブルが発生したことは確かなので、package名で始めることを推奨しておく。 - | Android Developers -- http://developer.android.com/guide/topics/manifest/permission-element.html#nm - | Android Developers -- http://developer.android.com/guide/topics/manifest/uses-permission-element.html#nm * 明示的Intentでのパッケージ名、クラス名 URIではなく、直接パッケージ名とクラス名を指定してIntentを使いたい場合: Intent i = new Intent(); i.setClassName(String packageName, String className) 例:package="foo.bar" アプリの、FQCN="foo.bar.activities.Main"を指定する。 正: i.setClassName("foo.bar", "foo.bar.activities.Main"); 誤: i.setClassName("foo.bar", ".activities.Main"); i.setClassName("foo.bar.activities", ".Main"); i.setClassName("foo.bar.activities", "Main"); 説明: IntentのsetClassName(String packageName, String className)は public ComponentName (String pkg, String cls) のショートカットとなっている。ここで"packageName", "pkg"は当然の"package"属性を指定する。ここをJavaクラスのパッケージと勘違いしたのが、 i.setClassName("foo.bar.activities", ".Main"); i.setClassName("foo.bar.activities", "Main"); と指定したパターン。 問題は"className", "cls"の部分で、公式ドキュメントにも >cls The name of the class inside of pkg that implements the component. Can not be null. としか書かれておらず、FQCNを指定すればよいのかが曖昧なままになっている。 ここでの"android:name"属性と同様と勘違いしてしまうパターンが次のケース。 i.setClassName("foo.bar", ".activities.Main"); 結論から言うとFQCNを指定する必要がある。 ヒントとなるのが public ComponentName (Context pkg, Class cls) というコンストラクタの存在であり、"Class"のgetName()メソッドはFQCN表記を返す。このことから、Stringで指定する場合もFQCNとなることが予想できる。 - Intent | Android Developers -- http://developer.android.com/reference/android/content/Intent.html#setClassName(java.lang.String, java.lang.String) - ComponentName | Android Developers -- http://developer.android.com/reference/android/content/ComponentName.html #navi_footer|技術|