(转)android manifest.xml中元素含义

本文深入解析AndroidManifest.xml文件中的组件属性与配置,包括活动、服务、广播接收器等,详细阐述各属性的功能及作用,帮助开发者更好地理解和使用AndroidManifest.xml。

转自http://blog.youkuaiyun.com/wbw1985/archive/2009/11/24/4862319.aspx





  是否允许activity更换从属的任务,比如从短信息任务 切换到浏览器任务。
  --------------------------------------------------------------------------------------
  android:alwaysRetainTaskState
  是否保留状态不变, 比如切换回home, 再从新打开, activity处于最后的状态
  --------------------------------------------------------------------------------------
  android:clearTaskOnLanunch
比如 P 是 activity, Q 是被P 触发的 activity, 然后返回Home, 从新启动 P, 是否显示 Q
--------------------------------------------------------------------------------------
android:configChanges
当配置list发生修改时, 是否调用 onConfigurationChanged() 方法  比如 "locale|navigation|orientation".
--------------------------------------------------------------------------------------

activity 是否可以被实例化,
--------------------------------------------------------------------------------------

是否可被显示在最近打开的activity列表里
--------------------------------------------------------------------------------------
android:exported
是否允许activity被其它程序调用
--------------------------------------------------------------------------------------
android:finishOnTaskLaunch
是否关闭已打开的activity当用户重新启动这个任务的时候
--------------------------------------------------------------------------------------
android.icon
--------------------------------------------------------------------------------------
android:label
--------------------------------------------------------------------------------------
android:launchMode
activity启动方式,  "standard" "singleTop"  "singleTask" "singleInstance"  其中前两个为一组, 后两个为一组
--------------------------------------------------------------------------------------
android:multiprocess
允许多进程
--------------------------------------------------------------------------------------
android:name

--------------------------------------------------------------------------------------
android:onHistory
是否需要移除这个activity当用户切换到其他屏幕时。 这个属性是 API level 3 中引入的
--------------------------------------------------------------------------------------
android:permission
--------------------------------------------------------------------------------------
android:process
一个activity运行时所在的进程名,所有程序组件运行在应用程序默认的进程中,这个进程名跟应用程序的包名一致。中的元素process属性能够为所有组件设定一个新的默认值。但是任何组件都可以覆盖这个默认值,允许你将你的程序放在多进程中运行。  如果这个属性被分配的名字以:开头,当这个activity运行时, 一个新的专属于这个程序的进程将会被创建。 如果这个进程名以小写字母开头,这个activity将会运行在全局的进程中,被它的许可所提供。
--------------------------------------------------------------------------------------

activity显示的模式,  "unspecified" 默认值  "landscape" 风景画模式,宽度比高度大一些  "portrait" 肖像模式, 高度比宽度大。  "user" 用户的设置  "behind"  "sensor" "nosensor"

android:stateNotNeeded

--------------------------------------------------------------------------------------

activity的亲属关系, 默认情况同一个应用程序下的activity有相同的关系

android:theme
activity的样式主题, 如果没有设置,则activity的主题样式从属于应用程序, 参见元素的theme属性
--------------------------------------------------------------------------------------

activity主窗口与软键盘的交互模式, 自从API level 3 被引入

以下转自http://www.chinaup.org/docs/devel/bblocks-manifest.html

AndroidManifest.xml 文件

AndroidManifest.xml是每一个应用都需要的文件, 位于应用根目录下,它 描述了程序包的全局变量, 包括暴露的应用组件(activities, services等等)和为每个组件的实现类, 什么样的数据可以操作, 以及在什么地方运行。

这个文件的一个重要方面就是是其中的intent过滤器(intent filters)。 这些过滤器描述了何时何种情况下让活动(activity) 启动。 当一个activity(或是操作系统)想要执行一个动作, 例如打开一个Web页或是打开一个联系人选取屏幕,它将会创建一个Intent对象。 该对象包含了很多几个描述符(descriptors), 描述了你想做什么操作, 你想处理什么数据, 数据的类型, 以及一些其他的信息。 Android将Intent对象中的信息与所有应用暴露的intent过滤器比较, 找到一个最能恰当处理请求者要求的数据和动作(action)的activity。关于intents的更多信息在Intent页可以找到。

除了声明应用的活动(Activities),内容管理器( Content Providers),服务( Services), 和 Intent 接收器(Intent Receivers), 你也可以在AndroidManifest.xml文件中指定权限和instrumentation(安全控制和测试). 请查看AndroidManifest了解这个标签和他们的属性。

如下是一个简单的AndroidManifest.xml文件:

<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.my_domain.app.helloactivity">
        
    <application android:label="@string/app_name">
    
        <activity android:name=".HelloActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        
    </application>
    
</manifest>
 需要注意的一些通用事项:
  • 几乎所有的AndroidManifest.xml 文件(同其他的Android文件一样)都会在其第一个元素(element)中包含一个命名空间的声明xmlns:android="http://schemas.android.com/apk/res/android" 。 该声明使标准Android属性在该文件中可用,这些属性为文件中的xml元素提供了大部分数据。.

  • 大多数的manifests包含一个<application>元素, 该元素定了这个程序包内所有应用层面上可用的组件和属性。

  • 所有需要可以从应用程序启动器(program launcher)中呈现给用户的顶层应用都至少需要包括一个活动(Activity)组件,它用来支持MAIN action 和显示在LAUNCHER 目录中。

下面列出了AndroidManifest.xml 这个文件详细的结构大纲, 描述了所有可用标签。

<manifest>
文件根节点。 描述了程序包的所有内容。 在其节点下面内可以放置:
<uses-permission>
请求一个安全授权, 你的程序包必须被授予该权限才能正确的操作。参见看安全模块(  Security Model)文档以了解有关授权的更多信息。 一个manifest可以包含零个或多个这样的节点。
<permission>
声明一个安全授权,它 用来限制哪些应用可以访问你的(或别的)程序包内的组件和特有功能(feature)。参见看安全模块(  Security Model)文档以了解有关授权的更多信息。一个manifest可以包含零个或多个这样的节点。
<instrumentation>
声明一个instrumentation 组件可用于测试这一个或别的包的代码。更详细内容参见 Instrumentation 。一个manifest可以包含零个或多个这样的节点。
<application>
声明程序包内应用级别组件的根节点。 该节点能够描述应用程序的全局(和/或)默认属性, 例如标签, 图标, 主题, 需要的权限, 等等。 一个manifest可以包含零个或一个这样的节点(多个application 节点是不允许的)。 在该节点下, 可以包含零个或多个以下每个组件的声明:
<activity>
活动( Activity) 是应用与用户交互的最主要机制。当一个应用运行的时候, 用户看到的第一个屏幕就是activity。 此外, 用户所使用的其他绝大多数屏幕也是由独立的活动实现的,它们由额外活动tag声明。

注意: 无论活动是外部可见还是仅在程序包内使用,在manifest中每一个活动必须在定义一个 <activity>标签。如果活动在manifest 中没有匹配的标签,那么你无法启动它。</activity>

此外,为了支持运行时活动查找,你可以包含一个或多个 <intent-filter>元素来描述该活动支持的动作(actions)。</intent-filter>

<intent-filter>
以一个 IntentFilter的形式声明组件所支持的特定的一组  Intent 值。除了可以在此元素下指定的各种值,也可以在此对属性(atttibutes)进行赋值以支持唯一的标签(label),图标(icon),和所描述动作(action)的其它信息。
<action>
该组件支持的  Intent action
<category>
该组件支持的Intent目录( Intent category)。
<data>
该组件支持的  Intent data MIME typeIntent data URI schemeIntent data URI authority, 或  Intent data URI path

你也可把一个或多个meta-data 与你的活动(activity)关联,其它客户端(clients)可以取得这些meta-dada以获得关于这个活动的任意信息。

<meta-data>
向活动(activity)添加新的元数据(meta data),客户端可以通过 ComponentInfo.metaData获取该数据。
<receiver>
一个 BroadcastReceiver 可以使应用接收数据变化和行为发生的通知,即使这个应用没有在运行也同样可以。同activity 标签一样, 你可以选择包含一个或多个该receiver支持<intent-filter>元素或<meta-data>值。更多信息参见活动(activity)的<a href="http://www.chinaup.org/docs/devel/bblocks-manifest.html#intent-filter" style="color: rgb(0, 0, 204); outline-style: none; ">&lt;intent-filter&gt;</a> 和 <a href="http://www.chinaup.org/docs/devel/bblocks-manifest.html#meta-data" style="color: rgb(0, 0, 204); outline-style: none; ">&lt;meta-data&gt;</a>描述。</meta-data></intent-filter>
<service>
服务( Service )是一个在后台可以运行任意长时间的组件。 同activity 标签一样, 你可以选择包含一个或多个该服务支持<intent-filter>元素或<meta-data>值。更多信息参见活动(activity)的<a href="http://www.chinaup.org/docs/devel/bblocks-manifest.html#intent-filter" style="color: rgb(0, 0, 204); outline-style: none; ">&lt;intent-filter&gt;</a>和 <a href="http://www.chinaup.org/docs/devel/bblocks-manifest.html#meta-data" style="color: rgb(0, 0, 204); outline-style: none; ">&lt;meta-data&gt;</a> 描述。</meta-data></intent-filter>
<provider>
组件管理器( ContentProvider)用来管理持久数据和向其它应用发布数据的组件。你也可以按照活动的(activity’s)<meta-data>中描述附加一个或多 <a href="http://www.chinaup.org/docs/devel/bblocks-manifest.html#meta-data" style="color: rgb(0, 0, 204); outline-style: none; ">&lt;meta-data&gt;</a> 值。</meta-data>
<think>我们面对的是一个Android Repo管理的项目,需要遍历.repo/manifest.xml文件中的各个project,并获取每个project的commit id。 根据引用[1]和[2],我们知道.repo目录下包含manifests.git(或manifests)这个Git仓库,它存储了manifest.xml文件。实际上,我们通常使用.repo/manifests目录下的xml文件(可能是manifest.xml或者是通过符号链接指向的实际xml文件)。 步骤: 1. 确定manifest文件的位置:通常位于.repo/manifests/下。但实际使用的manifest可能是由.repo/manifest.xml符号链接指向的(例如,指向.repo/manifests/default.xml)。因此,我们可以使用.repo/manifest.xml这个文件(如果存在)或者通过.repo/manifests/目录下的文件来确定。 2. 解析manifest.xml文件:该文件是一个XML文件,其中包含多个<project>元素。每个<project>元素有name(远程仓库名)和path(本地路径)等属性。重要的是,我们需要获取每个project的revision(即commit id或分支名)。但注意,revision可能定义在<project>元素上,也可能定义在其父元素<default>中(引用[3]提到,revision可以是一个分支名,也可以是一个commit id)。 3. 对于每个project,我们需要确定其revision(即commit id)。但是,如果revision是一个分支名,我们还需要进一步获取该分支当前指向的commit id。 4. 另外,根据引用[2],我们知道Repo工具本身将manifest仓库和repo仓库作为两个特殊的项目(MetaProject)进行管理。所以,我们可能还需要考虑这两个项目?但用户问题中只要求遍历manifest.xml里的各个project,所以通常不包括这两个。 因此,我们可以通过以下步骤实现: 步骤1:找到当前仓库使用的manifest文件。 - 通常,.repo/manifest.xml是一个符号链接,指向.repo/manifests/下的某个xml文件(如default.xml)。我们可以读取这个符号链接指向的实际文件。 步骤2:解析该XML文件,获取所有的<project>元素。 - 读取每个<project>元素的name、path和revision属性(如果没有revision属性,则使用<default>标签中的revision)。 步骤3:对于每个project,如果revision是一个分支(引用[3]提到,revision可以是分支名),则需要获取该分支当前指向的commit id;如果revision是一个commit id,则直接使用。 步骤4:输出每个project的name、path、revision(分支名)和commit id(实际的哈希值)。 注意:由于我们可能无法直接通过manifest.xml中的revision属性判断是分支还是commit id(因为commit id也是哈希字符串,分支是字符串,但有时分支名可能是哈希?通常不会),我们可以尝试: - 在project的路径下,使用git命令检查这个revision是一个分支还是commit id。但是,更可靠的做法是:在project的路径下,使用`git rev-parse`来获取该revision对应的commit id。 具体实现: 1. 确定manifest文件: manifest_file=".repo/manifest.xml" if [ ! -e "$manifest_file" ]; then echo "Error: .repo/manifest.xml not found." >&2 exit 1 fi # 如果manifest.xml是符号链接,则获取其实际路径 if [ -L "$manifest_file" ]; then manifest_file=$(readlink -f "$manifest_file") fi 2. 使用工具解析XML:在shell中,我们可以使用`xmllint`(需要安装libxml2)或者`xmlstarlet`来解析XML。 这里我们使用`xmllint`(更常见)来提取所有的project节点及其属性。 3. 提取每个project的name、path和revision(如果没有revision,则使用default的revision): default_revision=$(xmllint --xpath '//default/@revision' "$manifest_file" | awk -F'"' '{print $2}') # 然后遍历每个project xmllint --xpath '//project' "$manifest_file" | while read -r project_node; do # 提取属性 name=$(echo "$project_node" | grep -o 'name="[^"]*"' | cut -d'"' -f2) path_attr=$(echo "$project_node" | grep -o 'path="[^"]*"' | cut -d'"' -f2) revision=$(echo "$project_node" | grep -o 'revision="[^"]*"' | cut -d'"' -f2) # 如果没有指定revision,则使用default_revision if [ -z "$revision" ]; then revision="$default_revision" fi # 如果没有path属性,则使用name作为路径 if [ -z "$path_attr" ]; then path_attr="$name" fi # 现在,我们有了项目路径(相对于仓库根目录)和revision(可能是分支名或commit id) # 进入该项目目录,获取实际的commit id full_path=".repo/project-objects/${name}.git" # 注意:在.repo/project-objects下存储了每个项目的裸仓库 # 但是,根据repo的目录结构,我们也可以使用.repo/projects/$path_attr.git(但这里使用project-objects更为直接,因为name是唯一的) # 或者,我们可以使用工作目录:$path_attr,但需要确保该目录已经同步(可能没有同步,所以我们使用裸仓库) # 裸仓库的位置:.repo/project-objects/$name.git # 使用git命令在裸仓库中获取revision对应的commit id if [ -d ".repo/project-objects/${name}.git" ]; then commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q ${revision}^{commit} 2>/dev/null) if [ -z "$commit_id" ]; then # 如果失败,可能是revision不存在,或者项目未下载 commit_id="unknown" fi else commit_id="not_downloaded" fi echo "Project: $name" echo "Path: $path_attr" echo "Revision: $revision" echo "Commit ID: $commit_id" echo "-----------------------------------" done 但是,上面的循环处理project节点的方式不够健壮,因为`xmllint --xpath '//project'`输出的格式可能不是每行一个节点(而是连续输出)。我们可以使用`xmllint`配合`--shell`或者使用`xmlstarlet`更合适。 另一种方法是使用`xmlstarlet`工具(如果系统没有,需要安装)来逐个提取节点。 考虑到兼容性,这里我们使用`xmllint`结合循环: # 获取project节点的数量 count=$(xmllint --xpath 'count(//project)' "$manifest_file") for ((i=1; i<=count; i++)); do # 提取第i个project节点 name=$(xmllint --xpath "string(//project[$i]/@name)" "$manifest_file") path_attr=$(xmllint --xpath "string(//project[$i]/@path)" "$manifest_file") revision=$(xmllint --xpath "string(//project[$i]/@revision)" "$manifest_file") # 如果revision为空,则使用default的revision if [ -z "$revision" ]; then revision=$default_revision fi # 如果path为空,则使用name if [ -z "$path_attr" ]; then path_attr="$name" fi # 处理裸仓库路径 if [ -d ".repo/project-objects/${name}.git" ]; then commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q ${revision}^{commit} 2>/dev/null) # 如果失败,尝试直接获取该分支或标签的引用(但要求必须是commit) if [ -z "$commit_id" ]; then commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q ${revision} 2>/dev/null) # 检查是否为commit(避免是树或标签) if git --git-dir=".repo/project-objects/${name}.git" cat-file -t "$commit_id" 2>/dev/null | grep -q "commit"; then : # 是commit else commit_id="invalid" fi fi else commit_id="not_downloaded" fi # 输出 echo "Project: $name" echo "Path: $path_attr" echo "Revision: $revision" echo "Commit ID: ${commit_id:-unknown}" echo "-----------------------------------" done 注意:如果项目还没有下载(即.repo/project-objects下没有对应的仓库),则无法获取commit id。 但是,我们也可以考虑另一种方式:repo forall命令。实际上,repo工具提供了一个命令`repo forall`可以在每个项目上执行命令。 我们可以使用:`repo forall -c 'echo $REPO_PROJECT $REPO_PATH $REPO_REVISION'`,但是这里获取的REPO_REVISION是manifest中指定的revision(可能是分支或commit id),而不是最终的commit id。 要获取每个项目的commit id,我们可以: repo forall -c 'echo $REPO_PROJECT `git rev-parse HEAD`' 但是,这需要项目已经checkout(即工作目录存在)。如果我们还没有同步代码,则无法使用。 我们的需求是直接从manifest.xml中解析并利用裸仓库(即使没有工作目录)来获取commit id,所以使用裸仓库的方法更通用。 因此,我们综合上面的思路,编写脚本如下: 注意:我们假设.repo/manifest.xml存在,并且裸仓库在.repo/project-objects下。 但是,在repo的目录结构中,manifest仓库本身并不在manifest.xml的project列表中,它是一个特殊的项目。所以,我们脚本中只处理manifest.xml中列出的project。 另外,我们需要处理默认的revision(在default标签中)。 完整脚本如下: ```bash #!/bin/bash # 设置manifest文件路径 manifest_file=".repo/manifest.xml" # 如果manifest.xml是符号链接,则获取实际路径 if [ -L "$manifest_file" ]; then manifest_file=$(readlink -f "$manifest_file") fi if [ ! -f "$manifest_file" ]; then echo "错误: 找不到manifest文件: $manifest_file" >&2 exit 1 fi # 获取默认revision default_revision=$(xmllint --xpath 'string(//default/@revision)' "$manifest_file") # 获取project节点的数量 count=$(xmllint --xpath 'count(//project)' "$manifest_file") # 如果没有project节点,则退出 if [ "$count" -eq 0 ]; then echo "没有找到任何project节点" exit 0 fi # 遍历每个project节点 for ((i=1; i<=count; i++)); do # 提取属性 name=$(xmllint --xpath "string(//project[$i]/@name)" "$manifest_file") path_attr=$(xmllint --xpath "string(//project[$i]/@path)" "$manifest_file") revision=$(xmllint --xpath "string(//project[$i]/@revision)" "$manifest_file") # 如果没有指定revision,则使用默认的 if [ -z "$revision" ]; then revision="$default_revision" fi # 如果没有指定path,则使用name作为路径 if [ -z "$path_attr" ]; then path_attr="$name" fi # 检查裸仓库是否存在 if [ -d ".repo/project-objects/${name}.git" ]; then # 进入裸仓库目录,获取commit id commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q ${revision}^{commit} 2>/dev/null) if [ -z "$commit_id" ]; then # 尝试直接解析revision(可能是一个标签或分支) commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q "$revision" 2>/dev/null) # 验证是否为commit(因为rev-parse可能返回标签对象或树对象) if [ -n "$commit_id" ]; then # 获取对象类型 obj_type=$(git --git-dir=".repo/project-objects/${name}.git" cat-file -t "$commit_id" 2>/dev/null) if [ "$obj_type" != "commit" ]; then # 如果不是commit,则尝试进一步解析(例如标签) commit_id=$(git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify -q "$revision^{commit}" 2>/dev/null) fi fi # 如果还是空,则标记为未知 if [ -z "$commit_id" ]; then commit_id="unknown" fi fi else commit_id="not_downloaded" fi # 输出结果 echo "Project: $name" echo "Path: $path_attr" echo "Revision: $revision" echo "Commit ID: $commit_id" echo "-----------------------------------" done ``` 注意: 1. 该脚本需要在Android Repo仓库的根目录下运行(即.repo目录的父目录)。 2. 依赖xmllint(通常由libxml2-utils包提供)和git。 3. 如果项目还没有下载(not_downloaded),则无法获取commit id。 4. 解析revision时,我们首先尝试将其解析为commit(通过后缀^{commit}),如果失败,则尝试直接解析,并检查对象类型,如果不是commit,则再次尝试解析为commit(例如,如果revision是一个标签,则指向的commit)。 另外,如果revision是一个分支名,那么上述方法会返回该分支当前指向的commit id。 最后,我们生成相关问题: </think>### Android Repo 项目遍历 Commit ID 方法 以下是针对 Android Repo 项目中遍历 manifest.xml 文件获取各项目 commit ID 的完整解决方案: ```bash #!/bin/bash # 步骤1:定位 manifest 文件 manifest_file=".repo/manifest.xml" if [ -L "$manifest_file" ]; then manifest_file=$(readlink -f "$manifest_file") fi if [ ! -f "$manifest_file" ]; then echo "错误: 找不到 manifest 文件" >&2 exit 1 fi # 步骤2:解析 manifest.xml 获取默认 revision default_revision=$(xmllint --xpath 'string(/manifest/default/@revision)' "$manifest_file" 2>/dev/null) # 步骤3:遍历所有 project 节点 xmllint --xpath '//project' "$manifest_file" 2>/dev/null | while read -r project; do # 提取项目属性 name=$(echo "$project" | grep -oP 'name="\K[^"]+') path_attr=$(echo "$project" | grep -oP 'path="\K[^"]+' || echo "$name") revision=$(echo "$project" | grep -oP 'revision="\K[^"]+' || echo "$default_revision") # 获取实际 commit ID repo_dir=".repo/project-objects/${name}.git" if [ -d "$repo_dir" ]; then commit_id=$(git --git-dir="$repo_dir" rev-parse --verify "$revision" 2>/dev/null) [ -z "$commit_id" ] && commit_id="<无效的revision>" else commit_id="<项目未下载>" fi # 输出结果 echo "项目名称: $name" echo "本地路径: $path_attr" echo "指定版本: $revision" echo "Commit ID: $commit_id" echo "------------------------------------" done ``` ### 关键步骤说明 1. **Manifest 文件定位** 自动处理符号链接,确保找到实际 manifest 文件[^1]: ```bash manifest_file=$(readlink -f ".repo/manifest.xml") ``` 2. **XML 解析技术** 使用 `xmllint` 工具解析 XML 结构: - 获取默认 revision:`/manifest/default/@revision` - 遍历所有 project 节点:`//project` 3. **属性提取逻辑** 正则表达式提取关键属性: ```bash name=$(echo "$project" | grep -oP 'name="\K[^"]+') ``` 4. **Commit ID 获取** 通过裸仓库获取实际 commit ID[^2]: ```bash git --git-dir=".repo/project-objects/${name}.git" rev-parse --verify "$revision" ``` 5. **特殊处理逻辑** - 路径缺省时使用项目名:`path_attr || echo "$name"` - 无效 revision 处理:`[ -z "$commit_id" ] && commit_id="<无效的revision>"` ### 使用说明 1. 保存为 `get_repo_commits.sh` 2.Android 源码根目录执行: ```bash chmod +x get_repo_commits.sh ./get_repo_commits.sh ``` ### 输出示例 ```text 项目名称: platform/build 本地路径: build 指定版本: main Commit ID: 8a4b3d7f1e2c6a9b0c5d8e7f1a2b3c4d5e6f7a8b ------------------------------------ 项目名称: platform/frameworks/base 本地路径: frameworks/base 指定版本: android12-release Commit ID: d9e8f7a6b5c4d3e2f1a0b9c8d7e6f5a4b3c2d1e0 ------------------------------------ ``` ### 注意事项 1. 需要安装 `xmllint` 工具:`sudo apt install libxml2-utils` 2. `.repo/project-objects` 包含所有项目的裸仓库[^1] 3. `revision` 可以是分支名或 commit ID[^3] 4. 项目未下载时将显示 `<项目未下载>` 5. 确保在 Repo 初始化的 Android 源码根目录执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值