何时在Android中使用ComponentName的构造函数?

Zor*_*did 29 android constructor components

我对Android中的ComponentName类有点困惑.

有不同的方法来获取组件名称对象,但我不知道何时使用哪个...以及为什么!

例:

  • 申请包是 de.zordid.sampleapp
  • 但是widget提供者类是 de.zordid.sampleapp.widget.WidgetProvider

运用

ComponentName cn = new ComponentName("de.zordid.sampleapp.widget",
    "WidgetProvider");
Run Code Online (Sandbox Code Playgroud)

我得到了这个组件信息:ComponentInfo{de.zordid.sampleapp.widget/WidgetProvider},但我无法使用它 - 组件未知!但是JavaDoc说我应该给那个包中的包和类 - 这就是我做的,不是吗?

运用

ComponentName cn = new ComponentName(context, WidgetProvider.class);
Run Code Online (Sandbox Code Playgroud)

产量ComponentInfo{de.zordid.sampleapp/de.zordid.sampleapp.widget.WidgetProvider}- 而且工作正常!!

甚至还有另一种获取ComponentName的方法 - 通过上下文和字符串.应该在何时何地使用哪一个?

谢谢!

RTS*_*lio 43

ComponentName采用两个Strings 的构造函数可用于指代另一个应用程序中的组件.但是,第一个参数不是类的包名; 它是应用程序的包名称---该应用程序packagemanifest元素的属性AndroidManifest.xml.所以你的第一个例子应该是

ComponentName cn = new ComponentName("de.zordid.sampleapp",
    "de.zordid.sampleapp.widget.WidgetProvider");
Run Code Online (Sandbox Code Playgroud)

该构造函数当然可以用于引用您自己的应用程序中的组件,但由于您已经拥有了Context自己的应用程序中的一个,因此您可以使用它并使用其他构造函数之一.在我看来,Class无论什么时候可以使用a.你可以使用一个String如果你只是出于某种原因动态地知道这个类的那个; 在这种情况下,它应该采用上面的完全限定类名.

  • @Zordid,确实,您对以点开头的类名是正确的,至少在“AndroidManifest.xml”中是这样。但是,它在“ComponentName”构造函数中不起作用。 (2认同)

TWi*_*Rob 5

Robert Tupelo-Schneck的答案是正确的,而不是String。这是我的看法。

  • 要引用您自己的组件,请使用:

    new ComponentName(getApplicationContext(), WidgetProvider.class);
    
    Run Code Online (Sandbox Code Playgroud)
  • 要在您自己的应用程序中引用一些动态引用的组件,请使用:

    // values/strings.xml: <string name="provider">de.zordid.sampleapp.widget.WidgetProvider</string>
    String fqcn = getResources().getString(R.string.provider);
    new ComponentName(getApplicationContext(), fqcn);
    
    Run Code Online (Sandbox Code Playgroud)

    当您想使用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);
    
    Run Code Online (Sandbox Code Playgroud)

关于.Names和 <manifest package="

这里可能会有一些混乱,因为我认为历史上罗伯特的说法是正确的:

它是应用程序的程序包名称---该应用程序的AndroidManifest.xml中manifest元素的package属性

但没有更多了。自从引入新的Gradle构建系统以来,这里发生了一些变化

如果您在其中android.defaultConfig.applicationId指定,build.gradle则将其作为应用程序包名称,然后package在构建应用程序时清单中的属性是单独的事情。现在的第一个参数ComponentNameapplicationId + applicationIdSuffix。棘手的事情是,在最终的清单合并和打包之后,APK将具有,<manifest package=applicationId + applicationIdSuffix并且所有.Name都将扩展为FQCN。

用于学习名称解析的示例应用

这是一个基于我的应用程序结构的示例结构。在一个名为“ 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>
Run Code Online (Sandbox Code Playgroud)

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'
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在所有合并打开后检查最终清单的外观build\intermediates\manifests\full\debug\AndroidManifest.xml