在 Windows 计算机上设置 Android 游戏开发扩展并在 Android 设备或模拟器上运行示例 Visual Studio C++ 项目。
先决条件
按照本节中的步骤准备您的 Windows 计算机以安装扩展程序:
-
下载并安装 Visual Studio 的受支持版本之一:
-
Android Studio 3.5 或更高版本是可选的,但可以代替 Android 游戏开发扩展来安装 Android SDK 和 NDK。
安装扩展
按照本节中的步骤下载并安装 Android 游戏开发扩展:
-
关闭 Visual Studio 的所有实例。
-
从下载页面下载最新的扩展安装程序和示例 。
-
从您的下载位置,双击安装程序。安装程序需要几分钟才能完成。
-
如果您安装了多个版本的 Visual Studio,请选择您希望为其安装扩展的版本。
-
单击完成以完成安装。
安装 Android SDK 和 NDK
您可以使用 Android Studio 或 Android Game Development Extension安装 Android SDK 和 Android Native Development Kit (NDK) 。要从扩展安装 SDK 和 NDK,请使用SDK 管理器,它位于 Visual Studio 的扩展工具栏中。
安装 NDK 时,请确保使用NDK(并排)复选框,以便扩展程序可以找到它。您必须安装扩展支持的 NDK 版本(请参阅NDK 修订历史记录)。
要将 SDK 安装到与默认位置不同的位置, ANDROID_SDK_ROOT
请在您的计算机上设置环境变量:
- 确保 Visual Studio 已关闭。
- 在 Windows 搜索中,搜索
Environment Variables
. - 选择编辑系统环境变量。
- 单击环境变量。
- 在用户变量下,单击新建。
- 在“变量名称”框中,键入
ANDROID_SDK_ROOT
。 - 在变量值框中,输入 Android SDK 的路径。
- 重新启动计算机。
无法使用 SDK 管理器窗口修改 SDK 的位置,因为此环境变量是 SDK 位置的唯一真实来源。
运行示例
按照本节中的步骤在模拟器中运行 Teapot 示例,然后在物理 Android 设备上运行。
配置平台
图 1. Android 平台属性 图 2. Android 打包属性
-
如果 Visual Studio 尚未运行,请启动它。
-
将示例 zip 文件解压缩到您选择的目录中。包括以下示例:
- 茶壶
- 无尽的隧道
- 你好JNI
-
打开示例目录。选择文件 > 打开 > 项目/解决方案并导航到
Teapot.sln
. -
选择安卓平台:
- 选择构建 > 配置管理器。
- 在Active solution platform下,选择Android x86。
示例中已经配置了两个 Android 平台(您可以稍后添加更多 Android 平台)。
注意:典型的模拟器映像使用 x86 或 x86_64 ABI。
-
确保示例项目配置了 Android SDK 和 NDK 属性:
-
在解决方案资源管理器中,右键单击GameApplication并选择 Properties。
-
选择常规属性选项卡并找到适用于 Android 的平台 属性。
-
-
-
选择Android 打包属性选项卡。
您可以从此选项卡更改输出 APK 名称和目录。请注意,一些 Android 配置属性在属性页中定义并传递给 Gradle。例如,APK 名称属性
MSBUILD_ANDROID_OUTPUT_APK_NAME
将此名称传递给应用程序build.gradle
文件。
设置模拟器
-
从 Visual Studio 的扩展工具栏中启动 AVD Manager。配置一个虚拟设备,然后 在 Android Studio 模拟器中运行它。
注意:当 Android Studio 打开时,使用 Visual Studio 进行调试会中断。
- 在 Android 虚拟设备管理器中,单击创建虚拟设备。
- 选择一个设备定义(例如,Pixel 2)。
- 选择系统映像。您应该选择 x86 ABI,因为此架构在模拟器中执行得更快。
- 验证配置并单击完成。
-
通过单击Android 虚拟设备管理器中的运行按钮来启动虚拟设备。
-
在 Visual Studio 中,虚拟设备类型应显示在“开始调试”工具栏按钮旁边 。单击Start Debugging在设备上启动 Teapot 示例应用程序。调试器可能需要一些时间才能附加到应用程序。您可以通过在茶壶上拖动光标来旋转茶壶。
设置设备
-
要在物理 Android 设备上运行示例,您可能需要在项目中创建一个新的 Android 平台。该平台必须与设备的架构相匹配。要创建新平台,请在 Visual Studio 中执行以下操作:
- 选择构建 > 配置管理器。
- 在Active solution platform下,选择<New>。
-
为新平台键入以下内容之一:
- 安卓 armeabi-v7a
- 安卓 arm64-v8a
- 安卓 x86
- 安卓 x86_64
-
在Copy settings from框中,选择None。
-
使用 USB 数据线将 Android 设备连接到您的计算机。设备类型应显示在 Start Debugging工具栏按钮旁边。
如果未显示设备类型,请检查以下内容:
- 设备上启用了开发人员选项和 USB 调试。
- USB 电缆从设备连接到计算机。
- USB 电缆支持数据连接(而不仅仅是电源)。
- Android 调试桥 (adb) 正在运行。adb 与 Android Studio 一起安装。
- 平台选择与您设备的 ABI 相匹配。
-
单击开始调试工具栏按钮以在设备上启动示例茶壶应用程序。调试器可能需要一些时间才能附加到应用程序。连接后,您可以通过在茶壶上拖动手指来旋转茶壶。
常问问题
以下是有关 Android 游戏开发扩展的一些常见问题。
插件的日志在哪里?
您可以使用Android 游戏开发扩展工具栏中的打开日志图标 打开插件的日志文件。
为什么插件在错误的位置查找 adb?
该插件使用以下逻辑查找 SDK 的位置:
<span style="color:var(--devsite-code-color)"><code><span style="color:var(--devsite-code-keywords-color)">public</span> <span style="color:var(--devsite-code-keywords-color)">static</span> <span style="color:var(--devsite-code-keywords-color)">string</span> <span style="color:var(--devsite-code-types-color)">GetAndroidSdk</span>() =>
<span style="color:var(--devsite-code-types-color)">Environment</span>.<span style="color:var(--devsite-code-types-color)">GetEnvironmentVariable</span>(<span style="color:var(--devsite-code-strings-color)">"ANDROID_SDK_ROOT"</span>) ??
<span style="color:var(--devsite-code-types-color)">Environment</span>.<span style="color:var(--devsite-code-types-color)">GetEnvironmentVariable</span>(<span style="color:var(--devsite-code-strings-color)">"LocalAppData"</span>).<span style="color:var(--devsite-code-types-color)">Resolve</span>(@<span style="color:var(--devsite-code-strings-color)">"Android\Sdk"</span>);
</code></span>
插件使用什么环境变量?
该插件使用以下环境变量:
ANDROID_SDK_ROOT
ANDROID_SDK_HOME
TEMP
GOOGLE_ANDROID_LOG_DIR
下一步是什么
要将您自己的项目与扩展一起使用,您必须根据项目配置指南进行配置。
配置项目
配置项目以使用 Android 游戏开发扩展。
Android 游戏开发扩展调用 MSBuild 将 C/C++ 源代码构建到共享库 ( .so
) 和静态库 ( .a
) 中。作为构建过程的一部分,自定义 MSBuild 任务调用 Gradle 来编译 Java 和 Kotlin 源代码、打包资产并生成用于部署的 APK 文件。配置项目时,必须确保 MSBuild 具有为 Android 平台构建所需的信息。
使用 MSBuild构建 C / C++
一个典型的 Android 项目是使用 Gradle 构建的,其中项目内的本机代码由运行CMake或 ndk-build的 Gradle pass 构建。使用 Visual Studio 的 Android 游戏开发扩展,构建过程是相反的。现在 MSBuild 是构建过程的起点。所有 C/C++ 源代码均由 MSBuild 首先构建,用于作为扩展的一部分安装在您的系统上的新 Android 平台(例如,“Android x86_64”)。MSBuild 然后调用 Gradle 将包含 C/C++ 逻辑的共享库文件打包到 APK 中。
您应该首先在 CMake 中复制项目的现有构建逻辑,或者在 MSBuild 中复制 ndk-build。将目标平台设置为以下内容:
- 安卓 x86
- 安卓 x86_64
- 安卓 armeabi-v7a
- 安卓 arm64-v8a
这些平台都是由 Android Game Development Extension 提供的。
添加安卓平台
虽然茶壶示例项目包含 Android 平台,但您必须手动将 Android 平台添加到现有项目中。要添加新平台,请在 Visual Studio 中执行以下操作:
- 选择构建 > 配置管理器。
- 在Active solution platform下,选择<New>。
-
为新平台键入以下内容之一:
- 安卓 armeabi-v7a
- 安卓 arm64-v8a
- 安卓 x86
- 安卓 x86_64
-
在Copy settings from框中,选择None。确保您启用 了创建新项目平台。
添加 Android APK 项
选择Add > New Item > Visual C++ > Android > Android APK并单击 Add。在以下对话框中配置 Android 应用程序。
- 应用程序名称:Android 应用程序的可读名称。
- 应用程序 ID:您的 Android 应用程序的唯一标识符 。
- 解决方案资源管理器位置:包含添加的 Android 打包支持文件的虚拟文件夹的位置。默认情况下,这些文件也位于项目中的同名文件夹中。您可以通过选中将支持文件放入自定义位置 复选框并指定自定义位置来自定义位置。虚拟文件夹仍将位于解决方案资源管理器中的当前项目下。
让 MSBuild 调用 Gradle 来构建 APK
MSBuild 无法调用 Gradle,除非它知道 Gradle 项目的位置。使用Gradle Build Directory属性设置此位置,如图 1 所示。
此外,设置Application Module、Application Variant和APK Name属性(如上图所示),以便 MSBuild 知道要构建什么。
- 应用程序模块:Gradle 子项目的名称。这是
settings.gradle
文件中设置的主要项目。它通常app
用于直接使用 Android Studio 创建的项目。 - 应用程序变体:要构建的 Android 变体。此值应根据 MSBuild 配置进行设置。例如,调试版本应将值设置为调试变体。如果您的项目的 MSBuild 配置名称与 Gradle 变体名称匹配,则只需使用默认值
$(Configuration)
. - APK Name:生成的 APK 文件的名称,用于在您的开发计算机上进行调试和分析。此名称将传递给 Gradle,您的 Gradle 构建脚本应遵守此名称(请参阅
MSBUILD_ANDROID_OUTPUT_APK_NAME
下一节中的属性)。
修改 Gradle 构建脚本
在构建期间,MSBuild 将以下信息作为项目属性传递给 Gradle 脚本。更改项目的现有构建脚本(通常命名为build.gradle
)以读取这些属性。
-
MSBUILD_MIN_SDK_VERSION
:构建 APK 的最低 SDK 版本。在图 2 所示的项目属性页面上的最低 Android SDK 版本框中设置此值。Gradle 构建脚本应设置
minSdkVersion
为此值,如下所示。android { // ... defaultConfig { applicationId "com.yourcompany.yourapp" minSdkVersion MSBUILD_MIN_SDK_VERSION // ... } // ... }
-
MSBUILD_ANDROID_OUTPUT_APK_NAME
:Gradle 构建的 APK 的预期名称。Android 游戏开发扩展将查找与此名称匹配的 APK,然后将其部署到连接的设备(用于调试和分析)。在图 3 所示的项目属性页面的APK Name框中设置此值。Gradle 构建脚本必须尊重此属性。例如,以下示例将所有变体的输出 APK 名称设置为 MSBuild 选择的名称。
android { // ... applicationVariants.all { variant -> variant.outputs.all { outputFileName = MSBUILD_ANDROID_OUTPUT_APK_NAME } } // ... }
-
MSBUILD_JNI_LIBS_SRC_DIR
: 包含由 MSBuild 构建的共享库(.so
文件)的目录。在项目属性页面的输出目录框中设置此值, 如下所示。默认情况下,该值是 Visual Studio 项目的输出目录属性,如图 4 所示。Gradle 应将共享库文件打包到 APK 内的此文件夹中,以便 Android 应用程序在运行时加载它们。
android { // ... sourceSets { main { jniLibs.srcDirs += [MSBUILD_JNI_LIBS_SRC_DIR] } } // ... }
此外,由于任何 C/C++ 代码现在都是由 MSBuild 构建的,因此请删除
externalNativeBuild
Gradle 构建脚本中的部分。这些部分用于调用 CMake 或 ndk-build 来编译您的 C/C++ 代码,但不再需要。 -
MSBUILD_NDK_VERSION
:用于构建项目的 NDK 版本。在项目属性页面的Android NDK 版本框中设置此值,如图 5 所示。Gradle 构建脚本应设置
ndkVersion
为此值,如下所示:android { // ... ndkVersion MSBUILD_NDK_VERSION // ... }
有关更多信息,请参阅 Android Studio 主题 安装和配置 NDK 和 CMake。
//
调试器
使用 Android 游戏开发扩展时,使用 Visual Studio 调试器 (LLDB) 调试您的项目。
运行调试器
在运行调试器之前,您必须能够在 Android 上构建、部署和运行您的游戏。有关详细信息,请参阅运行示例部分。
一旦你确定你可以在没有调试器的情况下运行你的游戏,你可以通过按F5或选择调试菜单中的开始调试项目来使用调试器。当调试器附加到游戏时,您应该会看到一个对话框。
启动调试器需要 10 秒到 1 分钟或更长时间,具体取决于应用程序的大小和启动时需要加载的符号数量。首次连接到新设备时需要更多时间,因为调试器必须从设备下载一些 Android 库到主机。如果您在使用新设备的前几次尝试中花费的时间超过 1 分钟,请考虑取消调试会话,然后重新启动它。
当您以这种方式运行调试器时,游戏将以等待调试器模式启动,并且在调试器连接之前不会执行任何游戏代码。这使您还可以调试游戏的初始化部分。
您可以通过阅读Visual Studio 文档找到有关特定 Visual Studio 调试器功能的更多信息。
附加到进程
如果要调试已在物理或虚拟设备上运行的游戏,可以将调试器附加到 Visual Studio 中的进程。
在 Visual Studio 中,确保 Android 解决方案已打开,并且:
- 转到调试菜单并选择附加到进程...。
- 从Transport下拉列表中,选择Android Game Development Extension。
- 从Qualifier下拉列表中,选择您的 Android 设备。
- 从可用进程列表中选择游戏进程,然后单击附加。
执行 LLDB.Shell 命令
在调试会话处于活动状态时,使用 Visual Studio 的命令行窗口运行 LLDB.Shell 命令。
命令格式:
LLDB.Shell [command]
例子:
>LLDB.Shell expr myIntVariable = 9
Status: Success
Output Message:
(int) $2 = 9
警告:某些 shell 命令可能会导致 Visual Studio 与 LLDB 不同步并出现异常行为。
数据可视化
格式说明符
您可以使用格式说明符更改值在Autos、 Locals、Watch和变量DataTip窗口中显示的格式。
格式说明符位于表达式的末尾。它们以逗号开头,后跟一个短字符串。例如, 表达式,x
中的说明符会将myInt格式化为小写十六进制。_myInt,x
通过将格式说明符添加到 Natvis 表达式中,可以直接在Watch窗口或 Autos、Locals和DataTip窗口中使用格式说明符。有关详细信息,请参阅Natvis。
支持说明符列表
格式名称 | 说明符 | 描述 |
---|---|---|
布尔值 | 乙 | 将此显示为真/假布尔值,使用习惯规则,即 0 为假,其他一切为真 |
二进制 | b | 将其显示为一系列位 |
二进制,无前导 0b | bb | 将其显示为不带 0b 前缀的位序列 |
字节 | 是的 | 显示字节,但也尝试将它们显示为 ASCII 字符, 例如 (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._.... |
ASCII 字节 | 是 | 显示字节,但也尝试将它们显示为 ASCII 字符, 例如 (int *) c.sp.x = 50 f8 bf 5f ff 7f 00 00 P.._.... |
特点 | C | 将字节显示为 ASCII 字符, 例如 (int *) c.sp.x = P\xf8\xbf_\xff\x7f\0\0 |
可打印字符 | C | 将字节显示为可打印的 ASCII 字符, 例如 (int *) c.sp.x = P.._.... |
复数浮点数 | F | 将此值解释为复数浮点数的实部和虚部, 例如 (int *) c.sp.x = 2.76658e+19 + 4.59163e-41i |
十进制 | d, 我 | 将此显示为有符号整数(这不执行强制转换,它只是将字节显示为带符号的整数) |
枚举 | E,en | 将此显示为枚举,如果可用则打印值的名称,否则打印整数值, 例如 (枚举 enumType) val_type = eValue2 |
十六进制 - 小写 | x, h | 以小写十六进制表示法显示(这不执行强制转换,它只是将字节显示为十六进制) |
十六进制 - 大写 | X, H | 以大写十六进制表示法显示(这不执行强制转换,它只是将字节显示为十六进制) |
十六进制 - 小写,无前导 0x | xb, 血红蛋白 | 以不带 0x 前缀的小写十六进制表示法显示(这不执行强制转换,它只是将字节显示为十六进制) |
十六进制 - 大写,没有前导 0x | Xb,血红蛋白 | 以不带 0x 前缀的大写十六进制表示法显示(这不执行强制转换,它只是将字节显示为十六进制) |
漂浮 | F | 将其显示为浮点数(这不执行强制转换,它只是将字节解释为 IEEE754 浮点值) |
八进制 | ○ | 用八进制表示 |
操作系统类型 | ○ | 将其显示为 MacOS OSType, 例如 (浮点数)x = '\n\x1f\xd7\n' |
字符串 - C 字符串 | s | 将其显示为以 0 结尾的 C 字符串, 例如 “你好世界” |
string - C 字符串,不带引号 | 某人 | 将其显示为不带引号的以 0 结尾的 C 字符串, 例如 hello world |
字符串 - UTF-8 | s8 | 将其显示为以 0 结尾的 UTF-8 字符串, 例如 u8"你好世界☕" |
字符串 - UTF-8,无引号 | s8b | 将其显示为不带引号的以 0 结尾的 UTF-8 字符串, 例如 你好世界☕ |
字符串 - UTF-16 | 苏 | 将其显示为以 0 结尾的 UTF-16 字符串, 例如 你“你好世界☕” |
字符串 - UTF-16,无引号 | 子 | 将其显示为不带引号的以 0 结尾的 UTF-16 字符串, 例如 你好世界☕ |
字符串 - UTF-32 | s32 | 将其显示为以 0 结尾的 UTF-32 字符串, 例如 U“你好世界☕” |
字符串 - UTF-32,无引号 | s32b | 将其显示为不带引号的以 0 结尾的 UTF-32 字符串, 例如 你好世界☕ |
unicode16 | ü | 将其显示为 UTF-16 字符, 例如 (浮点数)x = 0xd70a 0x411f |
unicode32 | U32 | 将其显示为 UTF-32 字符, 例如 (浮点数)x = 0x411fd70a |
无符号十进制 | 你 | 将其显示为无符号整数(这不执行强制转换,它只是将字节显示为无符号整数) |
指针 | p | 将其显示为本机指针(除非这确实是一个指针,否则结果地址可能无效) |
复整数 | 我 | 将此值解释为复整数的实部和虚部, 例如 (int *) 指针 = 1048960 + 1i |
字符数组 | 一个 | 将其显示为字符数组, 例如 (char) *c.sp.z = {X} |
生的 | ! | 原始格式,忽略任何数据类型视图自定义 |
纳特维斯
Natvis 框架允许您自定义 Visual Studio 在调试器变量窗口中显示本机类型的方式。例如,使用 Natvis 自定义Watch、Locals和Data Tips窗口的显示。
Natvis 功能默认启用,但可以通过将Tools > Options > Android Game Development Extension > Natvis 标志设置为Disabled从 Visual Studio 禁用。
加载 Natvis 文件
Visual Studio 从下面列出的三个位置加载 Natvis 文件,并在您每次启动调试会话时重新加载它们。文件必须符合 Visual Studio 2017 Natvis 架构。
.natvis
作为已加载项目或顶级解决方案项的一部分的文件。- 用户特定目录 (
%USERPROFILE%\Documents\Visual Studio 2017\Visualizers
) - 系统范围的目录 (
%VSINSTALLDIR%\Common7\Packages\Debugger\Visualizers
)
重新加载 Natvis 文件
.natvisreload
在调试会话期间通过在命令窗口或监视窗口中进行评估来重新加载 Natvis 文件。
示例 Natvis 文件
此示例 Natvis 文件包含当前支持的所有标记和属性。
<span style="color:var(--devsite-code-color)"><code><?xml version=<span style="color:var(--devsite-code-strings-color)">"1.0"</span> encoding=<span style="color:var(--devsite-code-strings-color)">"utf-8"</span>?>
<span style="color:var(--devsite-code-keywords-color)"><AutoVisualizer</span> <span style="color:var(--devsite-code-types-color)">xmlns</span>=<span style="color:var(--devsite-code-strings-color)">"http://schemas.microsoft.com/vstudio/debugger/natvis/2010"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><Type</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"demo::Vector<*>"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><AlternativeType</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"MySimilarVectorType<*>"</span><span style="color:var(--devsite-code-keywords-color)">/></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <SmartPointer> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><SmartPointer</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Usage</span>=<span style="color:var(--devsite-code-strings-color)">"Minimal"</span><span style="color:var(--devsite-code-keywords-color)">></span>ptr<span style="color:var(--devsite-code-keywords-color)"></SmartPointer></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <DisplayString> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size == 0"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>()<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size == 1"</span><span style="color:var(--devsite-code-keywords-color)">></span>(x={_items[0]})<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size == 2"</span><span style="color:var(--devsite-code-keywords-color)">></span>(x={_items[0]}, y={_items[1]})<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size == 3"</span><span style="color:var(--devsite-code-keywords-color)">></span>(x={_items[0]}, y={_items[1]}, z={_items[2]})<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString></span>[Size={_size,x}] (x={_items[0]}, y={_items[1]}, z={_items[2]}, ...)<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <StringView> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><StringView</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_stringViewText<span style="color:var(--devsite-code-keywords-color)"></StringView></span>
<span style="color:var(--devsite-code-keywords-color)"><Expand</span> <span style="color:var(--devsite-code-types-color)">HideRawView</span>=<span style="color:var(--devsite-code-strings-color)">"false"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <Item> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><Item</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"X"</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size < 4 && _size >= 1"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_items[0]<span style="color:var(--devsite-code-keywords-color)"></Item></span>
<span style="color:var(--devsite-code-keywords-color)"><Item</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"Y"</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size < 4 && _size >= 2"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_items[1]<span style="color:var(--devsite-code-keywords-color)"></Item></span>
<span style="color:var(--devsite-code-keywords-color)"><Item</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"Z"</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size < 4 && _size >= 3"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_items[2]<span style="color:var(--devsite-code-keywords-color)"></Item></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <ArrayItems> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><ArrayItems</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"_size ></span>= 4" Optional="true">
<span style="color:var(--devsite-code-keywords-color)"><Size</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_size<span style="color:var(--devsite-code-keywords-color)"></Size></span>
<span style="color:var(--devsite-code-keywords-color)"><ValuePointer</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_items<span style="color:var(--devsite-code-keywords-color)"></ValuePointer></span>
<span style="color:var(--devsite-code-keywords-color)"></ArrayItems></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <IndexListItems> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><IndexListItems</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><Size</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_listSize<span style="color:var(--devsite-code-keywords-color)"></Size></span>
<span style="color:var(--devsite-code-keywords-color)"><ValueNode</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_list[%i]<span style="color:var(--devsite-code-keywords-color)"></ValueNode></span>
<span style="color:var(--devsite-code-keywords-color)"></IndexListItems></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <LinkedListItems> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><LinkedListItems</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><Size</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_listSize<span style="color:var(--devsite-code-keywords-color)"></Size></span>
<span style="color:var(--devsite-code-keywords-color)"><HeadPointer></span>_head<span style="color:var(--devsite-code-keywords-color)"></HeadPointer></span>
<span style="color:var(--devsite-code-keywords-color)"><NextPointer></span>_next<span style="color:var(--devsite-code-keywords-color)"></NextPointer></span>
<span style="color:var(--devsite-code-keywords-color)"><ValueNode></span>_value<span style="color:var(--devsite-code-keywords-color)"></ValueNode></span>
<span style="color:var(--devsite-code-keywords-color)"></LinkedListItems></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <ExpandedItem> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><ExpandedItem</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>_childVar<span style="color:var(--devsite-code-keywords-color)"></ExpandedItem></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <Synthetic> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><Synthetic</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"[Size]"</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><DisplayString></span>_size<span style="color:var(--devsite-code-keywords-color)"></DisplayString></span>
<span style="color:var(--devsite-code-keywords-color)"><Expand</span> <span style="color:var(--devsite-code-types-color)">HideRawView</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Any supported <Expand> sub-tags. --></span>
<span style="color:var(--devsite-code-keywords-color)"></Expand></span>
<span style="color:var(--devsite-code-keywords-color)"></Synthetic></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show the <TreeItems> feature is supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><TreeItems</span> <span style="color:var(--devsite-code-types-color)">Condition</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span> <span style="color:var(--devsite-code-types-color)">Optional</span>=<span style="color:var(--devsite-code-strings-color)">"true"</span><span style="color:var(--devsite-code-keywords-color)">></span>
<span style="color:var(--devsite-code-keywords-color)"><Size></span>_treeSize<span style="color:var(--devsite-code-keywords-color)"></Size></span>
<span style="color:var(--devsite-code-keywords-color)"><HeadPointer></span>_head<span style="color:var(--devsite-code-keywords-color)"></HeadPointer></span>
<span style="color:var(--devsite-code-keywords-color)"><LeftPointer></span>_left<span style="color:var(--devsite-code-keywords-color)"></LeftPointer></span>
<span style="color:var(--devsite-code-keywords-color)"><RightPointer></span>_right<span style="color:var(--devsite-code-keywords-color)"></RightPointer></span>
<span style="color:var(--devsite-code-keywords-color)"><ValueNode></span>_value<span style="color:var(--devsite-code-keywords-color)"></ValueNode></span>
<span style="color:var(--devsite-code-keywords-color)"></TreeItems></span>
<span style="color:var(--devsite-code-comments-color)"><!-- Included to show format specifiers are supported. --></span>
<span style="color:var(--devsite-code-keywords-color)"><Item</span> <span style="color:var(--devsite-code-types-color)">Name</span>=<span style="color:var(--devsite-code-strings-color)">"[Hex Dump at {_index,x}]"</span><span style="color:var(--devsite-code-keywords-color)">></span>myInt[_index],x<span style="color:var(--devsite-code-keywords-color)"></Item></span>
<span style="color:var(--devsite-code-keywords-color)"></Expand></span>
<span style="color:var(--devsite-code-keywords-color)"></Type></span>
<span style="color:var(--devsite-code-keywords-color)"></AutoVisualizer></span>
</code></span>
创作 Natvis 文件
Visual Studio 支持创作您自己的 Natvis 文件。有关自定义调试器变量窗口的更多信息,请参阅 MSDN {: external}。
调试 Natvis 文件
在某些情况下,错误将显示为变量的值(例如在Auto、Watch等窗口中)。例如:<error: use of undeclared identifier 'missingVar'>
您可以通过GoogleAndroid.log
从 Android 游戏开发扩展工具栏中打开文件来访问有关错误的更多详细信息。
已知限制
-
如果您的标签或属性未在上面的示例文件中列出,则它目前不受支持。Visual Studio 会忽略不受支持的标记和属性,因此您可以将它们保留在现有的 Natvis 文件中,只要它使用我们的架构,该文件就可以工作。
-
不支持该
Usage
属性,尽管架构需要 该属性<SmartPointer>
。但是,LLDB 不限制对 C++ 中定义的运算符的访问,因此任何需要的运算符都可以在 C++ 中定义。
//
衡量应用性能
您可以使用独立版本的 Android Studio Profiler 来衡量应用的性能。要启动分析器,请执行以下操作:
- 运行调试器。
- 单击 Visual Studio 工具栏中的探查器 按钮。
-
在SESSIONS旁边,单击 + 按钮并选择一个可调试的进程。
分析器显示以下类别的实时使用统计信息:CPU、内存、网络和能源。
有关某个类别的更多详细信息,请单击该类别的图表。
有关如何使用分析器的更多信息,请参阅Android Studio Profiler 文档
/
针对 Android Studio 修改 build 。分级文件
本指南介绍了如何修改 AGDE 项目中的build.gradle
文件,以便您可以在 Android Studio 中打开。本指南主要适用于管理 AGDE 项目的制造工程师。
在完成本指南中的更改后,您应该:
- 从使用 Android 工作室中进行制造。
- 制造多 ABI APK 和 App Bundle。
- 在 Android Studio 中利用完整的服务语言支持来修改源代码(go-to definition 等)。
- 使用Android Studio 调试程序进程和混合进程。
AGDE 以基于实验性的功能 Gradle 插件功能制造而成,支持Ninja 作为 Android 制造系统。
注意:这些更改依赖于 Android Gradle 插件中的实验性功能,功能可能会发生变化或被移除。
修改项目级构建。分级文件
更改项目级build.gradle
以引用 Android Gradle 插件版本 7.3.0-alpha02 或更高版本。
buildscript {
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.3.0-alpha02'
}
}
此变更生效后,您仍应能够在 Visual Studio 中编写项目。我们建议您立即试用,因为规定在接下来的更改之前进行调试将很容易。
将 run-msbuild 。bat 复制到您的项目中
调用最新版本的Tepot示例具有的脚本run-msbuild.bat
。此脚本调用一个名为,查找和调用MSBuild 的版本。
将run-msbuild.bat
复制到包含应用级build.gradle
文件的文件夹中。
注意:build.gradle
修改该文件后发布的 APK,该文件用于创建 APK。
修改应用级build.gradle
文件
这个步骤的主要目标是配置对run-msbuild.bat
的调用以及移除对MSBUILD_*
的引用。
设置 ndkVersion
将更ndkVersion
改为特定的 NDK 版本。例如:
android {
ndkVersion "22.1.7171670"
}
设置 minSdkVersion
将更minSdkVersion
改为特定的 SDK 版本。例如:
android {
defaultConfig {
minSdkVersion 30
}
}
调用运行-msbuild.bat
-
添加一个部分,以对项目的解决方案调用
run-msbuild.bat
。android { defaultConfig { externalNativeBuild { experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ] experimentalProperties["ninja.path"] = "Teapot.sln" experimentalProperties["ninja.configure"] = "run-msbuild" experimentalProperties["ninja.arguments"] = [ "\${ndk.moduleMakeFile}", "-p:Configuration=\${ndk.variantName}", "-p:Platform=Android-\${ndk.abi}", "-p:NinjaBuildLocation=\${ndk.buildRoot}", "-p:NinjaProject=GameApplication", "-p:RequireAndroidNdkVersion=\${ndk.moduleNdkVersion}", "-p:RequireMinSdkVersion=\${ndk.minPlatform}", "-t:GenerateBuildNinja" ] } } }
-
删除所有的
MSBUILD_JNI_LIBS_SRC_DIR
、MSBUILD_ANDROID_OUTPUT_APK_NAME
和MSBUILD_ANDROID_GRADLE_BUILD_OUTPUT_DIR
使用代码。通常,应用级
build.gradle
文件中的以下代码块可以完全删除。sourceSets { main { jniLibs.srcDirs = [MSBUILD_JNI_LIBS_SRC_DIR] } } applicationVariants.all { variant -> variant.outputs.all { outputFileName = MSBUILD_ANDROID_OUTPUT_APK_NAME } } buildDir = MSBUILD_ANDROID_GRADLE_BUILD_OUTPUT_DIR
反馈
此功能是实验功能,因此,如果您能提供反馈,我们将不会提供胜任性。提供方法如下:
- 一般性评论和评论,可以向这个错误添加注释。
- 要报告打开Android Studio,然后点击帮助,请点击帮助 >请参考C++查找“自定义C/构建系统”的bug。
- 如果您尚未安装 Android Studio,请点击此链接。
///
///