Custom Projects In Android Studio
Written by Ian Elliot   
Thursday, 16 January 2014
Article Index
Custom Projects In Android Studio
Using a Recipe

Recipe.xml.ftl

The Recipe file does all of the work setting up the project, but it does most of this by copying and expanding directories which exist in the template root directory. 

One key command that you are likely to use is copy, which copies a directory and all its subdirectories from the template root to the project. The command instantiate does the same job as copy, but it expands any FreeMarker tags within the files.  The final command is merge, which as you can guess merges the content of a source file in the template root with a project file.

The Recipe file starts out by loading compatibility libraries if they are needed:

 

<?xml version="1.0"?>
<recipe>
 <#if appCompat?has_content>
  <dependency
    mavenUrl="com.android.support:appcompat-v7:+"/>  </#if>
 <#if !appCompat?has_content &&
                       hasViewPager?has_content>
  <dependency
    mavenUrl="com.android.support:support-v13:+"/>
 </#if>
 <#if !appCompat?has_content >
  <dependency
     mavenUrl="com.android.support:support-v4:+"/>
 </#if>

 

You might as well leave these lines in your own Recipe file. 

Next we need to create the manifest:

<merge from="AndroidManifest.xml.ftl"
 to="${escapeXmlAttribute(manifestOut)}/
       AndroidManifest.xml"
/>

The template manifest is stored in the root:

 

<manifest xmlns:android=
  "http://schemas.android.com/apk/res/android" >
 <application>
  <activity android:name=
                 "${packageName}.${activityClass}"
   <#if isNewProject>
     android:label="@string/app_name"
   <#else>
     android:label="@string/title_${
          activityToLayout(activityClass)}"
   </#if>
   <#if buildApi gte 16 &&
        parentActivityClass != "">
      android:parentActivityName=
           "${parentActivityClass}"
   </#if>
  >
  <#if parentActivityClass != "">
    <meta-data android:name=
         "android.support.PARENT_ACTIVITY"
         android:value="${parentActivityClass}"
     />
   </#if>
   <#if isLauncher>
    <intent-filter>
     <action android:name=
           "android.intent.action.MAIN" />
     <category android:name=
           "android.intent.category.LAUNCHER" />
    </intent-filter>
   </#if>
  </activity>
 </application>
</manifest>

 When this file is processed it is merged with any existing manifest file in such a way that only the new lines are added. What this means is that when the same template is used to create a new activity within an existing project only the new definition of the activity is added to the existing manifest.

Next we have to merge some resource files:

<merge from="res/values/strings.xml.ftl"
         to="${escapeXmlAttribute(resOut)}/
                         values/strings.xml" />
<merge from="res/values/dimens.xml.ftl"
         to="${escapeXmlAttribute(resOut)}/
                         values/dimens.xml" />
<merge from="res/values-w820dp/dimens.xml"
         to="${escapeXmlAttribute(resOut)}/
                  values-w820dp/dimens.xml" />

As before, the values are merged with any existing files so there is no duplication of definitions. 

The strings.xml file is where we put the "Hello world" message:

<resources>
 <#if !isNewProject>
  <string name=
      "title_${activityToLayout(activityClass)}">
   ${escapeXmlString(activityTitle)}</string>
 </#if>
<string name="hello_world">Hello world!</string>
</resources>

The dimens file just contains some basic layout properties;

<resources>
<!-- Default screen margins,
     per the Android Design guidelines. -->
<dimen name=
   "activity_horizontal_margin">16dp</dimen>
<dimen name=
   "activity_vertical_margin">16dp</dimen>
</resources>

 

If you want to define additional string resources or layout parameters simply add them to the appropriate file. 

Our final task is to create the Java source and the xml layout files and this is just a matter of copying and expanding two template files:

<instantiate from=
  "res/layout/simpleactivity.xml.ftl"
 to="${escapeXmlAttribute(resOut)}/
                   layout/${layoutName}.xml" />
<instantiate from=
   "src/app_package/SimpleActivity.java.ftl"
 to="${escapeXmlAttribute(srcOut)}/
                 ${activityClass}.java" />

 

The layout file template simpleactivity.xml is very simple:

<RelativeLayout xmlns:android=
  "http://schemas.android.com/apk/res/android"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  android:paddingLeft=
           "@dimen/activity_horizontal_margin"
  android:paddingRight=
           "@dimen/activity_horizontal_margin"
  android:paddingTop=
           "@dimen/activity_vertical_margin"
  android:paddingBottom=
           "@dimen/activity_vertical_margin"
  tools:context="${packageName}.${activityClass}">
<TextView
 android:text="@string/hello_world"
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />
</RelativeLayout>

You can modify RelativeLayout to be any sort of container you want and you can remove the "hello world" message if you find it gets in the way. 

The Java template is:

package ${packageName};
import
 <#if appCompat?has_content>
  android.support.v7.app.ActionBarActivity
 <#else>android.app.Activity
 </#if>;
import android.
 <#if appCompat?has_content>support.v7.</#if>
app.ActionBar;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.os.Build;
public class ${activityClass} extends Activity {
 @Override
 protected void onCreate(Bundle savedInstanceState){
 super.onCreate(savedInstanceState);
 setContentView(R.layout.${layoutName});
 }
}

As before, you can modify this to include features you might want, but this the very minimum. 

Finally if you want to open some files in the editor ready for the programmer to start work you can:


<open file=
 "${escapeXmlAttribute(srcOut)}/
            ${activityClass}.java" />
</recipe>

This opens the jave souce code ready to work. 

This ends the recipe file and the entire template. 

Where Next

It would be wise not to spend too much time and effort on hand crafted templates as Android Studio is still changing, but you can see that simple templates are easy enough. If you study the documentation for FreeMarker and use the existing templates as examples, you should be able to cope until there is full documentation. 

The template presented here can be downloaded from the CodeBin. Note you have to register with I Programmer to access this.  

It also used in our ongoing series, Adventures with Android Studio

Androidgears

Related Articles:


Android ADT Template Format Document

Android Adventures With Android Studio 

  1. Getting Started With Android Studio
  2. The Activity And The UI
  3. Building The UI and a Calculator App
  4. Lifecycle and State
  5. Basic Controls And Events
  6. Spinners
  7. Pickers

 

 newproject

 

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 

To be informed about new articles on I Programmer, subscribe to the RSS feed, follow us on Google+Twitter, Linkedin or Facebook or sign up for our weekly newsletter.

 

Banner


Disk Drive Dangers - SMART and WMI

Getting access from an application to the hardware is never easy. If you want to know how well your disk drive is performing then there is a way of accessing the SMART data - including the temper [ ... ]



Setting Up Site-To-Site OpenVPN

Setting up a point-to-point VPN is relatively easy but site-to-site is much more complicated involving certificates and more IP addresses than you can count. Find out how to do it using OpenVPN.


Other Projects

 



Last Updated ( Tuesday, 21 January 2014 )