private String generateClass(String pkgName, String className) {
        TypeSpec.Builder subClass =
                TypeSpec
                        .classBuilder(className)
                        .addModifiers(FINAL, PUBLIC);

        ClassName IXposedHookZygoteInit = ClassName.get("github.tornaco.android.thanos.services.xposed", "IPackageLoaded");
        ClassName IXposedHookLoadPackage = ClassName.get("github.tornaco.android.thanos.services.xposed", "ISystemServerLoaded");
        // Lists.
        ClassName listClazz = ClassName.get("java.util", "List");
        TypeName listOfIXposedHookZygoteInit = ParameterizedTypeName.get(listClazz, IXposedHookZygoteInit);
        TypeName listOfIXposedHookLoadPackage = ParameterizedTypeName.get(listClazz, IXposedHookLoadPackage);

        // Maps.
        ClassName mapClazz = ClassName.get("java.util", "Map");
        ClassName intClazz = ClassName.get("java.lang", "Integer");
        TypeName mapOfIXposedHookZygoteInit = ParameterizedTypeName.get(mapClazz, intClazz, listOfIXposedHookZygoteInit);
        TypeName mapOfIXposedHookLoadPackage = ParameterizedTypeName.get(mapClazz, intClazz, listOfIXposedHookLoadPackage);

        // All sdk.
        int[] allSdkVersion = XposedHook.SdkVersions.ALL;
        for (int sdkVersion : allSdkVersion) {
            subClass.addField(FieldSpec
                    .builder(listOfIXposedHookZygoteInit, "sIXposedHookZygoteInits" + sdkVersion, STATIC, PRIVATE, FINAL)
                    .initializer(CodeBlock.of("new $T<>()", ArrayList.class))
                    .addJavadoc("IXposedHookZygoteInits of sdk version: " + sdkVersion)
                    .build());
            subClass.addField(FieldSpec
                    .builder(listOfIXposedHookLoadPackage, "sIXposedHookLoadPackages" + sdkVersion, STATIC, PRIVATE, FINAL)
                    .initializer(CodeBlock.of("new $T<>()", ArrayList.class))
                    .addJavadoc("IXposedHookLoadPackages of sdk version: " + sdkVersion)
                    .build());
        }

        // Maps for sdks.
        subClass.addField(FieldSpec
                .builder(mapOfIXposedHookZygoteInit, "sIXposedHookZygoteInitsMap", STATIC, PRIVATE, FINAL)
                .initializer(CodeBlock.of("new $T<>()", HashMap.class))
                .addJavadoc("IXposedHookZygoteInits mapping")
                .build());
        subClass.addField(FieldSpec
                .builder(mapOfIXposedHookLoadPackage, "sIXposedHookLoadPackageMap", STATIC, PRIVATE, FINAL)
                .initializer(CodeBlock.of("new $T<>()", HashMap.class))
                .addJavadoc("IXposedHookLoadPackages mapping")
                .build());

        // initXposedHookInfos
        MethodSpec.Builder initXposedHookInfosMethodBuilder = MethodSpec.methodBuilder("initXposedHookInfos").addModifiers(PRIVATE, STATIC);

        for (XposedHookInfo info : hooks) {
            int[] currentHookVersions = info.getTargetSdkVersion();
            for (int currentHookVersion : currentHookVersions) {
                initXposedHookInfosMethodBuilder.addStatement(
                        "try {"
                                + "sIXposedHookZygoteInits"
                                + currentHookVersion
                                + ".add(new " +
                                info.getClassName() +
                                "());"
                                + "} catch(Throwable e) {throw new RuntimeException(e);}");

                initXposedHookInfosMethodBuilder.addStatement(
                        "try {"
                                + "sIXposedHookLoadPackages"
                                + currentHookVersion
                                + ".add(new " +
                                info.getClassName() +
                                "());"
                                + "} catch(Throwable e) {throw new RuntimeException(e);}");
            }
        }

        // Mapping.
        for (int sdkVersion : allSdkVersion) {
            initXposedHookInfosMethodBuilder.addComment("Adding to maps.");
            initXposedHookInfosMethodBuilder.addStatement("sIXposedHookZygoteInitsMap.put(" +
                    sdkVersion
                    + ", sIXposedHookZygoteInits" +
                    sdkVersion
                    + ")");
            initXposedHookInfosMethodBuilder.addStatement("sIXposedHookLoadPackageMap.put(" +
                    sdkVersion
                    + ", sIXposedHookLoadPackages" +
                    sdkVersion
                    + ")");
        }
        subClass.addMethod(initXposedHookInfosMethodBuilder.build());

        // Static
        subClass.addStaticBlock(CodeBlock.of(
                "initXposedHookInfos();\n"
        ));

        // Getter for IXposedHookZygoteInit
        subClass.addMethod(MethodSpec.methodBuilder("getXposedHookZygoteInitForSdk")
                .addJavadoc("Getter for IXposedHookZygoteInit")
                .returns(listOfIXposedHookZygoteInit)
                .addParameter(ParameterSpec.builder(TypeName.INT, "sdkVersion", FINAL).build())
                .addStatement("return sIXposedHookZygoteInitsMap.get(sdkVersion)")
                .addModifiers(PUBLIC, STATIC).build());

        // Getter for IXposedHookLoadPackage
        subClass.addMethod(MethodSpec.methodBuilder("getXposedHookLoadPackageForSdk")
                .addJavadoc("Getter for IXposedHookLoadPackage")
                .returns(listOfIXposedHookLoadPackage)
                .addParameter(ParameterSpec.builder(TypeName.INT, "sdkVersion", FINAL).build())
                .addStatement("return sIXposedHookLoadPackageMap.get(sdkVersion)")
                .addModifiers(PUBLIC, STATIC).build());


        JavaFile javaFile = JavaFile.builder(pkgName, subClass.build())
                .addFileComment(SettingsProvider.FILE_COMMENT)
                .skipJavaLangImports(true)
                .build();
        return javaFile.toString();
    }
Created by guohao4 on 2017/9/6.
Email: Tornaco@163.com
android/annotation_processors/xposed_hook_compiler/src/main/java/github/tornaco/permission/compiler/XposedHookCompiler.java