📜 ⬆️ ⬇️

Android IDE Template Format


In the process of creating new applications, it is often necessary to write the same type of code and reproduce the time-tested class structures. IDE (in particular, Android Studio) facilitates in many respects the tasks associated with the creation of new components for the application. The list of template tivity is growing with each new version of the SDK Tools. But what if you need to create your own template? For a single file, this is easy, but what if you need to create a template with multiple files? Knowing the capabilities of the IDE, it is quite realizable, because the Activity is created with the markup file, and you can add a fragment to it. However, the description of such functionality was not found, so I had to find a solution for this possibility on my own.

Under the cut I want to tell you about how this feature is implemented in Android Studio.


My first thought was to ask colleagues who use JetBrains products how they solve this problem. The answer was quite simple. To create the class structure, a separate script was written that performed all the necessary actions.
')
Indeed, this was the first decision that came to mind. And it has its advantages, namely, independence from the IDE. However, this is inconvenient, and the issue of compatibility with the IDE remained relevant.

In the source code of the SDK there is a description of the way to solve the problem. Android IDE Template Format .

Having received such a tool, I immediately decided to try it out and I hasten to share this experience.
To create templates using FreeMarker . This is very similar to using PHP and Django templates.



The bottom line is that we have a specific template and form for entering parameters. After entering, the parameters are transferred to the template, and the required class is collected based on this data.

A list of all used templates is located at the following address
android-studio-folder \ plugins \ android \ lib \ templates \

To create your template, add a new directory to the directory activities (or other) with the following list of files


Only the template.xml and recipe.xml files are required.

template.xml


This XML file contains metadata about the template, including the name, description, category, and options that are visible to the user and are available as options in the IDE.

Sample template.xml
<!--    Activity.     format=4,     . --> <template format="4" revision="2" minApi="7" minBuildApi="16" name="Blank Activity" description="Creates a new blank activity, with navigation."> <!--  ;    FreeMarker    (.ftl files)  ${activityName}. --> <parameter id="activityClass" name="Activity Name" type="string" constraints="class|unique|nonempty" suggest="${layoutToActivity(layoutName)}" default="MainActivity" help="The name of the activity class to create." /> <parameter id="layoutName" name="Layout Name" type="string" constraints="layout|unique|nonempty" suggest="${activityToLayout(activityClass)}" default="activity_main" help="The name of the layout to create for the activity" /> <parameter id="navType" name="Navigation Type" type="enum" default="none" help="The type of navigation to use for the activity"> <option id="none">None</option> <option id="tabs" minApi="11">Tabs</option> <option id="pager" minApi="11">Swipe Views</option> <option id="dropdown" minApi="11">Dropdown</option> </parameter> <parameter id="fragmentName" name="Fragment Name" type="string" constraints="class|unique|nonempty" default="MainFragment" visibility="navType != 'none'" help="The name of the fragment class to create" /> <!-- 512x512 PNG . --> <thumbs> <!--  . --> <thumb>template_default.png</thumb> <!--        --> <thumb navType="tabs">template_tabs.png</thumb> <thumb navType="dropdown">template_dropdown.png</thumb> </thumbs> <!--    --> <globals file="globals.xml.ftl" /> <!--  ()      . --> <execute file="recipe.xml.ftl" /> </template> 



Template element
format - the version of the template that this template follows. Must be 4. (well, so here)
revision is an optional parameter. The version of this template (which can be increased by updating the template)
name - the display name of the template.
description - description of the template.
minApi is an optional parameter. The minimum API level is checked for this template. IDE before creating a template will check that minSdkVersion is not lower than this value.

Element parameter
Defines a customizable template parameter.
id - identifier for the variable. Available in a global variable file. If the identifier is Foo, then the parameter value will be available in FreeMarker files as $ {Foo}.
name - the display name of the parameter.
type - the type of the parameter. Available values ​​are string, boolean, enum, and separator.
constraints is optional. Parameter restrictions. Constraints can be combined with |.
Types of restrictions
  • nonempty - the value should not be empty
  • apilevel - indicates API level
  • package - value must be a valid Java package name
  • app_package - the value must be a valid Android app package name
  • module - the value must be a valid module name
  • class - the value must be a valid Java class
  • activity - the value must be the full name of the class Activity
  • layout - the value must be a valid resource layout name
  • drawable - the value must be a valid drawable resource name
  • string - the value must be a valid string name of the resource
  • id - the value must be a valid id name
  • unique - the value must be unique
  • exists - value must exist


suggest - optional. Automatically updated expressions depending on the value of other parameters.
default is optional. The default value for this parameter.
visibility is optional. FreeMarker expression defining component visibility.
help is optional. Hint for this parameter.

Option element
For parameters of type enum, represents the elements to select.

id - the parameter value is set if this option is selected.
minApi is optional. A minimum API level is required.
[text] - The text displayed when this option is selected.

Thumb element
Shows the thumbnail for the template. Items must be inside the item. The text contained in this element is the path to the thumbnail. If this element has attributes, they will be treated as a selector.
Example:
 <thumbs> <thumb>template.png</thumb> <thumb navType="tabs">template_tabs.png</thumb> </thumbs> 

Template_tabs.png will be shown as a thumbnail if tabs is selected in navType.

globals.xml.ftl


The XML file contains global variables for use in FreeMarker working layouts.
Example globals.xml.ftl:
 <globals> <global id="srcOut" value="src/${slashedPackageName(packageName)}" /> <global id="activityNameLower" value="${activityName?lower_case}" /> <global id="activityClass" value="${activityName}Activity" /> </globals> 


recipe.xml.ftl


This XML file contains separate instructions that must be executed when generating code for this template.
For example, you can copy some files or directories (copy instruction), you can create files via FreeMarker (instantiate instruction), and you can ask the IDE to open the file (open instruction).

Note: The name of the instruction file is defined in template.xml. However, by convention, it is better to call it recipe.xml.ftl.
Note: Globals.xml.ftl global variables are available for use in recipe.xml.ftl.
Recipe.xml.ftl example
 <recipe> <#if appCompat?has_content> <dependency mavenUrl="com.android.support:appcompat-v7:+"/> </#if> <merge from="AndroidManifest.xml.ftl" to="${escapeXmlAttribute(manifestDir)}/AndroidManifest.xml" /> <!--   ,   FreeMarker --> <copy from="res/drawable-mdpi" to="${escapeXmlAttribute(resDir)}/res/drawable-mdpi" /> <copy from="res/drawable-hdpi" to="${escapeXmlAttribute(resDir)}/res/drawable-hdpi" /> <copy from="res/drawable-xhdpi" to="${escapeXmlAttribute(resDir)}/res/drawable-xhdpi" /> <copy from="res/drawable-xxhdpi" to="${escapeXmlAttribute(resDir)}/res/drawable-xxhdpi" /> <copy from="res/menu/main.xml" to="${escapeXmlAttribute(resDir)}/res/menu/${activityNameLower}.xml" /> <!--  FreeMarker  merge     --> <merge from="res/values/dimens.xml" to="${escapeXmlAttribute(resDir)}/res/values/dimens.xml" /> <merge from="res/values-large/dimens.xml" to="${escapeXmlAttribute(resDir)}/res/values-large/dimens.xml" /> <merge from="res/values/styles.xml" to="${escapeXmlAttribute(resDir)}/res/values/styles.xml" /> <merge from="res/values/strings.xml.ftl" to="${escapeXmlAttribute(resDir)}/res/values/strings.xml" /> <!--     --> <#if navType?contains("pager")> <instantiate from="${escapeXmlAttribute(resDir)}/res/layout/activity_pager.xml.ftl" to="${escapeXmlAttribute(resDir)}/res/layout/activity_${activityNameLower}.xml" /> <#elseif navType == "tabs" || navType == "dropdown"> <copy from="${escapeXmlAttribute(resDir)}/res/layout/activity_fragment_container.xml" to="${escapeXmlAttribute(resDir)}/res/layout/activity_${activityNameLower}.xml" /> <#else> <copy from="${escapeXmlAttribute(resDir)}/res/layout/activity_simple.xml" to="${escapeXmlAttribute(resDir)}/res/layout/activity_${activityNameLower}.xml" /> </#if> <!--  Activity  --> <#if navType == "none"> <instantiate from="src/app_package/SimpleActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" /> <#elseif navType == "pager"> <instantiate from="src/app_package/PagerActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" /> <#elseif navType == "tabs"> <instantiate from="src/app_package/TabsActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" /> <#elseif navType == "dropdown"> <instantiate from="src/app_package/DropdownActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/${activityClass}.java" /> </#if> <!--    Java class   --> <open file="${escapeXmlAttribute(resDir)}/res/layout/${activityNameLower}.xml" /> <open file="${escapeXmlAttribute(srcOut)}/${activityClass}.java" /> </recipe> 



The instructions support the following methods:

dependency
Indicates that the template needs a library. If not, the IDE will add a dependency to the project.

MavenUrl attribute
Specifying the maven library package. For example, com.android.support:appcompat-v7:+

copy
The only required parameter is the path to the source files to be copied relative to the root / directory. All necessary subdirectories are created automatically, if necessary.
The creation directory defaults to the location of the template relative to the / root folder. There is an optional parameter to specify the path to create the file. Please note that the .ftl extension is automatically removed. For example, the entry /> is correct. This will create a file named strings.xml, not strings.xml.ftl.

instantiate
Same as copy, but for the source file FreeMarker will be launched first.

merge
This instruction will launch FreeMarker for the source file, and then merge the content with an existing file in the project or create a new file. The most common example of using this instruction is adding components to the AndroidManifest.xml file or combining resources such as strings.xml.

open
Opens the file specified in the arguments after the code generation is complete.

mkdir
Checks the existence of the directory specified in the arguments

root /


All template files (resources, Java sources, Android Manifest) should be located in the root / directory
However, instead of placing the source files in src / com / google / ... you can simply use src / app_package /.

Built-in Template Functions


There are several functions that are not included in the FreeMarker functions that can be used.

Here are some of them:

string activityToLayout (string)
Converts the class name of the Activity to a string suitable for use as a resource name. For example, FooActivity will be converted to activity_foo.

string camelCaseToUnderscore (string)
Converts a camel-case string to an underscore string. For example, FooBar will be converted to foo_bar.

string classToResource (string)
Converts the Android class name, for example, FooActivity or FooFragment, to the corresponding resource with the addition of the suffix 'Activity' or 'Fragment'.
Currently recognized:

string layoutToActivity (string)
Converts a suffixed resource to a class string. For example, activity_foo will be translated to the Java class FooActivity.

string slashedPackageName (string)
Converts the full name of the Java package to the corresponding directory path. For example, if the argument is com.example.foo, then the return value will be com / example / foo.

string underscoreToCamelCase (string)
Converts the underscore string to the corresponding camel case line. For example, foo_bar to FooBar.

Built-in Template Parameters


Some options available for FreeMarker expressions and files.

packageName
Project package name, for example, com.example.foo

isNewProject
A Boolean value indicating whether the template is a new project template.

manifestDir
Directory with AndroidManifest.xml.

srcDir
The Java source directory for the project.

resDir
The directory of the root directory of resources (res /) for the project.

For a complete list of functions and parameters, refer to the documentation .

In general, creating your own template is not difficult. Having spent some time on its creation, you can get rid of the routine for creating components and structures in the project.
Use and automate everything that can be automated.

useful links


Documentation
Article on creating your own Google Analytics Activity
Work with FreeMarker

Source: https://habr.com/ru/post/274959/


All Articles