移動(dòng)應(yīng)用開(kāi)發(fā):如何創(chuàng)建自定義Android代碼模板

介紹

這篇教程會(huì)為你展示如何創(chuàng)建屬于你自己的代碼模板。大多數(shù)的Android開(kāi)發(fā)者都至少一次使用過(guò)Android代碼模板來(lái)新建工程。但是你有沒(méi)有嘗試過(guò)創(chuàng)建自己的Android代碼模板?
在這篇教程中,我們將會(huì)為你展示可用于從Android Studio IDE生成包含Google Analytics配置的Android工程模板。

源碼

這里下載源碼

代碼生成過(guò)程圖解

具體創(chuàng)建步驟

要?jiǎng)?chuàng)建自己的模板,請(qǐng)確保:

  1. 你已經(jīng)了解上述代碼生成過(guò)程圖解;
  2. 你有一些關(guān)于FreeMarker的知識(shí);
  3. 你有一些關(guān)于Android IDE模板格式的知識(shí),你可以在這里查看相關(guān)文檔。

第一步:創(chuàng)建Google Analytics應(yīng)用程序文件夾

這是你的模板目錄,在Windows上,${android studio 安裝路徑}/plugins/android/lib/templates/,其他平臺(tái)Linux,Mac OS請(qǐng)自行查找;
在GoogleAnalyticApplication文件夾中創(chuàng)建根文件夾和其他文件,如下所示:


第二步:創(chuàng)建template.xml文件

每個(gè)模板目錄必須包含一個(gè)template.xml文件,這其中包含有關(guān)模板的一些元數(shù)據(jù),包括名稱,描述,類別和用戶可見(jiàn)參數(shù)這些IDE將作為選項(xiàng)呈現(xiàn)給用戶。
文件中還會(huì)在指明FreeMarker處理的recipe文件名稱和全局變量文件,如果除了模板參數(shù)值之外還有全局變量應(yīng)該對(duì)所有FreeMarker處理的文件可見(jiàn)。
Template.xml

<?xml version="1.0"?>
<template
    format="3"
    revision="4"
    name="Google Analytics Application"
    minApi="7"
    minBuildApi="14"
    description="Creates a new application that has already Google Analytics configuration.">
    <category value="Activity" />
    <formfactor value="Mobile" />
    <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="classApplication"
        name="Class extends Application"
        type="string"
        constraints="nonempty|class"
        help="The name of class that extends from Application" />
    <parameter
        constraints="nonempty|string"
        id="googleAnalyticID"
        name="Google Analytic ID"
        type="string"
        help="Id of Google Analytic" />
    <parameter
        id="dispatchPeriod"
        name="Dispatch Period"
        help="Frequency of automatic dispatch in seconds. Defaults to 30 minutes (1800 seconds)."
        type="string"
        default="1800"/>
    <parameter
        id="autoActivityTracking"
        name="Auto Activity Tracking"
        help="If true, views (Activities) will be tracked automatically. false by default."
        type="boolean"
        default="false"/>
    <!-- 128x128 thumbnails relative to template.xml -->
    <thumbs>
        <!-- default thumbnail is required -->
        <thumb>template_google_analytics.png</thumb>
    </thumbs>
    <globals file="globals.xml.ftl" />
    <execute file="recipe.xml.ftl" />
 
</template>

其中的一些參數(shù)比如: activityClass, layoutName, classApplication, googleAnalyticID, dispatchPeriod, autoActivityTracking,將在創(chuàng)建項(xiàng)目時(shí)顯示在彈出窗口中。

第三步:創(chuàng)建globals.xml.ftl文件

這是一個(gè)可選的文件,里面包含全局變量的定義,用于此模板的所有FreeMarker處理任務(wù)。
globals.xml.ftl

<?xml version="1.0"?>
<globals>
    <global id="manifestOut" value="${manifestDir}" />    
    <global id="srcOut" value="${srcDir}/${slashedPackageName(packageName)}" />
    <global id="resOut" value="${resDir}" />    
</globals>

第四步:在root文件夾中創(chuàng)建相關(guān)文件和文件夾

root文件夾中包含模板源代碼

1.創(chuàng)建AndroidManifest.xml.ftl
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="${packageName}">
    <application
        android:name="${packageName}.${classApplication}"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <meta-data
            android:name="com.google.android.gms.version"
            android:value="@integer/google_play_services_version" />
        <meta-data
            android:name="com.google.android.gms.analytics.globalConfigResource"
            android:resource="@xml/analytics_global_config" />
        <activity
            android:name=".activities.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>

其中的packageName,classApplication是在template.xml文件中定義的。

2.創(chuàng)建Application.java.ftl文件
package ${packageName};
import android.app.Application;
import com.google.android.gms.analytics.GoogleAnalytics;
import com.google.android.gms.analytics.Tracker;
/**
 * Created by TungDX on 5/29/2015.
 */
public class ${classApplication} extends Application {
    private static GoogleAnalytics analytics;
    private static Tracker tracker;
    @Override
    public void onCreate() {
       analytics = GoogleAnalytics.getInstance(this);
       tracker = analytics.newTracker("${googleAnalyticID}");
    }
    public static GoogleAnalytics getGoogleAnalytics() {
       return analytics;
    }
    public static Tracker getTracker() {
        return tracker;
    }
}

其中的packageName,googleAnalyticID是在template.xml文件中定義的。

3.創(chuàng)建MainActivity.java.ftl文件
package ${packageName}.activities;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import ${packageName}.${classApplication};
import ${packageName}.R;
public class MainActivity extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    @Override
    protected void onStart() {
        super.onStart();
        ${classApplication}.getGoogleAnalytics().reportActivityStart(this);
    }
    @Override
    protected void onStop() {
        super.onStop();
        ${classApplication}.getGoogleAnalytics().reportActivityStop(this);
    }
}

其中的packageName,classApplication是在template.xml文件中定義的。

4.創(chuàng)建activity_main.xml.ftl文件
<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">
    <TextView
        android:text="@string/ready"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
</RelativeLayout>
5.創(chuàng)建strings.xml.ftl文件
<resources>
    <#if !isNewProject>
    <string name="title_${activityToLayout(activityClass)}">${escapeXmlString(activityTitle)}</string>
    </#if>
    <string name="ready">Google Analytic is ready!</string>
</resources>
6.創(chuàng)建dimens.xml文件
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>
7.創(chuàng)建recipe.xml.ftl文件

recipe.xml文件中包含了從該模板生成代碼時(shí)應(yīng)執(zhí)行的各個(gè)命令。比如,你可以復(fù)制某些文件或目錄,或者通過(guò)FreeMarker運(yùn)行源文件,并要求IDE在代碼生成后打開(kāi)一個(gè)文件。

<?xml version="1.0"?>
<recipe>
<dependency mavenUrl="com.android.support:support-v4:${targetApi}.+" />
<dependency mavenUrl="com.android.support:appcompat-v7:${targetApi}.+"/>
<dependency mavenUrl="com.google.android.gms:play-services:6+" />

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

<instantiate from="src/app_package/Application.java.ftl" to="${escapeXmlAttribute(srcOut)}/${classApplication}.java"/>

<instantiate from="src/app_package/activities/MainActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/activities/${activityClass}.java"/>
 
<instantiate from="res/xml/analytics_global_config.xml.ftl" to="${escapeXmlAttribute(resOut)}/xml/analytics_global_config.xml"/>

<instantiate from="res/layout/activity_main.xml.ftl" to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml"/>

<copy from="res/values/dimens.xml" to="${escapeXmlAttribute(resOut)}/values/dimens.xml"/>

    <merge from="res/values/strings.xml.ftl"to="${escapeXmlAttribute(resOut)}/values/strings.xml" />   
    <open file="${escapeXmlAttribute(srcOut)}/activities/${activityClass}.java" />
    <open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />
</recipe>
8.檢查依賴
9.檢查AndroidManifest.xml.ftl
<instantiate from="AndroidManifest.xml.ftl"          to="${escapeXmlAttribute(manifestOut)}/AndroidManifest.xml" />
10.檢查Application.java.ftl
<instantiate from="src/app_package/Application.java.ftl" to="${escapeXmlAttribute(srcOut)}/${classApplication}.java"/>https://robusttechhouse.com/wp-admin/post.php?post=6937&action=edit&message=10#
11.檢查MainActivity.java.ftl
<instantiate from="src/app_package/activities/MainActivity.java.ftl" to="${escapeXmlAttribute(srcOut)}/activities/${activityClass}.java"/>

12.檢查analytics_global_config.xml.ftl
<instantiate from="res/xml/analytics_global_config.xml.ftl" to="${escapeXmlAttribute(resOut)}/xml/analytics_global_config.xml"/>
13.從模板中生成 activity_main.xml, dimens.xml, strings.xml文件
<instantiate from="res/layout/activity_main.xml.ftl" to="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml"/>
<copy from="res/values/dimens.xml" to="${escapeXmlAttribute(resOut)}/values/dimens.xml"/>
<merge from="res/values/strings.xml.ftl" to="${escapeXmlAttribute(resOut)}/values/strings.xml" />
14.工程創(chuàng)建成功后打開(kāi)對(duì)應(yīng)文件
<open file="${escapeXmlAttribute(srcOut)}/activities/${activityClass}.java" />
<open file="${escapeXmlAttribute(resOut)}/layout/${layoutName}.xml" />

如果你的Android Studio IDE運(yùn)行,請(qǐng)重新啟動(dòng)它看到自己的模板如下圖



如果從模板生成項(xiàng)目時(shí)遇到此錯(cuò)誤:AssertionError: Wrong line separators: ‘…plication;\r\n\r\nimport…’ at offset 29:
請(qǐng)檢查模板中所有文件的行分隔符是否正確,請(qǐng)確保使用正確的行分隔符在對(duì)應(yīng)的的計(jì)算機(jī)的操作系統(tǒng)中。

原文鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容