AndroidのComponentNameクラスについて少し混乱しています。
コンポーネント名オブジェクトを取得する方法はいくつかありますが、いつどのように使用すればよいのかわかりません。なぜですか!
例:
de.zordid.sampleapp
de.zordid.sampleapp.widget.WidgetProvider
使用する
ComponentName cn = new ComponentName("de.zordid.sampleapp.widget",
"WidgetProvider");
このコンポーネント情報を取得しました:ComponentInfo{de.zordid.sampleapp.widget/WidgetProvider}
、しかしこれは使用できませんでした-コンポーネントは不明です!しかし、JavaDocは、パッケージとそのパッケージ内のクラスを与えるべきだと言っています-そしてそれは私がやったことではありませんか?
使用する
ComponentName cn = new ComponentName(context, WidgetProvider.class);
ComponentInfo{de.zordid.sampleapp/de.zordid.sampleapp.widget.WidgetProvider}
-そしてそれはうまくいきます!!
ComponentNameを取得するには、コンテキストと文字列による別の方法もあります。どこで、いつ使用するのですか?
ありがとう!
2つのComponentName
sを取るString
コンストラクターを使用して、別のアプリケーションのコンポーネントを参照できます。ただし、最初の引数はクラスのパッケージ名ではありません。これは、アプリケーションのパッケージ名、つまりそのアプリケーションのAndroidManifest.xml
のpackage
要素のmanifest
属性です。だからあなたの最初の例は
ComponentName cn = new ComponentName("de.zordid.sampleapp",
"de.zordid.sampleapp.widget.WidgetProvider");
そのコンストラクターは確かに独自のアプリケーションのコンポーネントを参照するために使用できますが、独自のアプリケーションからのContext
をすでに保持しているので、それを使用して他のコンストラクターの1つを使用することもできます。私の意見では、Class
を使用する方が、使用可能であればいつでも優先する必要があります。何らかの理由でクラスを動的に知っているだけなら、String
を取るものを使用できます。その場合は、上記の完全修飾クラス名を使用する必要があります。
または、BroadcastReceiver内で次のように使用できます。
ComponentName smsReceiver = new ComponentName(this, SMSReceiver.class);
Robert Tupelo-Schneck の答えは、文字列ではなくオブジェクトを優先することです。これが私の見方です。
独自のコンポーネントを参照するには、以下を使用します。
new ComponentName(getApplicationContext(), WidgetProvider.class);
独自のアプリで動的に参照されるコンポーネントを参照するには、次を使用します。
// values/strings.xml: <string name="provider">de.zordid.sampleapp.widget.WidgetProvider</string>
String fqcn = getResources().getString(R.string.provider);
new ComponentName(getApplicationContext(), fqcn);
これは、Androidのリソース修飾子を使用して、使用するコンポーネントを決定する場合に役立ちます。values-*/strings.xml
のデフォルトの文字列をオーバーライドできます。
別のアプリケーションのコンポーネントを参照するには、次を使用します。
int componentFlags = GET_ACTIVITIES | GET_PROVIDERS | GET_RECEIVERS | GET_SERVICES;
PackageInfo otherApp = context.getPackageManager().getPackageInfo("com.other.app", componentFlags);
ComponentInfo info = otherApp.activities[i]; // or providers/receivers/...
new ComponentName(info.packageName, info.name);
<manifest package="
について歴史的にロバートの発言は真実だったと思うので、ここで混乱が生じるかもしれません。
これはアプリケーションのパッケージ名です---そのアプリケーションのAndroidManifest.xmlのmanifest要素のpackage属性です
もうそうじゃない。新しいGradleビルドシステムが導入されてから、ここに いくつかの変更 がありました。
Android.defaultConfig.applicationId
にbuild.gradle
が指定されている場合、それがアプリパッケージ名となり、マニフェストのpackage
属性は、アプリのビルド時に別のものになります。 ComponentName
の最初の引数はapplicationId + applicationIdSuffix
を参照するようになりました。トリッキーなことは、最終的なマニフェストのマージとパッケージ化の後、APKは<manifest package=applicationId + applicationIdSuffix
を持ち、すべての.NamesがFQCNに展開されることです。
これは、私のアプリの1つの構造に基づく構造の例です。 「app」と呼ばれる架空のアプリで、次のクラスを考えます。
net.twisterrob.app.Android.App
net.twisterrob.app.Android.GlideSetup
net.twisterrob.app.Android.subpackage.SearchResultsActivity
net.twisterrob.app.Android.subpackage.Activity
net.twisterrob.app.Android.content.AppProvider
アプリのサーバー側バックエンドまたは一部の共有モデルクラス、あるいはその両方で:
net.twisterrob.app.data.*
net.twisterrob.app.backend.*
net.twisterrob.app.web.*
私のAndroidヘルパーライブラリ:
net.twisterrob.Android.activity.AboutActivity
他のライブラリ:
Android.support.v4.content.FileProvider
このようにして、すべてがnet.twisterrob.app
で名前空間になります。 Androidアプリは、独自のサブパッケージ内の全体の一部にすぎません。
AndroidManifest.xml
(無関係な部分は省略)<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
package="net.twisterrob.app.Android">
<!--
`package` above defines the base package for .Names
to simplify reading/writing the manifest.
Notice that it's different than the `applicationId` in build.gradle
and can be independently changed in case you want to refactor your packages.
This way you can still publish the same app with the same name.
-->
<!-- Will be expanded to net.twisterrob.app.Android.App in the manifest merging phase. -->
<application Android:name=".App">
<!-- meta-data needs FQCNs because the merger can't know if you want to expand them or not.
Also notice that name and value both can contain class names, depending on what you use. -->
<meta-data Android:name="net.twisterrob.app.Android.GlideSetup" Android:value="GlideModule" />
<meta-data Android:name="Android.app.default_searchable" Android:value="net.twisterrob.app.Android.subpackage.SearchResultsActivity" />
<!-- Will be expanded to net.twisterrob.app.Android.subpackage.Activity in the manifest merging phase. -->
<activity Android:name=".subpackage.Activity" />
<!-- Needs full qualification because it's not under the package defined on manifest element. -->
<activity Android:name="net.twisterrob.Android.activity.AboutActivity" />
<!-- Will be expanded to net.twisterrob.app.Android.content.AppProvider in the manifest merging phase. -->
<provider Android:name=".content.AppProvider" Android:authorities="${applicationId}" />
<!-- Needs full qualification because it's not under the package defined on manifest element. -->
<provider Android:name="Android.support.v4.content.FileProvider" Android:authorities="${applicationId}.share" />
</application>
<!-- ${applicationId} will be replaced with what's defined in `build.gradle` -->
</manifest>
build.gradle
Android {
defaultConfig {
// this is what will be used when you upload it to the Play Store
applicationId 'net.twisterrob.app'
}
buildTypes {
debug {
// The neatest trick ever!
// Released application: net.twisterrob.app
// IDE built debug application: net.twisterrob.app.debug
// This will allow you to have your installed released version
// and sideloaded debug application at the same time working independently.
// All the ContentProvider authorities within a system must have a unique name
// so using ${applicationId} as authority will result in having two different content providers.
applicationIdSuffix '.debug'
}
}
}
マージ後の最終的なマニフェストがどのようになるかを確認するには、build\intermediates\manifests\full\debug\AndroidManifest.xml
を開きます。