如何通过注解处理器生成Android字符串等资源?含实现示例
实现通过注解自动生成Android字符串资源
我来帮你搞定这个需求——用自定义注解标记方法,让项目编译后自动生成包含对应字符串的strings.xml资源文件。下面是完整的实现步骤:
1. 定义自定义注解@StringKey
首先创建一个注解类,用来标记需要生成字符串资源的方法:
import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.SOURCE) // 仅在编译阶段生效 @Target(ElementType.METHOD) // 仅用于标记方法 public @interface StringKey { String value(); // 用来指定生成的字符串资源名称 }
2. 编写注解处理器(核心逻辑)
接下来编写注解处理器,它会在编译时扫描所有带@StringKey的方法,自动生成资源文件。创建一个继承AbstractProcessor的类:
import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.Element; import javax.lang.model.element.TypeElement; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.Set; @SupportedAnnotationTypes("com.yourpackage.StringKey") // 替换成你的注解全类名 @SupportedSourceVersion(SourceVersion.RELEASE_8) public class StringKeyProcessor extends AbstractProcessor { @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { // 获取所有标记了@StringKey的元素(这里是方法) Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(StringKey.class); if (elements.isEmpty()) { return false; } // 生成资源文件的路径,适配Android项目结构 String resDir = processingEnv.getOptions().get("android.resourceOutputDir"); if (resDir == null) { resDir = "src/main/res/values"; // 默认路径,可根据实际调整 } File valuesDir = new File(resDir); if (!valuesDir.exists()) { valuesDir.mkdirs(); } File stringsFile = new File(valuesDir, "generated_strings.xml"); // 写入资源文件内容 try (FileWriter writer = new FileWriter(stringsFile)) { writer.write("<resources>\n"); writer.write(" <!-- Automatically generated file. DO NOT MODIFY -->\n"); writer.write(" <!-- Values from product flavor: prod -->\n"); for (Element element : elements) { StringKey annotation = element.getAnnotation(StringKey.class); String key = annotation.value(); // 写入字符串资源,值和key一致(你可以根据需求修改值) writer.write(String.format(" <string name=\"%s\" translatable=\"false\">%s</string>\n", key, key)); } writer.write("</resources>"); } catch (IOException e) { processingEnv.getMessager().printError("Failed to generate strings.xml: " + e.getMessage()); } return true; } }
3. 配置项目(Android Gradle)
要让注解处理器生效,需要在模块的build.gradle(或build.gradle.kts)中进行配置:
android { // ...其他配置 defaultConfig { // ...其他配置 javaCompileOptions { annotationProcessorOptions { arguments = ["android.resourceOutputDir": "${project.buildDir}/intermediates/merged_resources/${variant.name}/out"] } } } } dependencies { // 依赖自定义注解 implementation project(":your-annotation-module") // 如果注解在单独模块 // 依赖注解处理器 annotationProcessor project(":your-processor-module") // 如果处理器在单独模块 // 或者如果是同一模块,直接用annotationProcessor依赖当前模块(不推荐,建议拆分模块) }
注意:推荐把注解和注解处理器拆分到单独的模块,避免主模块引入不必要的依赖。
4. 验证效果
现在用你的示例代码标记方法:
@StringKey("style1") void applyStyle1() { // ...方法逻辑 }
编译项目后,会在指定的资源目录下生成generated_strings.xml,内容如下:
<resources> <!-- Automatically generated file. DO NOT MODIFY --> <!-- Values from product flavor: prod --> <string name="style1" translatable="false">style1</string> </resources>
这样就完全实现了你想要的效果,生成的资源值可以根据需求在处理器中修改,比如从其他配置读取,这里默认和key保持一致。
内容的提问来源于stack exchange,提问作者georgeci
相关产品推荐
相关产品推荐

