کانال بله, جهت پشتیبانی و اطلاع رسانی کانال بله, جهت پشتیبانی و اطلاع رسانی
عضویت

کامپایل / Build پروژه های اندرویدی با سیستم Gradle

استفاده از Gradle برای کامپایل پروژه های اندرویدی

فایل های build اپلیکیشن های اندروید

فرایند build پروژه های اندرویدی توسط سیستم کامپایل Gradle مدیریت می شود. زمانی که پروژه ی جدیدی در محیط برنامه نویسی اندروید ایجاد می کنید، به دنبال آن build script (فایل build.gradle) نیز به طور خودکار تولید می شوند. در واقع محیط کاری Android Studio به صورت خودکار runtime و بستر اجرای Gradle را دربرمی گیرد، از این رو احتیاجی به نصب ابزار یا افزونه ی جداگانه وجود ندارد.

سیستم Gradle build طوری طراحی شده که از سناریوهای پیچیده مختلف برای ایجاد اپلیکیشن های اندرویدی پشتیبانی کند:

  • Multi-distribution: وضعیتی که یک اپلیکیشن بایستی برای چندین سرویس گیرنده یا شرکت اختصاصی تنظیم شود.
  • Multi-apk: تولید چندین فایل apk از یک اپلیکیشن جهت سازگاری با انواع دستگاه ها و استفاده ی مجدد از بخش هایی از کد برنامه در این فایل های apk.

همچنین می توانید از یک wrapper script که سیستم Gradle تولید می کند، استفاده نمایید (wrapper script: wrapper script یک اسکریپت است که چندین دستور و اسکریپت که قابلیت اجرا در برنامه ی اصلی را ندارد، در بر می گیرد). این wrapper به شما امکان می دهد تا یک Gradle build را بدون اینکه لازم باشد هیچ ابزار و فایل دیگری نصب کنید، از خط دستور (command line) اجرا نمایید.

زمانی که بر روی دکمه ی run در محیط کاری Android Studio کلیک می کنید، تسک مربوطه ی Gradle راه اندازی شده و اپلیکیشن اجرا می شود.

نکته :

می توانید به ورژن های مختلف افزونه ی Gradle تحت آدرس https://jcenter.bintray.com/com/android/tools/build/gradle/ دسترسی داشته باشید.

پروسه ای که کد برای تبدیل به اپلیکیشن اندروید طی می کند

کامپایلر جاوا فایل های حاوی کدهای جاوا (java source file) را به فایل هایی با پسوند .class تبدیل می کند (فایل هایی که دربردانده ی bytecode ها و کدهای زبان میانی بوده و بر روی JVM اجرا می شود). Android SDK یک ابزار به نام dx دارد که فایل های .class را به فایل هایی با پسوند .dex (فایل های اجرایی Dalvik) تبدیل می کند. تمامی فایل های کلاس اپلیکیشن در فایل اجرایی Dalvik جایگذاری می شوند. در طی این پروسه تبدیل، اطلاعات مازاد موجود در فایل های .class داخل فایل .dex بهینه می شوند. برای مثال، چناچه یک String در چندین فایل .class وجود داشته باشد، فایل .dex تنها یک reference یا اشاره گر به متغیر مزبور را نزد خود نگه می دارد.

فایل های .dex از نظر حجم بسیار سبک تر از فایل های .class متناظر هستند.

فایل .dex و سایر منابع و محتوا همچون image و فایل های XML همگی در قالب یک فایل .apk گنجانده می شوند. این وظیفه را ابزار پکیج بندی منابع و محتوای اپلیکیشن های اندرویدی به نام aapt (Android Asset Packaging Tool) بر عهده دارد.

فایل .apk خروجی، دربردارنده ی تمامی داده های لازم برای اجرای اپلیکیشن اندروید بوده و به راحتی از طریق ابزار adb قابل نصب بر روی دستگاه اندرویدی می باشد.

از ویرایش 5.0 به بعد، Android RunTime به عنوان ابزار بارگذاری و اجرا / runtime تمامی اپلیکیشن های اندرویدی ایفای نقش می کند. ART یک قابلیت است که اپلیکیشن را درست به مجرد درخواست کاربر لود کرده و اجرا می کند. بدین وسیله سرعت اجرای اپلیکیشن به مراتب نسبت به زمانی که از Dalvik استفاده می شد، بالا می رود. در واقع ART از تلفیقی از دو روش کامپایل Ahead of Time (ترجمه ی کد زودتر از درخواست کاربر) و Just-in-Time (ترجمه ی کد به محض درخواست کاربر) استفاده می کند. به هنگام نصب یک اپلیکیشن بر روی دستگاه اندرویدی، کد اپلیکیشن به زبان ماشین ترجمه می شود.

ابزار dex2oat فایل .dex که خروجی مجموعه ابزار اندروید می باشد را تحویل گرفته و آن را به یک فایل (EFL) با فرمت Executable and Linkable تبدیل می کند. این فایل حاوی کد dex، کد کامپایل شده برای سخت افزار و محیط جاوا / native code و meta-data می باشد.

راه اندازی Gradle از خط دستور (command line)

می توانید فایل Gradle build خود را از خط دستور اجرا کنید. برای این منظور، دستور زیر را از پوشه ی اصلی پروژه (main project directory) اجرا نمایید. لازم است Gradle بر روی دستگاه مربوطه نصب شده باشد و یا کد دربرگیرنده ی Gradle (Gradle wrapper gradlew) را برای اجرای build بکار ببرید. در صورت لزوم wrapper خود به صورت خودکار سیستم Gradle را دانلود می کند. در زیر لیست task های مهم Android Gradle را با شرح کاربرد مشاهده می شود:

دستور
شرح کاربرد
./gradlew build
پروژه را build و کامپایل نموده و هر دو تسک assemble و check را اجرا می کند.
./gradlew clean build
پروژه را کامل از صفر کامپایل و build می کند.
./gradlew clean build
پروژه را از صفر build و کامپایل می کند.
./gradlew test
تست ها را اجرا می کند.
./gradlew connectedAndroidTest
تست های مبتنی بر instrumentation را اجرا می کند.

جهت مشاهده ی تمامی task های موجود، دستور gradle wrapper را فراخوانی کنید.

gradle build
# alternatively speedup second grandle build by holding it in memory
# gradle build --daemon

با اجرای این دستور، یک پوشه ی build برای قرارگیری خروجی Gradle build ایجاد می شود. به صورت پیش فرض، Gradle build دو فایل با پسوند .apk در پوشه ی build/outputs/apk ایجاد می کند.

به منظور build و راه اندازی تست های نرم افزاری unit test خود بر روی دستگاه مجازی جاوا (JVM)، دستور زیر را فراخوانی کنید.

gradle test

حال جهت کامپایل، build و راه اندازی تست های مبتنی بر instrumentation خود بر روی دستگاه واقعی اندروید، دستور زیر را اجرا نمایید.

gradle connectedCheck

حذف منابع و کلاس های غیرضروری جاوا با روش بهینه سازی منابع یاresource shrinking

سیستم کامپایل و build پروژه Gradle، قادر است با استفاده از روش بهینه سازی منابع (resource shrinking) در زمان کامپایل و build پروژه، کلاس ها و منابع غیرضروری جاوا را حذف نماید. بدین معنی که منابع بلااستفاده از پکیج اپلیکیشن به صورت خودکار حذف می شوند. علاوه بر آن، تمامی منابع غیرضروری از کتابخانه هایی که مورد استفاده ی پروژه هستند، حذف شده حجم نرم افزار به طور قابل توجهی کاهش می یابد.

به منظور فعال سازی قابلیت بیهنه سازی منابع (resource shrinking)، محتوای فایل build خود را به صورت زیر ویرایش کنید.

android {
    ...
    buildTypes {
        release {
            minifyEnabled true
            shrinkResources true
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

تعریف dependency ها و اعلان ورژن کتابخانه های لازم خارج از بدنه ی بستار (closure) dependencies

یک روش بهینه که استفاده از آن بسیار توصیه می شود، تعریف ورژن نیازمندی های کتابخانه ی خود (library dependencies) خارج از بدنه ی بستار (closure) dependencies می باشد. بدین وسیله نگهداشت و maintenance به غایت آسان تر می شود.

ext {
    // App dependencies
    junitVersion = '4.12'
    mockitoVersion = '1.10.19'
    powerMockito = '1.6.2'
    hamcrestVersion = '1.3'
}
dependencies {
    // Dependencies for local unit tests
    testCompile "junit:junit:$junitVersion"
    testCompile "org.mockito:mockito-all:$mockitoVersion"
    testCompile "org.hamcrest:hamcrest-all:$hamcrestVersion"
    testCompile "org.powermock:powermock-module-junit4:$powerMockito"
    testCompile "org.powermock:powermock-api-mockito:$ext.powerMockito"
}
توجه :

پس از قرار دادن بستار ext داخل فایل build اصلی (root)، می توانید، برای مثال، با پارامتر '$rootProject.ext.junitVersion' به راحتی به property ها و خواص آن دسترسی داشته باشید.

build و کامپایل ورژن های (flavor) مختلف از اپلیکیشن اندرویدی خود

انواع build (build flavor)

به طور پیش فرض، اندروید دو نوع build دارد: debug (ورژن debug دربردارنده ی کد برای اشکال زدایی و مقداری گزارش یا logging) و release (ورژن آماده و بهینه سازی شده برای اجرا). برای این انواع build، می توانید flavor های مختلف در Gradle build ایجاد نمایید (build دو ورژن دارد که هر دو یک نسخه از اپلیکیشن هستند، اما flavor برای سرویس گیرنده و مشتری های مختلف تولید می شوند مانند نسخه ی پولی و رایگان از یک اپلیکیشن).

سیستم Gradle build قادر است flavor های مختلفی از یک اپلیکیشن تولید و مدیریت کند. product flavor بیانگر یک ورژن اختصاصی از اپلیکیشن می باشد. این امر امکانی را فراهم می کند تا بخش هایی از codebase یا منابع مورد استفاده ی پروژه برای نسخه های مختلف اپلیکیشن مورد نظر متفاوت باشد.

برای مثال، می توانید برای انواع دستگاه ها همچون گوشی یا تبلت (device category)، ورژن های مختلف (build varaint) تولید نمایید. به عنوان یک مورد استفاده ی دیگر می توان به نسخه ی پولی و رایگان اپلیکیشن مورد نظر اشاره کرد. همچنین زمانی که قصد دارید به هنگام اجرای تست بر روی اپلیکیشن، منابع و کلاس های متفاوت را بکار ببرید.

تعریف انواع flavor در فایل Gradle build

می توانید با استفاده از بستار productFlavors در محتوای فایل app/build.gradle ، نسخه های مختلف از اپلیکیشن نهایی خود اعلان نمایید.

productFlavors {
    prod {
        applicationId = "com.vogella.android.gradlebuildflavors.prod"
        versionName = "1.0-paid"
    }
    mock {
        applicationId = "com.vogella.android.gradlebuildflavors.mock"
        versionName = "1.0-free"
    }
}

محتوای کل فایل build.gradle ممکن است ظاهری مشابه زیر داشته باشد.

apply plugin: 'com.android.application'
android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.exam.gradleexamples"
        minSdkVersion 19
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
        prod {
            applicationId = "com.vogella.android.gradlebuildflavors.prod"
            versionName = "1.0-paid"
        }
        mock {
            applicationId = "com.vogella.android.gradlebuildflavors.mock"
            versionName = "1.0-free"
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
    testCompile 'junit:junit:4.+'
}

پس از اعلان flavor و ورژن های مختلف از اپلیکیشن، می توانید داخل محیط کاری Android Studio، تمامی ورژن های مختلف از اپلیکیشن خود را در کادر Build Variants مشاهده و انتخاب نمایید.

تعریف flover در فایل Gradle Build

ارائه ی منابع مختلف برای flavor ها و ورژن های مختلف اپلیکیشن

به منظور تعریف قابلیت و امکانات مختلف برای flavor مورد نظر، می بایست پوشه های مختلفی برای flavor های مشخص شده در پوشه ی app/src/ ایجاد نمایید.

منابع مختص به هر flavor، منابع کلی و اصلی را بازنویسی می کند. به طور مثال، زمانی یک آیکون متفاوت برای flavor معین تعیین کرده باشید، سیستم build و کامپایل Android، آن آیکونی که ویژه ی flavor مورد نظر تعریف شده را به عنوان آیکون اپلیکیشن انتخاب می کند.

تعریف source set های متفاوت برا flavor های مختلف از اپلیکیشن

دایرکتوری های مقیم در پوشه ی src/ در اصطلاح source sets شناخته می شود. هر flavor از نرم افزار می تواند source set اختصاصی خود را داشته باشد.

لازم به ذکر است که code file ها (فایل های حاوی کدهای جاوا) مانند resource ها و منابع پروژه جایگزین نمی شوند، بلکه با یکدیگر ادغام می گردند. به طور مثال، شما نمی توانید در یک flavor از اپلیکیشن خود اکتیویتی com.example.MainActivity را در پوشه ی app/main/java/ داشته و در flavor دیگر، نسخه ی پیاده سازی شده ی دیگری از activity مزبور داشته باشید. در صورتی که دو نسخه ی پیاده سازی شده از activity داشته باشید، یک پیغام خطا در خصوص وجود کلاس های تکراری (duplicate class) صادر می شود.

با این وجود می توانید با جلوگیری از ایجاد کلاس در source folder اصلی پروژه و سپس ایجاد یک کلاس مجزا در هر flavor، برای هر flavor از اپلیکیشن خود نسخه ی پیاده سازی شده ی متفاوتی از یک کلاس (برای مثال activity) داشته باشید.

تمرین: ساخت اپلیکیشن های اندرویدی با flavor های مختلف

هدف اصلی از این تمرین

در تمرین جاری، یک اپلیکیشن اندرویدی با دو flavor مختلف به ترتیب به نام های prod و mock ایجاد می کنید.

نسخه ی mock منابع متفاوتی از نسخه ی prod مورد استفاده قرار می دهد. در نمونه ی اول، فایل strings.xml مستقر در folder/project بازنویسی (override) می شود. اینکه کدام ورژن build باشد، از طریق کادر Build Variants قابل تعریف است.

ساخت پروژه ی جدید اندروید

یک پروژه ی جدید بر اساس قالب آماده (template) Empty Activity و با اسم پکیج com.vogella.android.gradlebuildflavors ایجاد نمایید.

دو flavor جدید در فایل app/build.gradle به نام های "prod" و "mock" تعریف کنید.

apply plugin: 'com.android.application'
android {
    compileSdkVersion 22
    buildToolsVersion "22.0.1"
    defaultConfig {
        applicationId "com.exam.gradleexamples"
        minSdkVersion 19
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    productFlavors {
        prod {
            applicationId = "com.vogella.android.gradlebuildflavors.prod"
            versionName = "1.0-paid"
        }
        mock {
            applicationId = "com.vogella.android.gradlebuildflavors.mock"
            versionName = "1.0-free"
        }
    }
}
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:22.0.0'
    testCompile 'junit:junit:4.+'
}

ساختار درختی پوشه ها (folder structure) برای دو flavor نام برده را ایجاد نمایید. اگر Android resource directory را انتخاب کنید، در آن صورت می توانید flavor مورد نظر را در پنجره ی محاوره ای زیر، همانند تصویر حاضر، انتخاب نمایید.

ایجاد Flover های جدید

فایل strings.xml را از پوشه ی main به پوشه ی مناسب از flavor مربوطه کپی کرده و جایگذاری نمایید.

مقدار متغیر رشته ای hello_world از فایل strings.xml را برای هر flavor به ترتیب به مقدارهای Mock World! و Prod World! تغییر دهید.


Flavor
Mock World! 


Flavor
Prod World! 

ایجاد Flover

اعتبارسنجی و تست پروژه

در کادر Build Variant محیط کاری Android Studio، گزینه ی mockDebug را انتخاب کرده و اپلیکیشن را جهت تست اجرا نمایید.

اعتبارسنجی

زمانی که اپلیکیشن را اجرا می کنید، می بایست رشته ی مربوطه (Mock World!) را از mock flavor مشاهده نمایید. اکنون prod flavor را انتخاب کرده و اجرا نمایید. مقدار رشته ای مربوطه (Prod Word!) بایستی در نمایشگر قابل مشاهده باشد.

کامپایل و build پروژه از طریق خط دستور Gradle

می توانید با درج دستور ./gradlew build در پنجره ی فرمان، تمامی flavor های اپلیکیشن خود را اجرا نمایید.

تست ورژن یا flavor های مختلف از یک اپلیکشن (gradle flavor های یک اپلیکیشن)

کلاسی به نام ShareIntentBuilder با پیاده سازی زیر ایجاد کنید. این کلاس به وسیله ی یک آبجکت intent که داده ها را به اشتراک می گذارد (share intent) و یک متد static، activity دیگری را راه اندازی می نماید.

import android.content.Context;
import android.content.Intent;
public class ShareIntentBuilder {
    public static void startSendActivity(Context context, String title, String body) {
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEND);
        intent.putExtra(Intent.EXTRA_TITLE, title);
        intent.putExtra(Intent.EXTRA_TEXT, body);
        intent.setType("text/plain");
        Intent chooserIntent = Intent.createChooser(intent, context.getResources().getText(R.string.share));
        chooserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(chooserIntent);
    }

پیاده سازی نسخه های مختلف از کلاس MainActivity در flavor مورد نظر از اپلیکیشن

اجازه دهید activity ای که این آبجکت intent را در سطح خود تعریف کرده و به عنوان پارامتر به بیرون ارسال می کند، در mock flavor جایگزین گردد. چنانچه flavor “mock” انتخاب شده بود، یک activity دیگر راه اندازی کنید که داده های ارسالی را نمایش می دهد. در صورتی که “prod” flavor انتخاب شده باشد، intent مشترک بین دو activity را ارسال کنید.

توجه :

لازم به ذکر است که کلاس ها قابل بازنویسی نیستند. شما بایستی کلاس ها را در flavor های ویژه ی هر یک و نه در flavor اصلی ایجاد کنید.

تنظیم اختصاصی فایل Gradle build

ویرایش اسم فایل apk خروجی

ویرایش اسم فایل apk خروجی

تعریف keystore مجزا برای debug build

می توانید در فایل build.gradle خود یک keystore مجزا تعریف نمایید (keystore: برای درج امضای خالق یک پروژه ی اندرویدی بر روی فایل APK خروجی از keystore استفاده می شود). برای مشاهده ی جزئیات بیشتر به آدرس http://tools.android.com/tech-docs/new-build-system/user-guide مراجعه فرمایید.

به طور مثال می توانید Keystore را ویژه ی نسخه ی debug اپلیکیشن مورد نظر به صورت زیر ویرایش نمایید.

android {
    signingConfigs {
        debug {
            storeFile file("your.keystore")
        }
    }
}

انتقال / migrate کردن یک پروژه ی خروجی گرفته شده از محیط Eclipse به Gradle

وارد کردن (import) یک پروژه ی خروجی گرفته شده از Eclipse در محیط کاری Android Studio

پروژه های اندرویدی به دو روش متفاوت (با دو نحوه ی تنظیم و پیکربندی) سازمان دهی می شوند: 1. یک روش پیکربندی قدیمی که تا سال 2013 توسط ابزار ساخت و توسعه ی اپلیکیشن های اندرویدی محیط کاریEclipse (Eclipse ADT) استفاده می شد 2. دیگری از ساختار درختی جدید برای سازماندهی پروژه به نام Gradle build structure استفاده می کند. می توان سیستم Gradle را طوری تنظیم کرد که از هر دو فرمت ذکر شده برای پیکربندی پروژه استفاده کند.

پس از اینکه فایل Gradle مورد نیاز را به پروژه ی اندرویدی خروجی گرفته شده از Eclipse اضافه نمودید، می توانید پروژه ی خود را وارد محیط برنامه نویسی Android Studio کنید. برای این منظور کافی است داخل محیط مزبور، بر روی File از منوی اصلی کلیک کرده و گزینه ی Import Project را انتخاب نمایید. سپس پوشه ی پروژه و فایل Gradle build مربوطه را انتخاب کنید.

اضافه کردن فایل Gradle به پروژه ی اندرویدی که از محیط Eclipse خروجی گرفته شده است

برای نیل به این هدف، فایل build.gradle خود را به پوشه ی اصلی (root) پروژه اضافه نمایید.

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.0-beta3'
    }
}
apply plugin: 'com.android.application'
android {
     lintOptions {
          abortOnError false
      }
    compileSdkVersion 22
    buildToolsVersion "21.1.2"
                defaultConfig {
                        targetSdkVersion 22
                }
    sourceSets {
        main {
            manifest.srcFile 'AndroidManifest.xml'
            java.srcDirs = ['src']
            resources.srcDirs = ['src']
            aidl.srcDirs = ['src']
            renderscript.srcDirs = ['src']
            res.srcDirs = ['res']
            assets.srcDirs = ['assets']
        }
        // Move the build types to build-types/
        // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
        // This moves them out of them default location under src//... which would
        // conflict with src/ being used by the main source set.
        // Adding new build types or product flavors should be accompanied
        // by a similar customization.
        debug.setRoot('build-types/debug')
        release.setRoot('build-types/release')
    }
}
1396/01/20 6497 2075
رمز عبور : tahlildadeh.com یا www.tahlildadeh.com
نظرات شما

نظرات خود را ثبت کنید...