How to create a group of File Templates in Android Studio – Part 3

Update – 24 May 2021: The solution described in this blog post is now outdated – yay! See the official solution from IntelliJ. This works in Android Studio Artic Fox and above – https://www.jetbrains.com/help/idea/templates-with-multiple-files.html

For historical purposes – I’ve left the original post below.

————————–

In the previous two posts, we looked at creating custom live templates and file templates. I received a question on twitter once I posted the file template tutorial:

The following slides were shared with me from Tomás Ruiz-López. I thought I would share my findings thanks to the slides. Android Studio Templates use Freemarker for template definitions. In this post, we will look at creating a set of file templates that can achieve similar results to the default ones in Android Studio.

How to create a group of file templates

In this example, we are going to look at how to create a custom group of file templates for creating MVP functionality. We need to create a Presenter, an Activity and a Contract that defines the interfaces between the two.

  1. Navigate to the location of the templates folder :
  2. {ANDROID_STUDIO_LOCATION}/plugins/android/lib/templates/other/

    On MacOS, this folder was the following:

    /Applications/Android Studio.app/Contents/plugins/android/lib/templates/other/

    Create a folder in the location of your android studio installation with the name of your template – for example MVP Template Activity .

  3. Define the following files & folder in the folder that you have just created:
    • template.xml  – This will contain information about the template (Name, minSdkVersion, etc)
    • recipe.xml.ftl  – This will contain instructions explaining how to create the template, including what variables to ask the user for and what should be done with those variables.
    • globals.xml.ftl  – This defines global variables
    • root/  folder – this will contain the template code.
  4. In the template.xml place the following xml, substituted with your information about your app.
    <template format="4"
            revision="1"
            name="MVP Template Activity"
            description="Creates a new MVP classes - Presenter, View and Contract between the two">
    
        <category value="Other"/>
    
        <parameter id="className"
            name="Functionality Name"
            type="string"
            constraints="class|unique|nonempty"
            default="MvpFunction"
            help="The name of the functionality that requires MVP views"/>
    
        <globals file="globals.xml.ftl" />
        <execute file="recipe.xml.ftl" />
    
    </template>
    

    This file contains all the parameters that should be asked for from the user. In this case, I am asking the user for a name for the MVP functionality that we will be creating.

  5. In the recipe.xml.ftl you define exactly how the recipe should run, what parameters should be requested from the user (the types of parameters too) and the order in which to instantiate them.
    <?xml version="1.0"?>
    <recipe>
    
        <instantiate from="src/app_package/Contract.java.ftl"
                       to="${escapeXmlAttribute(srcOut)}/${className}Contract.java" />
        <instantiate from="src/app_package/MvpViewActivity.java.ftl"
                       to="${escapeXmlAttribute(srcOut)}/${className}Activity.java" />
        <instantiate from="src/app_package/Presenter.java.ftl"
                       to="${escapeXmlAttribute(srcOut)}/${className}Presenter.java" />
    
    
        <open file="${srcOut}/${className}Presenter.java"/>
    </recipe>

    We are now specifying the different files that are created, and where to substitute the name of the output file. We also specify which file should be opened at the end.

  6. In the globals.xml.ftl place the following:
    <?xml version="1.0"?>
    <globals>
     <global id="resOut" value="${resDir}" />
     <global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
    </globals>
  7. Then in the root folder, create the following folder structure:
    • root/src/app_package/

      In this app_package  folder, you can then create the template files that need to be created when using this template. For my example, I have the following files in the app_package  folder:

      • Contract.java.ftl
      • MvpViewActivity.java.ftl
      • Presenter.java.ftl
package ${packageName};

import com.example.android.presentation.base.MvpPresenter;
import com.example.presentation.base.MvpView;

public interface ${className}Contract{
    
    interface View extends MvpView {

    }

    interface Presenter extends MvpPresenter<View> {

    }
}
package ${packageName};

import com.example.android.presentation.base.*;
public class ${className}Activity extends BaseActivity implements ${className}Contract.View {

    ${classname}Contract.Presenter presenter;
    
    @Override
    protected void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        presenter = new ${className}Presenter();
        presenter.attachView(this);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.detachView();
    }
}
package ${packageName};

import com.example.android.presentation.base.*;

public class ${className}Presenter extends BasePresenter<${className}Contract.View> implements ${className}Contract.Presenter{
    
}
  1. To use it, you might need to restart Android Studio. Once restarted, right click on a package that you want to create the template in and select it from the “New” menu, as below:File Template Groups

You will then be prompted to fill in the variables that you asked for in the template.xml

Group File Templates - Custom variables.

It will then generate all the classes required for new MVP functionality. I found that I was often creating the same kind of classes and having to look up how to link the presenter and activity to one another. By implementing it as a template, the whole team can use it, which will ensure standardisation and an easy way of creating new screens or classes.

What other use cases can you think of for groups of file templates?

If you are looking for a sample usage of File Templates, you can see the github repo here which contains the folder for the template that I use.

Known Issue:

When upgrading Android Studio, and you have custom groups of file templates in the installation area specified above, Studio will say you have conflicts in the area that need to be deleted. Unfortunately you will have to remove them, and then place them in the same folder after the upgrade. Check out this feature request here.

Links:


Comments

9 responses to “How to create a group of File Templates in Android Studio – Part 3”

  1. Макс Литучий avatar
    Макс Литучий

    It does not work for me in Android Studio 2.2 preview 3. Can you share the whole folder (Mvp Template Template), please?

  2. Mateus Brandão avatar
    Mateus Brandão

    Thanks for the great Article! Although i guess you forgot to add the “globals.xml.ftl” file to the folder. I only managed to get it working after copying a globals from other folder in the same directory.

  3. Hi Mateus,
    Thanks for spotting that, I have updated the blog post now to reflect that file too.

  4. Hi,
    I have created a project on Github including the full folder for my template:
    https://github.com/riggaroo/android-studio-group-templates-mvp

    I have also updated the blog post to include globals.xml.ftl file which was missing before which might have caused an issue.

  5. fangzhzh avatar
    fangzhzh

    Hi Rebecca, if I want create layout as well, let say ${className}_layout.xml, how can I do it?

  6. Макс Литучий avatar
    Макс Литучий

    Thank you

  7. Hi,
    Yes that is also possible.
    In the root folder, create a folder called “res”, then a “layout” folder, then the name of the layout file : “fragment_layout.xml.ftl”
    Then in your recipe.xml.ftl, just add the following:

    You can dive into the default Android templates that are found in the same folder that you would place your custom one in. If you look into the following folder:
    /{ANDROID_STUDIO_INSTALLATION_PATH}/Contents/plugins/android/lib/templates/other/BlankFragment – this is an example template that creates an xml file.

  8. fangzhzh avatar
    fangzhzh

    Thank you. I found it.

    It’s so fun.

  9. fangzhzh avatar
    fangzhzh

    Hi Rebecca, I tried google for a while, but can’t find the answer.
    My question is Can I get my username time time stamp when I create the files.
    So in my generated files, I can have these lines:


    /**
    * @author ubuntu
    * @datetime 14 Jan 2015, 10:05 AM
    */