使用 Android 清单

Androidmanifest.xml 是 Android 平台上功能非常强大的文件,可便于向 Android 描述应用程序的功能和要求。 然而,使用它并不容易。 通过允许你向类添加自定义特性(这些特性然后会自动为你生成清单),Xamarin.Android 有助于最大限度地降低使用难度。 我们的目标是,99% 的用户永远都不需要手动修改 Androidmanifest.xml

Androidmanifest.xml 是在生成流程中生成,Properties/Androidmanifest.xml 中的 XML 会与通过自定义特性生成的 XML 合并在一起。 生成的合并 Androidmanifest.xml 驻留在 obj 子目录中;例如,对于调试内部版本,它驻留在 obj/Debug/android/Androidmanifest.xml 中。 合并过程很简单:它使用代码中的自定义特性来生成 XML 元素,并将这些元素插入 Androidmanifest.xml 中。

基础知识

在编译时,扫描程序集中是否有派生自 Activity 且声明了 [Activity] 特性的非 abstract 类。 然后,它使用这些类和特性来生成清单。 例如,考虑以下代码:

namespace Demo
{
    public class MyActivity : Activity
    {
    }
}

这不会在 AndroidManifest.xml 中生成任何内容。 要生成 <activity/> 元素,需要使用 [Activity] 自定义属性:

namespace Demo
{
    [Activity]
    public class MyActivity : Activity
    {
    }
}

此示例将下面的 xml 片段添加到 AndroidManifest.xml 中:

<activity android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity" />

[Activity] 特性对 abstract 类型没有任何影响;将忽略 abstract 类型。

活动名称

自 Xamarin.Android 5.1 起,活动的类型名称基于要导出的类型的程序集限定名称的 MD5SUM。 这样,可以从两个不同的程序集提供相同的完全限定名称,而不会出现打包错误。 (在低于 Xamarin.Android 5.1 的版本中,活动的默认类型名称是根据小写的命名空间和类名创建的。)

若要重写此默认值,并显式指定活动名称,请使用 Name 属性:

[Activity (Name="awesome.demo.activity")]
public class MyActivity : Activity
{
}

此示例生成下面的 xml 片段:

<activity android:name="awesome.demo.activity" />

注意

只能出于向后兼容性原因,才使用 Name 属性,因为此类重命名可能会在运行时减慢类型查找速度。 若有旧代码需要活动的默认类型名称基于小写的命名空间和类名,请参阅 Android 可调用包装器命名,以获取关于维持兼容性的提示与技巧。

活动标题栏

默认情况下,Android 会运行的应用程序提供标题栏。 本教程使用的值为 /manifest/application/activity/@android:label。 在大多数情况下,此值与类名不同。 若要在标题栏上指定应用的标签,请使用 Label 属性。 例如:

[Activity (Label="Awesome Demo App")]
public class MyActivity : Activity
{
}

此示例生成下面的 xml 片段:

<activity android:label="Awesome Demo App" 
          android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity" />

可从应用程序选择器启动

默认情况下,活动不会显示在 Android 的应用程序启动器屏幕中。 这是因为应用程序可能有很多活动,你不希望每个活动都有图标。 若要指定哪个活动应可从应用程序启动器启动,请使用 MainLauncher 属性。 例如:

[Activity (Label="Awesome Demo App", MainLauncher=true)] 
public class MyActivity : Activity
{
}

此示例生成下面的 xml 片段:

<activity android:label="Awesome Demo App" 
          android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>

活动图标

默认情况下,活动分配有系统提供的默认启动器图标。 若要使用自定义图标,请先将 .png 添加到 Resources/drawable,将它的“生成操作”设置为“AndroidResource”,然后使用 Icon 属性指定要使用的图标。 例如:

[Activity (Label="Awesome Demo App", MainLauncher=true, Icon="@drawable/myicon")] 
public class MyActivity : Activity
{
}

此示例生成下面的 xml 片段:

<activity android:icon="@drawable/myicon" android:label="Awesome Demo App" 
          android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
</activity>

权限

如果你将权限添加到 Android 清单(如向 Android 清单添加权限中所述),这些权限记录在 Properties/Androidmanifest.xml 中。 例如,如果你设置 INTERNET 权限,下面的元素会添加到 Properties/Androidmanifest.xml 中:

<uses-permission android:name="android.permission.INTERNET" />

调试内部版本会自动设置一些权限以简化调试(例如 INTERNETREAD_EXTERNAL_STORAGE)- 这些设置只在生成的 obj/Debug/android/AndroidManifest.xml 中设置,不会在“必需权限”设置中显示为“已启用”

例如,如果检查 obj/Debug/android/AndroidManifest.xml 处生成的清单文件,可能会看到以下添加的权限元素:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

在(obj/Debug/android/AndroidManifest.xml 处)清单的发布内部版本中,这些权限不会自动配置。 如果发现切换到发布内部版本导致应用丢失在调试内部版本中可用的权限,请验证是否已在应用的“必需权限”设置中显式设置此权限(在 Visual Studio for Mac 中依次转到“内部版本”>“Android 应用程序”;在 Visual Studio 中,依次转到“属性”>“Android 清单”)。

高级功能

意向操作和功能

使用 Android 清单,可以描述活动的功能。 这是通过 Intents[IntentFilter] 自定义属性完成的。 可以使用 构造函数来指定哪些操作适合你的活动,IntentFilter 构造函数,以及哪些类别适用于 Categories 属性。 至少必须提供一个活动(正因为此,活动是在构造函数中提供的)。 可以多次提供 [IntentFilter],每次使用都会在 <activity/> 中生成单独的 <intent-filter/> 元素。 例如:

[Activity (Label="Awesome Demo App", MainLauncher=true, Icon="@drawable/myicon")] 
[IntentFilter (new[]{Intent.ActionView}, 
        Categories=new[]{Intent.CategorySampleCode, "my.custom.category"})]
public class MyActivity : Activity
{
}

此示例生成下面的 xml 片段:

<activity android:icon="@drawable/myicon" android:label="Awesome Demo App" 
          android:name="md5a7a3c803e481ad8926683588c7e9031b.MainActivity">
  <intent-filter>
    <action android:name="android.intent.action.MAIN" />
    <category android:name="android.intent.category.LAUNCHER" />
  </intent-filter>
  <intent-filter>
    <action android:name="android.intent.action.VIEW" />
    <category android:name="android.intent.category.SAMPLE_CODE" />
    <category android:name="my.custom.category" />
  </intent-filter>
</activity>

Application 元素

使用 Android 清单,还可以为整个应用程序声明属性。 这是通过 <application> 元素及其对应项 Application 自定义特性完成的。 请注意,这些是应用程序范围内(程序集范围内)设置,而不是每活动设置。 通常是先为整个应用程序声明 <application> 属性,再(根据需要)每活动重写这些设置。

例如,下面的 Application 特性添加到 AssemblyInfo.cs 中,以指明应用程序是可调试的、应用程序的用户可读名称是“我的应用”,以及应用程序使用 Theme.Light 样式作为所有活动的默认主题:

[assembly: Application (Debuggable=true,   
                        Label="My App",   
                        Theme="@android:style/Theme.Light")]

此声明在 obj/Debug/android/AndroidManifest.xml 中生成下面的 XML 片段:

<application android:label="My App" 
             android:debuggable="true" 
             android:theme="@android:style/Theme.Light"
                ... />

在此示例中,应用中的所有活动都默认使用 Theme.Light 样式。 如果你将某活动的主题设置为 Theme.Dialog,只有此活动会使用 Theme.Dialog 样式,而应用中的其他所有活动则都会默认使用 <application> 元素中设置的 Theme.Light 样式。

Application 元素不是配置 <application> 特性的唯一方法。 也可以直接将特性插入 Properties/Androidmanifest.xml<application> 元素中。 这些设置合并到在 obj/Debug/android/AndroidManifest.xml 处驻留的最终 <application> 元素。 请注意,Properties/Androidmanifest.xml 的内容始终重写自定义特性提供的数据。

可以在 <application> 元素中配置的应用程序范围内特性有很多;若要详细了解这些设置,请参阅 ApplicationAttribute公共特性部分。

自定义特性列表