Android——编译体系中的【PRODUCT_COPY_FILES】【ALL_PREBUILT】【BUILD_PREBUILT】

PRODUCT_COPY_FILES语法解析 已开通新的博客,后续文字都会发到新博客 http://www.0xfree.top Android 编译系统解析系列文档 解析lunch的执行过程以及make执行过程中include文件的顺序 Android编译系统分析之lunch分析 Android编译系统分析之make分析 关注一些make执行过程中的几个关键点 Android编译系统分析之几个关键点(一) Android编译系统分析... 阅读详情
AI摘要

本文介绍了Android系统层中常见的几种文件复制方法,包括PRODUCT_COPY_FILES的使用方式、copy_from和copy_to配合ALL_PREBUILT的注意事项以及通过BUILD_PREBUILT进行文件复制的过程。此外,还详细讲解了如何批量复制文件夹。

           对andriod系统层进行开发,或者进行移植时,时常需要添加文件到编译体系中,在最终的编译中复制到out中,最后打包成镜像,这里总结一下Copy File 方法,这里以我的 android 4.2.1为例.

如有不对或者有其它的新招,欢迎拍砖留言~


                                                 撰写不易,转载请注明出处:http://blog.youkuaiyun.com/jscese/article/details/40615801


一.PRODUCT_COPY_FILES :

这个变量就是用来标记Copy操作的,比较常见的形式如下:

#jscese cp 3g script and 
PRODUCT_COPY_FILES += \
    $(DEVICE_SOURCES)/3g-script/ip-up-datakey:system/etc/ppp/ip-up-datakey \
    $(DEVICE_SOURCES)/3g-script/ip-down-datakey:system/etc/ppp/ip-down-datakey \
    $(DEVICE_SOURCES)/3g-script/init.gprs-pppd:system/etc/ppp/init.gprs-pppd \
    device/sample/etc/apns-full-conf.xml:system/etc/apns-conf.xml \
    #external/usb-modeswitch/usb_modeswitch.d:system/etc/usb_modeswitch.d
#PRODUCT_COPY_FILES += \  
    #$(DEVICE_SOURCES)/3g-script/ip-down-datakey:system/etc/ppp/ip-down-datakey 
    
#end

可以看到 格式<source file>:<dest file> 中间用 “ :  ” 隔开!



编译过源码的都知道在最开始 编译的时候 都会出现:

PRODUCT_COPY_FILES frameworks/base/data/sounds/effects/ogg/Effect_Tick.ogg:system/media/audio/ui/Effect_Tick.ogg ignored.
PRODUCT_COPY_FILES frameworks/base/data/sounds/effects/ogg/KeypressStandard.ogg:system/media/audio/ui/KeypressStandard.ogg ignored.
PRODUCT_COPY_FILES frameworks/base/data/sounds/effects/ogg/KeypressSpacebar.ogg:system/media/audio/ui/KeypressSpacebar.ogg ignored.
PRODUCT_COPY_FILES frameworks/base/data/sounds/effects/ogg/KeypressDelete.ogg:system/media/audio/ui/KeypressDelete.ogg ignored.
PRODUCT_COPY_FILES frameworks/base/data/sounds/effects/ogg/KeypressReturn.ogg:system/media/audio/ui/KeypressReturn.ogg ignored.
...
这样的打印,现在告诉你这东西在哪里打出来的~  /build/core/Makefile 中最开始的:

# -----------------------------------------------------------------
# Define rules to copy PRODUCT_COPY_FILES defined by the product.
# PRODUCT_COPY_FILES contains words like <source file>:<dest file>[:<owner>].
# <dest file> is relative to $(PRODUCT_OUT), so it should look like,
# e.g., "system/etc/file.xml".
# The filter part means "only eval the copy-one-file rule if this
# src:dest pair is the first one to match the same dest"
#$(1): the src:dest pair
define check-product-copy-files
$(if $(filter %.apk, $(1)),$(error \
    Prebuilt apk found in PRODUCT_COPY_FILES: $(1), use BUILD_PREBUILT instead!))
endef
# filter out the duplicate <source file>:<dest file> pairs.
unique_product_copy_files_pairs :=
$(foreach cf,$(PRODUCT_COPY_FILES), \
    $(if $(filter $(unique_product_copy_files_pairs),$(cf)),,\
        $(eval unique_product_copy_files_pairs += $(cf))))
unique_product_copy_files_destinations :=
$(foreach cf,$(unique_product_copy_files_pairs), \
    $(eval _src := $(call word-colon,1,$(cf))) \
    $(eval _dest := $(call word-colon,2,$(cf))) \
    $(call check-product-copy-files,$(cf)) \
    $(if $(filter $(unique_product_copy_files_destinations),$(_dest)), \
        $(info PRODUCT_COPY_FILES $(cf) ignored.), \
        $(eval _fulldest := $(call append-path,$(PRODUCT_OUT),$(_dest))) \
        $(if $(filter %.xml,$(_dest)),\
            $(eval $(call copy-xml-file-checked,$(_src),$(_fulldest))),\
            $(eval $(call copy-one-file,$(_src),$(_fulldest)))) \
        $(eval ALL_DEFAULT_INSTALLED_MODULES += $(_fulldest)) \
        $(eval unique_product_copy_files_destinations += $(_dest))))
unique_product_copy_files_pairs :=
unique_product_copy_files_destinations :=

这就是 PRODUCT_COPY_FILES 起作用的地方! 可以看上面注释,描述了规则用法,只能copy file!

也就是上面编译打印的出处,代表忽略项. 详细的规则可跟进去细看,无非是依赖Copy之类的.



这里需要注意一点, PRODUCT_COPY_FILES 不能在 Android.mk 中使用 添加新的Copy 项!

详情可看/build/core/main.mk 中的:

# Can't use first-makefiles-under here because
# --mindepth=2 makes the prunes not work.
subdir_makefiles := \
	$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)

include $(subdir_makefiles)

endif # ONE_SHOT_MAKEFILE

# Now with all Android.mks loaded we can do post cleaning steps.
include $(BUILD_SYSTEM)/post_clean.mk

ifeq ($(stash_product_vars),true)
  $(call assert-product-vars, __STASHED)
endif

在这里加载所有的Android.mk ,重点在后面的 assert-product-vars 函数:

#
# Assert that the the variable stashed by stash-product-vars remains untouched.
# $(1): The prefix as supplied to stash-product-vars
#
define assert-product-vars
$(strip \
  $(eval changed_variables:=)
  $(foreach v,$(_product_stash_var_list), \
    $(if $(call streq,$($(v)),$($(strip $(1))_$(call rot13,$(v)))),, \
        $(eval $(warning $(v) has been modified: $($(v)))) \
        $(eval $(warning previous value: $($(strip $(1))_$(call rot13,$(v))))) \
        $(eval changed_variables := $(changed_variables) $(v))) \
   ) \
  $(if $(changed_variables),\
    $(eval $(error The following variables have been changed: $(changed_variables))),)
)
endef

如果有改变就会报错的,编译出错如下:

build/core/main.mk:528: *** The following variables have been changed: PRODUCT_COPY_FILES。 停止。


使用 PRODUCT_COPY_FILES 应该算是最常用的Copy File 的方法了,一般可直接加在 device.mk 中!




二 .copy_to copy_from ALL_PREBUILT:

  这个方法用在Android.mk中,可参考 /system/core/rootdir/Android.mk:

copy_from += etc/init.goldfish.sh

copy_to := $(addprefix $(TARGET_OUT)/,$(copy_from))
copy_from := $(addprefix $(LOCAL_PATH)/,$(copy_from))

$(copy_to) : PRIVATE_MODULE := system_etcdir
$(copy_to) : $(TARGET_OUT)/% : $(LOCAL_PATH)/% | $(ACP)
    $(transform-prebuilt-to-target)

ALL_PREBUILT += $(copy_to)

可以看到copy_from 就是需要copy的,copy_to 就是目的地!

可以看下规则,定义在/build/core/definitions.mk中:

# Copy a prebuilt file to a target location.
define transform-prebuilt-to-target
@echo "$(if $(PRIVATE_IS_HOST_MODULE),host,target) Prebuilt: $(PRIVATE_MODULE) ($@)"
$(copy-file-to-target)
endef

define copy-file-to-target
@mkdir -p $(dir $@)
$(hide) $(ACP) -fp $< $@
endef

需要注意的是,如果我们自己添加一些文件到 copy_from中,就会出现 :

build/core/main.mk:533: *** Some files have been added to ALL_PREBUILT.
build/core/main.mk:534: *
build/core/main.mk:535: * ALL_PREBUILT is a deprecated mechanism that
build/core/main.mk:536: * should not be used for new files.
build/core/main.mk:537: * As an alternative, use PRODUCT_COPY_FILES in
build/core/main.mk:538: * the appropriate product definition.
build/core/main.mk:539: * build/target/product/core.mk is the product
build/core/main.mk:540: * definition used in all products.
build/core/main.mk:541: *
build/core/main.mk:542: * unexpected usb_modeswitch.h in ALL_PREBUILT
build/core/main.mk:542: * unexpected usb_modeswitch.sh in ALL_PREBUILT
build/core/main.mk:542: * unexpected usb_modeswitch.tcl in ALL_PREBUILT
build/core/main.mk:543: *
build/core/main.mk:544: *** ALL_PREBUILT contains unexpected files。 停止。

错误发生在 /build/core/main.mk

include $(BUILD_SYSTEM)/legacy_prebuilts.mk
ifneq ($(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),)
  $(warning *** Some files have been added to ALL_PREBUILT.)
  $(warning *)
  $(warning * ALL_PREBUILT is a deprecated mechanism that)
  $(warning * should not be used for new files.)
  $(warning * As an alternative, use PRODUCT_COPY_FILES in)
  $(warning * the appropriate product definition.)
  $(warning * build/target/product/core.mk is the product)
  $(warning * definition used in all products.)
  $(warning *)
  $(foreach bad_prebuilt,$(filter-out $(GRANDFATHERED_ALL_PREBUILT),$(strip $(notdir $(ALL_PREBUILT)))),$(warning * unexpected $(bad_prebuilt) in ALL_PREBUILT))
  $(warning *)
  $(error ALL_PREBUILT contains unexpected files)
endif


上面的打印信息告诉我们  ALL_PREBUILT  是一种过时的机制,已经不让用于copy新的文件了,推荐使用PRODUCT_COPY_FILES  !


而可以添加进 ALL_PREBUILT 变量的成员定义在 legacy_prebuilts.mk中:

 # This is the list of modules grandfathered to use ALL_PREBUILT

# DO NOT ADD ANY NEW MODULE TO THIS FILE
#
# ALL_PREBUILT modules are hard to control and audit and we don't want
# to add any new such module in the system

GRANDFATHERED_ALL_PREBUILT := \
    akmd2 \
    am \
    ap_gain.bin \

...

注释写的很明白了!

所以如果我们自己想加个文件编译copy ,就不能使用 copy_from copy_to ALL_prebuilt 这种机制 !




三 .BUILD_PREBUILT :

      这种方式把文件当成编译项目,在Android.mk中copy一个file:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS) \
LOCAL_MODULE := usb_modeswitch.conf \
LOCAL_MODULE_CLASS := ETC  \
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc \
LOCAL_SRC_FILES :=$(LOCAL_MODULE)  \
include $(BUILD_PREBUILT) 

上面的就是copy usb_modeswitch.conf 文件到 OUT 下面的 etc目录,这个目录常用来存放配置相关文件。

上面所有的都说的是Copy File  但是如果需要 Copy 一个文件目录下所有就需要另做操作了!




四 .Copy Directory

       以我前面的博客  Android——4.2 - 3G移植之路之usb-modeswitch (二)  中copyusb-modewitch.d 数据目录 为例.

在那里的Android.mk 中我使用了shell命令Copy:

$(shell cp -rf $(LOCAL_PATH)/usb_modeswitch.d $(TARGET_OUT)/etc/usb_modeswitch.d)  

这样做在源码已经编译好了的情况下,是没有问题的,因为$(TARGET_OUT)/etc 目录已经存在,但是作为新编译是不会Copy的,

所以说在android的编译体系中 还得按照android提供的机制来进行操作,像这种shell取巧,是方便,但不是正途!

我现在的处理:

在上面的shell的地方 include 处理Copy usb-modewitch.d 的mk文件,内容如下:

# $(1): module name
# $(2): source file
# $(3): destination directory
define include-prebuilt-with-destination-directory
include $$(CLEAR_VARS)
LOCAL_MODULE := $(1)
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/usb_modeswitch_data.mk
LOCAL_MODULE_STEM := $(notdir $(2))
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_PATH := $(3)
LOCAL_SRC_FILES := $(2)
include $$(BUILD_PREBUILT)
endef

#== rename 's/:/_/' * ==#


usb_modeswitch_data := $(notdir $(wildcard $(LOCAL_PATH)/usb_modeswitch.d/*))

$(warning jscese display -usb_modeswitch_data--$(usb_modeswitch_data))

usb_modeswitch_data_target_directory := $(TARGET_OUT)/etc/usb_modeswitch.d
$(foreach data, $(usb_modeswitch_data), $(eval $(call include-prebuilt-with-destination-directory,target-data-$(notdir $(data)),usb_modeswitch.d/$(data),$(usb_modeswitch_data_target_directory))))
usb_modeswitch_data_target := $(addprefix $(usb_modeswitch_data_target_directory)/,$(foreach cacert,$(usb_modeswitch_data),$(notdir $(usb_modeswitch_data))))
.PHONY: usb_modeswitch_data_target
usb_modeswitch_data: $(usb_modeswitch_data_target)

# This is so that build/target/product/core.mk can use usb_modeswitch_data in PRODUCT_PACKAGES
ALL_MODULES.usb_modeswitch_data.INSTALLED := $(usb_modeswitch_data_target)

可以看到原理同 Copy 一个单独的 File是一样的 BUILD_PREBUILT ,只不过是遍历了一下文件夹,而且把这个当成一个module来处理 写进 PRODUCT_PACKAGES

关于PRODUCT_PACKAGES 变量的作用可参考我之前的博文 Android——编译安装Module的控制因素


另外因为文件名称都是 XXXX:XXXX类型,我这里先在直接使用reanme命令把:全替换成 _

如果不替换,导致传入文件的时候 makefile 把中间的 : 可能当成了依赖符号~ 会报错

我如果使用subst 把:换成 \: 添加进去转义符号,好像是文件又找不到,不知道有没有遇到过这种情况.....





Android 进阶——源码编译之产品配置和常用的Make脚本模板 前面文章总结了MakeFile基础语法和对Android.mk的进行了解读,这篇文章将从整体上概述下AOSP 编译时的产品配置相关知识。Android 的产品配置文件的作用是按照Build系统的要求,将生成产品的各种image文件所需要的对应信息(如版本号等各种参数)、资源(图片、字体、多媒体等)、二进制文件(apk、jar、so库等)有机组织起来,同时根据配置文件进行裁剪或增加模块,所谓系统支持在一定程度上其实就像将相应的资源添加到对应的文件中。默认的编译类型,该编译类型适用于开发阶段,执行即,编译时以下 阅读详情

相关推荐

Android.mk--编译Android的模块

Android中的各种模块,无论是APK应用、可执行程序还是jar包,都可以通过Build系统编译生成。在每一个模块的源码目录下,都有一个Android.mk文件,里面包含了模块代码的位置、模块的名称、需要链接的动态库等一系列的定义。

Kitty_Landon的专栏 5663

Android 10.0 根文件系统和编译系统

1, 讲解android根文件系统结构和组成2, 讲解android系统镜像的概念和拆包3, 讲解Android系统源码结构4, 讲解Android系统编译规则5, 讲解Android系统ADB使用和Log日志调试方法6, 讲解Android系统Android.mk和Android.bp是各种规则 

从RTL到GDSII:DC综合里那些没人告诉你的时钟约束冷知识(附真实工程示例)

本文深入探讨数字IC设计中DC综合阶段的时钟约束冷知识,包括无毛刺时钟切换、寄存器分频时钟约束、虚拟时钟应用等关键技巧。通过真实工程示例,揭示常见约束误区及解决方案,帮助工程师提升时序收敛效率。特别针对input_delay和output_delay在多时钟域场景下的设置陷阱提供实用指南。

weixin_29306317的博客 430

用PRODUCT_COPY_FILES拷贝文件夹(转)

(shell cp -rf $(LOCAL_PATH)/usb_modeswitch.d ${OUT)}"/system/etc/"),然后通过shell拷贝任意文件。$(shell mkdir -p ${OUT}"/system/etc/")源码编译的时候,先读取该mk文件,该目录还没创建,所以要建一个,否则拷贝失败。原因是build/core/Makefile中对copy file作了检测,如果是apk文件,会出错。如果出现拷贝的是apk文件,则有可能出现如下错误。

m0_64837135的博客 2830

XGBoost调参新姿势:Bayesian优化实战指南(附完整代码)

本文详细介绍了如何使用Bayesian优化方法高效调优XGBoost模型参数。通过解析Bayesian优化核心原理和XGBoost关键参数,提供完整的实战代码示例,帮助读者掌握这一智能调参技术,显著提升模型性能。文章特别适合机器学习工程师和数据科学家阅读。

weixin_42536058的博客 366

【实战解析】RTL8306MB交换芯片驱动开发中的RMII接口调试陷阱

本文通过一个RTL8306MB交换芯片驱动开发的实战案例,深入剖析了RMII接口调试中的经典陷阱。文章详细描述了因TX_EN与CRS_DV信号线交叉连接错误导致的“静默”故障,并分享了使用逻辑分析仪和示波器进行硬件排查的完整流程与核心技巧,为嵌入式网络驱动开发提供了宝贵的避坑指南。

weixin_29267307的博客 421

Android——编译体系中的【PRODUCT_COPY_FILES】【ALL_PREBUILT】【BUILD_PREBUILT

对andriod系统层进行开发,或者进行移植时,时常需要添加文件到编译体系中,在最终的编译中复制到out中,最后打包成镜像,这里总结一下Copy File 方法,这里以我的 android 4.2.1为例. 如有不对或者有其它的新招,欢迎拍砖留言~                                                  撰写不易,转载请注明出处:htt

专栏 6038

BQ4050开发进阶(二):Protections参数优化策略与实战解析

本文深入解析了BQ4050电池管理芯片中Protections参数的优化策略与实战方法。针对电压、电流、温度等核心保护功能,详细阐述了如何根据具体电芯特性、负载场景和环境因素,精细调整CUV、COV、OCC/OCD等阈值与延时,以在确保电池绝对安全的前提下,实现极致的用户体验与系统可靠性。

rgv234567的博客 481

Android——编译体系中的 Copy

http://www.2cto.com/kf/201410/347837.html 对andriod系统层进行开发,或者进行移植时,时常需要添加文件到编译体系中,在最终的编译中复制到out中,最后打包成镜像,这里总结一下Copy File 方法,这里以我的 android 4.2.1为例.   一.PRODUCT_COPY_FILES : 这个变量就是用来标记Copy操作的,比

shuwu 1425

STM32F103 串口DMA + 空闲中断 实现不定长数据收发

文章目录1. 空闲中断1.1 uart_dma.c1.2 uart_dma.h1.3 main.c1.4 stm32f10x_it.c1.5 效果演示1.6 知识补充1.6.1 外设的基地址     DMA(Direct Memory Access,直接存储器访问) 是所有现代电脑的重要特色,它允许不同速度的硬件装置来沟通,而不需要依赖于 CPU 的大量中断负载。否则,CPU 需要从来源把每一片段的资料复制到暂存器,然后把它们再次写回到新的地方。在这个时间中,CPU

夏夜晚风_的博客 3万+

【RandLA-Net实战】从零构建隧道点云数据集并训练大场景语义分割模型

本文详细介绍了如何使用RandLA-Net构建隧道点云数据集并进行大场景语义分割模型训练。从数据采集、标注到模型训练与优化,提供了完整的实战指南,特别针对隧道场景的特殊挑战提出了解决方案。通过实际案例展示了RandLA-Net在处理大场景点云数据时的高效性和准确性,为隧道巡检等工程应用提供了可靠的技术支持。

weixin_30485379的博客 116

Android PRODUCT_COPY_FILES 自动拷贝文件

/********************************************************************** * Android PRODUCT_COPY_FILES 自动拷贝文件 * 说明: * 本文主要记录如何向Android系统中自动添加自己的文件,主要是考虑到 * 后续需要添加一些自动化脚本,不可能每次都自己...

weixin_33963594的博客 1049

国科大学习资料--VLSI测试与可测试设计--2020期末考试试题

国科大学习资料–VLSI测试与可测试设计–2020期末考试试题 国科大学习资料–VLSI测试与可测试设计–2020期末考试试题 国科大学习资料–VLSI测试与可测试设计–2020期末考试试题 一、概念题 1简述可测试性测度与两个主要的测度指标的含义; 2以March C-算法为例,说明March算法的构成,以及March C-算法的故障覆盖率; 3“效果-原因”诊断法和“原因效果诊断法”的不同; 4列举四条扫描设计时出现的问 题及解决办法; 5最少写出1149.1与1500的五点不同; = = = = =

无名何许人的博客 1150

curl在android服务器上编译,Android curl的上载编译和使用

mm执行编译:============================================PLATFORM_VERSION_CODENAME=RELPLATFORM_VERSION=4.0.3TARGET_PRODUCT=fullTARGET_BUILD_VARIANT=engTARGET_BUILD_TYPE=releaseTARGET_BUILD_APPS=TARGET_ARCH=...

weixin_35621029的博客 314

大数据预测分析:精准把握市场趋势

传统市场预测多依赖经验判断(比如“去年卖了1000件,今年加20%”)或小数据统计(比如用近6个月的销量做线性回归)。而大数据预测分析是:利用海量结构化+非结构化数据(销售、用户、社交媒体、天气等),通过机器学习/深度学习模型,挖掘数据中的关联关系与趋势规律,实现对未来市场走势的精准预测。更全面:覆盖内部(企业数据)+外部(行业、环境数据)的全维度数据;更精准:用算法替代人工,避免主观偏差;更实时:支持分钟级/小时级的实时预测(比如直播带货的销量预测)。错误做法。

AI智能探索者的博客 1025

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

android编译

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33963189的博客 102

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

预制第三方APK, 库的方法

如何在android固件系统预制第三方APK? 一. 首先需要单独提取其lib,使用PRODUCT_COPY_FILES宏拷贝到/system/lib下 二. 拷贝APK到指定系统APK目录/system/app(或者/system/priv-app), 拷贝的方法如下: 建立Android.mk, 写入如下的内容 方法一: LOCAL_PATH := $(call my-dir

leo.wang 技术专栏 1653

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

Android编译系统参考手册

build/core/Makefile.mk 在main.mk里定义了许多目标,而Makefile定义了各个目标的生成规则 CL_RED 编译输出用的颜色,类似的还有   CL_GRN  CL_YLW  CL_BLU  CL_MAG CL_CYN CL_RST CL_RED表示用echo输出时使用红色作为前景色 FILE_NAME_TAG 输出的文件名的tag,

chongyang198999的专栏 3654

preload & preinstall

把apk 或binary可运行文件安装到系统(system.img)中  方法一: ################################################################ include $(CLEAR_VARS) ALL_PRE

jackie_gnu的专栏 876

Android curl的下载编译和使用

          mm执行编译: ============================================ PLATFORM_VERSION_CODENAME=REL PLATFORM_VERSION=4.0.3 TARGET_PRODUCT=full TARGET_BUILD_VARIANT=eng TARGET_BUILD_TYPE=release T...

北门锁钥 578
上一篇: Ubuntu——修正LibreOffice中文乱码以及eclipse提示框颜色
下一篇: Android—— ubuntu下【CTS】测试TV真机
南丶烟
博客等级 码龄14年 569粉丝 98原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值