Create your own File Templates in Android Studio

You already know that you can make templates for code snippets in Android Studio. You can do same thing for whole files as well. And you probably use file templates even if you didn‘t yet created your own.
Everytime you create new file using New menu, you are creating files based on file templates.


When you select probably most used option – new Java file – file is created based on file template. Something like this:

 package com.zdenekskrobak.testproject;
/**
 * Created by zskro on 26.12.2017.
 */
public class Test {
}

How does file template look like? You can check them all under Edit file Templates… option.

Template for new Java file that is created after filling Create New Class dialog looks like this:

#if (${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end

#if (${IMPORT_BLOCK} != "")${IMPORT_BLOCK}
#end
#parse("File Header.java")

#if (${VISIBILITY} == "PUBLIC")public #end #if (${ABSTRACT} == "TRUE")abstract #end #if (${FINAL} == "TRUE")final #end class ${NAME} #if (${SUPERCLASS} != "")extends ${SUPERCLASS} #end #if (${INTERFACES} != "")implements ${INTERFACES} #end {
}

So what does this all means? Good thing is that description tells you lot about template. File template is similar to live template.There is text and variable placeholders (between ${}. Some are predefined (e.g. PACKAGE_NAME, USER), for others you will be prompted in dialog when template is applied.

But… template looks nothing like final file. Where is this Created by comment? It is entered there by command #parse(“File Header.java”) from file File header that you can find under Includes tab. It content is:

/**
 * Created by ${USER} on ${DATE}.
 */

So you can create new Includes files and reuse them in many file templates without repeating yourself.

Let’s look at few more examples of built-in templatest get inspiration for your own file templates.

This is Android Activity:

package ${PACKAGE_NAME};

import android.app.Activity;
import android.os.Bundle;

#parse("File Header.java")
public class ${NAME} extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
}

And this is Android layout resource file:

<?xml version="1.0" encoding="utf-8"?>
<${ROOT_TAG} xmlns:android="http://schemas.android.com/apk/res/android"
             android:layout_width="${LAYOUT_WIDTH}"
             android:layout_height="${LAYOUT_HEIGHT}">

</${ROOT_TAG}>

You can see that you are asked for some variables in dialog but dialog asks you for Name, not NAME or Interface(s), not INTERFACES. Also File templates menu doesn’t include all options offered by New menu. Where do these values come from?

Go to your Android studio install path\plugins\android\lib\templates. Inside are various templates used by Android Studio not just for new file templates but also for whole new projects. Let’s ignore customizing creation of new project for now and look at folders activities and others.

For example in folder activities/Empty activity you can find configuration files for generated empty activity. This is content of template.xml.

<?xml version="1.0"?>
<template description="Creates a new empty activity" minBuildApi="14" minApi="9" name="Empty Activity" revision="5" format="5"><category value="Activity"/><formfactor value="Mobile"/><parameter name="Instant App URL Host" help="The domain to use in the Instant App route for this activity" visibility="isInstantApp!false" default="instantapp.example.com" suggest="${companyDomain}" type="string" id="instantAppActivityHost"/><parameter name="Instant App URL Route Type" help="The type of route to use in the Instant App route for this activity" visibility="isInstantApp!false" default="pathPattern" type="enum" id="instantAppActivityRouteType"><option id="path">Path</option><option id="pathPrefix">Path Prefix</option><option id="pathPattern">Path Pattern</option></parameter><parameter name="Instant App URL Route" help="The route to use in the Instant App route for this activity" visibility="isInstantApp!false" default="/.*" type="string" id="instantAppActivityRoute"/><parameter name="Activity Name" help="The name of the activity class to create" default="MainActivity" suggest="${layoutToActivity(layoutName)}" type="string" id="activityClass" constraints="class|unique|nonempty"/><parameter name="Generate Layout File" help="If true, a layout file will be generated" default="true" type="boolean" id="generateLayout"/><parameter name="Layout Name" help="The name of the layout to create for the activity" visibility="generateLayout" default="activity_main" suggest="${activityToLayout(activityClass)}" type="string" id="layoutName" constraints="layout|unique|nonempty"/><parameter name="Launcher Activity" help="If true, this activity will have a CATEGORY_LAUNCHER intent filter, making it visible in the launcher" default="false" type="boolean" id="isLauncher"/><parameter name="Backwards Compatibility (AppCompat)" help="If false, this activity base class will be Activity instead of AppCompatActivity" default="true" type="boolean" id="backwardsCompatibility"/><parameter name="Package name" default="com.mycompany.myapp" type="string" id="packageName" constraints="package"/>
<!-- 128x128 thumbnails relative to template.xml -->
<thumbs>
<!-- default thumbnail is required -->
<thumb>template_blank_activity.png</thumb></thumbs><globals file="globals.xml.ftl"/><execute file="recipe.xml.ftl"/></template>

There are multiple files used to generate all required classes, imports, activity entry inside Android Manifest etc. Quite complicated stuff. I won‘t dive into it, you got some basics for your explorations now:)
But this doesn‘t answer our question where texts for constant inside file templates such as Name are defined. And I don‘t know at the moment. If you find out, please let me know. For now, just accept filling CONSTANTS inside menu. Actually, it is not clear to me where New file dialog itself comes from. However, you can still customize it or create your own file templates.

Let’s try to edit default Java class template.

 
#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME};#end

#parse("File Header.java")
/**
* Purpose of this class is to ${PURPOSE}
**/

public class ${NAME} {
}

Dialog is still the same but after it is closed, new dialog opens with prompt for PURPOSE. There seems to be however problem with parsed file. If you add new variable inside it, you will not be prompted for it’s value. Let me know if you know way around this.