Роберт Тупело-Шнек правильно ответил о том, что предпочитает объекты строкам. Вот как я это вижу.
Чтобы сослаться на свои собственные компоненты, используйте:
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);
О .Names и <manifest package="
Здесь может быть некоторая путаница, потому что я думаю, что исторически утверждение Роберта было правдой:
это имя пакета приложения --- атрибут пакета элемента manifest в AndroidManifest.xml этого приложения
но не больше. С момента появления новой системы сборки Gradle здесь произошли некоторые изменения .
Если в build.gradle
указано android.defaultConfig.applicationId
, это будет имя пакета приложения, а затем атрибут package
в манифесте - это отдельная вещь при создании приложения. Первый аргумент ComponentName
теперь относится к applicationId + applicationIdSuffix
. Хитрость заключается в том, что после окончательного слияния и упаковки манифеста APK будет иметь <manifest package=applicationId + applicationIdSuffix
, и все .Names будут расширены до FQCN.
Пример приложения для обучения разрешению имен
Вот пример структуры, основанной на структуре одного из моих приложений. Рассмотрим следующие классы в гипотетическом приложении под названием «приложение»:
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
.