一,原有模板分析
模板存放路径:android-studio\plugins\android\lib\templates,模板包内的文件:
(1).globals.xml.ftl 存放的是一些自定义的和引用的全局变量
<globals>
<global id="manifestOut" value="${manifestDir}" />有manifes文件时需要 <global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />有src类文件需要<global id="resOut" value="${resDir}" />用到res资源需要
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />包
<#include "../common/common_globals.xml.ftl" />引用的全局变量,
</globals>
(2).template.xml(EmptyActivity模板为例)
(3).recipe.xml.ftl
<recipe>
<#if useFragment>
<#include "recipe_fragment.xml.ftl" />
<#else>
<#include "../common/recipe_simple.xml.ftl" />
</#if>
<merge from="root/AndroidManifest.xml.ftl"
to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
<copy from="root/res/drawable-hdpi"
to="${escapeXmlAttribute(resOut)}/drawable-hdpi" />
<merge from="root/${resIn}/values/strings.xml.ftl"
to="${escapeXmlAttribute(resOut)}/values/strings.xml" />
<instantiate from="root/res/xml/device_admin_receiver.xml.ftl"
to="${escapeXmlAttribute(resOut)}/xml/device_admin_receiver.xml" />
<open file="${escapeXmlAttribute(resOut)}/xml/$device_admin_receiver.xml" />
<instantiate from="root/src/app_package/DeviceAdminReceiver.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}.java" />
<open file="${escapeXmlAttribute(srcOut)}/${className}.java" />
</recipe>
- <#if ...>...<#else>
... </#if>: if语法
- #include:引用的文件或资源文件
- copy :从root中copy文件到我们的目标目录,比如我们的模板Activity需要使用一些图标,那么可能就需要使用copy标签将这些图标拷贝到我们的项目对应文件夹。
- merge : 合并的意思,比如将我们使用到的strings.xml合并到我们的项目的stirngs.xml中
- instantiate : 和copy类似,但是可以看到上例试将ftl->java文件的,也就是说中间会通过一个步骤,将ftl中的变量都换成对应的值,那么完整的流程是
ftl->freemarker process -> java
。 - open:在代码生成后,打开指定的文件,比如我们新建一个Activity后,默认就会将该Activity打开。
内部机制:声明变量:global.xml.ftl-----获取参数:template.xml-----模板事件:root目录-----模板变现:recipe.xml.ftl
变现流程:ftl->freemarker process->项目中的代码/资源/文件
二,简单自定义模板:DeviceAdminReceiver
1,copy一份BroadcastReceiver模板命名为DeviceAdminReceiver,(个人喜好使用Notepad++编辑)
2,修改\android-studio\plugins\android\lib\templates\other\BroadcastReceiver.java.ftl,文件名和文件中的BroadcastReceiver替换为DeviceAdminReceiver,\Android\android-studio\plugins\android\lib\templates\other\DeviceAdminReceiver.java.ftl:
package ${packageName};
import android.app.admin.DeviceAdminReceiver;
public class ${className} extends DeviceAdminReceiver {
public ${className}() {
}
//代码
}
3,创建\android-studio\plugins\android\lib\templates\other\DeviceAdminReceiver\root\res\xml文件夹,创建一个管理配置文件device_admin_receiver.xml.ftl:
<?xml version="1.0" encoding="utf-8"?>
<device-admin xmlns:android="http://schemas.android.com/apk/res/android">
<uses-policies>
<limit-password />
<watch-login />
<reset-password />
<force-lock />
<wipe-data />
<expire-password />
<encrypted-storage />
<disable-camera />
</uses-policies>
</device-admin>
4,修改\android-studio\plugins\android\lib\templates\other\DeviceAdminReceiver\root\AndroidManifest.xml.ftl文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application>
<receiver android:name="${relativePackage}.${className}"
android:exported="${isExported?string}"
android:enabled="${isEnabled?string}"
android:label="组件名字"
android:permission="android.permission.BIND_DEVICE_ADMIN" >
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/device_admin_receiver" />
<intent-filter>
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
</manifest>
5,修改globals.xml.ftl文件,这时候我们应该明白增加了哪些内容,分析原来的变量声明,有manifestOut,srcOut,relativePackage,而我们增加使用了res资源文件,相比较于srcOut,我们应该也声明resOut,怎么声明:参考其他模板。得到的globals.xml.ftl为:
<?xml version="1.0"?>
<globals>
<global id="manifestOut" value="${manifestDir}" />
<global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
<global id="resOut" value="${resDir}" />
<global id="relativePackage" value="<#if relativePackage?has_content>${relativePackage}<#else>${packageName}</#if>" />
</globals>
6,修改template.xml文件,参考其他模板和原模板界面显示稍微改动就好了,最简单的只需改个名字就好了,这里除名字外,我修改了两处,
一处增加了类别属性,也为另一个BroadcastReceiver增加了属性,这个效果在上面第四张图可以看到,Other下面增加了个Receiver,Receiver包含两个模板;另一处增加了package块,下面就可以看到效果:
<?xml version="1.0"?>
<template
format="5"
revision="3"
name="DeviceAdminReceiver"
description="Creates a new DeviceAdminReceiver component and adds it to your Android manifest.">
<category value="Receiver" />
<parameter
id="className"
name="Class Name"
type="string"
constraints="class|unique|nonempty"
default="MyDeviceAdminReceiver"
help="The name of the DeviceAdminReceiver component class to create"/>
<parameter
id="isExported"
name="Exported"
type="boolean"
default="true"
help="Whether or not the broadcast receiver can receive messages from sources outside its application" />
<parameter
id="isEnabled"
name="Enabled"
type="boolean"
default="true"
help="Whether or not the broadcast receiver can be instantiated by the system" />
<parameter
id="packageName"
name="Package name"
type="string"
constraints="package"
default="com.mycompany.myapp"/>
<globals file="globals.xml.ftl" />
<execute file="recipe.xml.ftl" />
</template>
7,修改recipe.xml.ftl,仅增加了个xml文件:
<?xml version="1.0"?>
<recipe>
<merge from="root/AndroidManifest.xml.ftl"
to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
<instantiate from="root/res/xml/device_admin_receiver.xml.ftl"
to="${escapeXmlAttribute(resOut)}/xml/device_admin_receiver.xml" />
<open file="${escapeXmlAttribute(resOut)}/xml/$device_admin_receiver.xml" />
<instantiate from="root/src/app_package/DeviceAdminReceiver.java.ftl"
to="${escapeXmlAttribute(srcOut)}/${className}.java" />
<open file="${escapeXmlAttribute(srcOut)}/${className}.java" />
</recipe>
OK,仔细检查下代码,不然使用模板出错了很麻烦的,我的就需要重启android-studio。现在在项目里创建个DeviceAdminReceiver:
嗯,代码就没啥好贴的了,以后使用中再根据需要向模板里面添加功能