Categories
android studio

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:

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

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

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.

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

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.

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
*/

Comments are closed.